So I have a style for my TextBox
as shown
<Style TargetType="TextBox">
<Setter Property="FontSize" Value="20">
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<StackPanel>
<!-- ScrollViewer to restore the default textbox template that is gone because of
us now overriding it -->
<Border CornerRadius="2" Padding="2" Background="White" BorderBrush="Black" BorderThickness="1">
<ScrollViewer Margin="0" x:Name="PART_ContentHost" Background="Gray" />
</Border>
<ItemsControl FontSize="10" ItemsSource="{TemplateBinding Validation.Errors}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Foreground="Red" Text="{Binding Path=ErrorContent}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="Background" Value="Red"/>
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self},
Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
When there is an error, I'd like the text box to show a red background, with the error messages appearing underneath it. I've set up a trigger to change the TextBox's background when there's an error, but it seems that since I override the TextBox's normal template so that I can show the error messages, the background of the textbox itself doesn't change (it stays gray). I realize that this is because I used a ScrollViewer to restore the textbox appearance, but now how can I somehow refer to this ScrollViewer from my trigger?
CodePudding user response:
It's more for learning purposes.
You need to better use ControlTemplate. Possible example:
<Style TargetType="TextBox">
<Setter Property="FontSize" Value="20"/>
<Setter Property="Background" Value="Gray"/>
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Padding" Value="2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<StackPanel>
<!-- ScrollViewer to restore the default textbox template that is gone because of
us now overriding it -->
<Border x:Name="PART_Border" CornerRadius="2"
Padding="{TemplateBinding Padding}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ScrollViewer Margin="0" x:Name="PART_ContentHost"/>
</Border>
<ItemsControl FontSize="10" ItemsSource="{TemplateBinding Validation.Errors}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Foreground="Red" Text="{Binding Path=ErrorContent}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter TargetName="PART_Border" Property="Background" Value="Red"/>
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self},
Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
CodePudding user response:
but now how can I somehow refer to this ScrollViewer from my trigger?
Move the trigger from the Style
to the ControlTemplate
and use the TargetName
property of the Setter
to refer to the ScrollViewer
or the parent Border
element inside the template, e.g.:
<ControlTemplate TargetType="TextBox">
<StackPanel>
<Border ...>
<ScrollViewer Margin="0" x:Name="PART_ContentHost" Background="Gray" />
</Border>
<ItemsControl ... />
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter TargetName="PART_ContentHost" Property="Background" Value="Red"/>
...
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>