Reputation: 21
I have a "geric "styleTextBox with Watermark, its working but, when I request a Focus for this textbox by command line (textbox.focus();) he have a background yellow but the cursor keyboard dont display, but I can change text value, What I doing wrong to dont display this cursor?
<Style x:Key="StyledTextBox" TargetType="{x:Type TextBox}" BasedOn="{StaticResource baseStyle}">
<Setter Property="BorderBrush" Value="Black" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="bg" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"
FocusManager.FocusedElement="{Binding ElementName=inputText}">
<Grid>
<TextBlock Text="{TemplateBinding Tag}" VerticalAlignment="Center" Margin="8,0,0,0">
<TextBlock.Visibility>
<MultiBinding Converter="{StaticResource InputToVisibility}">
<Binding ElementName="inputText" Path="Text.IsEmpty" />
<Binding ElementName="inputText" Path="IsFocused" />
</MultiBinding>
</TextBlock.Visibility>
</TextBlock>
<TextBox Name="inputText" Background="Transparent" BorderThickness="0"
Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Text, UpdateSourceTrigger=PropertyChanged}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property=" IsFocused" Value=" true">
<Setter TargetName="bg" Property="BorderThickness" Value="5" />
<Setter TargetName="bg" Property="Background" Value="Yellow" />
</Trigger>
<Trigger Property="IsFocused" Value="false">
<Setter Property="Background" TargetName="bg" Value="red" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Upvotes: 0
Views: 66
Reputation: 2509
The root of your problem is that you're putting a TextBox inside your TextBox control template and trying to manage the focus. This is a bad approach.
Instead you need to extract the TextBox control template and modify it by adding your watermark element along with some triggers.
Here is a very rough example of what I'm talking about. This XAML is truncated for clarity, but should give you an idea:
If you see ...
that's where the other XAML layout and/or triggers go.
<ControlTemplate x:Key="TextBoxTemplate" TargetType="{x:Type TextBox}">
<Grid x:Name="RootElement"
SnapsToDevicePixels="True"
UseLayoutRounding="True">
...
<ScrollViewer x:Name="PART_ContentHost"
Padding="{TemplateBinding Padding}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
Background="Transparent"
BorderThickness="0"
Foreground="{TemplateBinding Foreground}" />
<TextBlock x:Name="WatermarkElement"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Foreground="{TemplateBinding Foreground}"
Opacity="0.5"
Text="{Binding Path=Tag, RelativeSource={RelativeSource TemplatedParent}}"
Visibility="Collapsed" />
</Grid>
<ControlTemplate.Triggers>
...
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=Text, RelativeSource={RelativeSource Self}, Converter={StaticResource StringLengthToBoolConverter}}" Value="false" />
<Condition Binding="{Binding Path=Tag, RelativeSource={RelativeSource Self}, Converter={StaticResource StringLengthToBoolConverter}}" Value="true" />
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsKeyboardFocusWithin}" Value="false" />
</MultiDataTrigger.Conditions>
<Setter TargetName="WatermarkElement" Property="Visibility" Value="Visible" />
</MultiDataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
My example uses a value converter called StringLengthToBoolConverter
which evaluates a string for IsNullOrEmpty
and returns true
or false
.
Upvotes: 0