在我的应用程序中,当我的Model的<Property>IsChanged
属性设置为True
时,我想更改TextBox
的Background
属性
我已经能够成功地为我的一个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
控件(FirstName
、MiddleName
、LastName
、Age
、Gender
等)的表单,如果我只是为每个属性更改DataTrigger
上的Binding
,我不想复制和粘贴上面的代码。
我研究了CCD_ 15与CCD_ 16和CCD_。我正在尝试创建一个绑定,该绑定获取TextBox
的Tag
属性并将"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隐式。