简体   繁体   中英

WPF override custom template using trigger XAML tag on validation

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?

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>

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, eg:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM