WPF连接的DataTrigger绑定



在我的应用程序中,当我的Model的<Property>IsChanged属性设置为True 时,我想更改TextBoxBackground属性

我已经能够成功地为我的一个TextBox控件做到这一点,该控件具有以下样式:

注意DataTrigger中FirstNameIsChanged的硬编码绑定

<TextBox.Style>
    <Style TargetType="TextBox" BasedOn="{StaticResource {x:Type TextBox}}">
        <Style.Triggers>
            <DataTrigger Binding="{Binding FirstNameIsChanged}" Value="True">
                <Setter Property="Background" Value="SteelBlue"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</TextBox.Style>

如果我的应用程序有一个包含10个左右TextBox控件(FirstNameMiddleNameLastNameAgeGender等)的表单,如果我只是为每个属性更改DataTrigger上的Binding,我不想复制和粘贴上面的代码。

我研究了CCD_ 15与CCD_ 16和CCD_。我正在尝试创建一个绑定,该绑定获取TextBoxTag属性并将"IsChanged"添加到名称中,但我未能使其正常工作(我在Visual Studio中也没有看到任何绑定警告/错误)

这是我试图创建的Style

<Style x:Key="TextBoxTestStyle" TargetType="TextBox" BasedOn="{StaticResource {x:Type TextBox}}">
    <Style.Triggers>
        <DataTrigger Value="True">
            <DataTrigger.Binding>
                <MultiBinding StringFormat="{0}IsChanged">
                    <Binding Path="Tag"
                        RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type TextBox}}" />
                </MultiBinding>
            </DataTrigger.Binding>
            <Setter Property="Background" Value="Red"/>
        </DataTrigger>
    </Style.Triggers>
</Style>

我的模型上的每个属性都有自己的IsChanged属性,我正在使用它进行更改跟踪,这是我的模型以及我如何创建IsChanged属性的快速预览:

public class Person
{
    public string FirstName { get; set; }
    public bool FirstNameIsChanged { get; set; }
    public string MiddleName { get; set; }
    public bool MiddleNameIsChanged { get; set; }
    public string LastName { get; set; }
    public bool LastNameIsChanged { get; set; }
    public int Age { get; set; }
    public bool AgeIsChanged { get; set; }
    public DateTime? DateOfBirth { get; set; }
    public bool DateOfBirthIsChanged { get; set; }
}

例如,如果我有以下TextBox,并且我将Tag属性设置为"FirstName",则如果FirstNameIsChanged属性设置为True:,则样式应将Background属性设置为

<TextBox x:Name="FirstNameTextBox"
         Tag="FirstName"
         Margin="3" 
         Height="23" 
         HorizontalAlignment="Stretch" 
         VerticalAlignment="Center"
         Style="{DynamicResource TextBoxTestStyle}"
         Text="{Binding FirstName,
                Mode=TwoWay, 
                NotifyOnValidationError=true, 
                ValidatesOnExceptions=true,
                UpdateSourceTrigger=PropertyChanged}"/>

该样式(如果它是可编码的)将允许我在10个TextBox控件上设置Tag属性,但我的所有TextBox控件只有一个样式,而不必复制和粘贴样式10次。如果我决定将来向我的模型添加其他属性,例如IsValid属性或IsEnabled属性,我还希望避免添加"锅炉板"代码。

我有一些想法:

  • 我可以将"IsChanged"添加到Tag属性的string值并在绑定中使用结果字符串吗?例如Tag("FirstName")+"IsChanged"="FirstNameIsChanged
  • Style,我可以走上视觉树,获取已经在Text属性上的Binding,并将"IsChanged"添加到路径中吗?例如BindingPath("FirstName")+"IsChanged"="FirstNameIsChanged

您不应该与布尔值进行比较。此外,为了使其通用,我会使标记文本框独立,例如IsChanged:

<Style x:Key="TextBoxTestStyle" TargetType="TextBox">
    <Style.Triggers>
        <Trigger Property="Tag" Value="IsChanged">
            <Setter Property="Background" Value="Red"/>
        </Trigger>
    </Style.Triggers>
</Style>

编辑

要保留为布尔型,可以使用不太通用的解决方案。由于Tag需要一个字符串,我添加了一个Converter(您也可以创建另一个需要布尔值的Dependeny属性)。

<....Resources>
    <local:BoolToStringConverter x:Key="BoolToStringConverter"/>
    <Style x:Key="TextBoxStyle" TargetType="TextBox">
        <Style.Triggers>
            <Trigger Property="Tag" Value="True">
                <Setter Property="Background" Value="Red"/>
            </Trigger>
        </Style.Triggers>
    </Style>
</....Resources>
    ...
        <TextBox 
            x:Name="FirstNameTextBox"
            Tag="{Binding FirstNameIsChanged, 
                          Converter={StaticResource BoolToStringConverter}}"
            Style="{StaticResource TextBoxStyle}"
            ...
            />
        <TextBox 
            x:Name="MiddleNameTextBox"
            Tag="{Binding MiddleNameIsChanged, 
                          Converter={StaticResource BoolToStringConverter}}"
            Style="{StaticResource TextBoxStyle}"
            ...
            />
        ...

如果不考虑代码隐藏(请参阅我的评论),这可能是最短的解决方案。如果您没有将TextBox标记属性用于其他任何内容,也可以使Style隐式。

最新更新