Home > Net >  WPF override custom template using trigger XAML tag on validation
WPF override custom template using trigger XAML tag on validation

Time:09-21

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>
  • Related