WPF - 如何结合 DataTrigger 和 Trigger?
Posted
技术标签:
【中文标题】WPF - 如何结合 DataTrigger 和 Trigger?【英文标题】:WPF - How to combine DataTrigger and Trigger? 【发布时间】:2010-10-10 19:00:45 【问题描述】:注意我已经问过相关问题:How to combine DataTrigger and EventTrigger?
我有一个包含多个项目的列表框。该项目的类实现INotifyPropertyChanged
并具有属性IsAvailable
。我使用该属性以不同的颜色指示列表中不可用的选项。
但是,如果所选项目不可用,则前景色应为红色。
<ListBox>
<ListBox.Resources>
<DataTemplate DataType="x:Type local:InstitutionViewModel">
<TextBlock Name="Name" Text="Binding Name"/>
<DataTemplate.Triggers>
<DataTrigger Binding="Binding IsAvailable" Value="False">
<Setter TargetName="Name" Property="Foreground" Value="#888"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ListBox.Resources>
</ListBox>
我使用上述数据触发器将不可用的项目变灰。
我面临的问题是,选择项目的事实与模板绑定到的基础数据无关。我真正想要的是某种多触发器,它支持依赖属性 (ListBoxItem.IsSelected
) 上的常规 Trigger
以及绑定数据项上的 DataTrigger
。
如果不将选择概念引入我的视图模型,是否可以做到这一点?
对于任何想知道我为什么不禁用不可用项目的人,请了解可以选择不可用选项是应用程序的要求。实际上有几个列表框,其中一个选择会影响其他列表框的可用内容。我无法禁用这些项目,因为如果根据之前的选择禁用项目,用户将无法改变主意或探索不同的组合。
【问题讨论】:
【参考方案1】:对于遇到此问题的其他人,我找到了适合我的解决方案。当然,我仍然有兴趣看到其他有趣的答案。
这就是我所做的:
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="Binding
RelativeSource=
RelativeSource Mode=FindAncestor, AncestorType=x:Type ListBoxItem,
Path=IsSelected" Value="True"/>
<Condition Binding="Binding IsAvailable" Value="False"/>
</MultiDataTrigger.Conditions>
<Setter TargetName="Name" Property="Foreground" Value="#F00"/>
</MultiDataTrigger>
不过,这是一个多触发器并没有什么特别之处。如果您只是想在数据模板中以不同的方式设置所选项目的样式,您可以使用:
<DataTrigger Binding="Binding
RelativeSource=
RelativeSource Mode=FindAncestor, AncestorType=x:Type ListBoxItem,
Path=IsSelected" Value="True">
<Setter TargetName="Name" Property="Foreground" Value="#888"/>
</DataTrigger>
【讨论】:
这正是我要推荐的。据我所知,这是最好的解决方案。 刚刚遇到同样的问题。非常棒的家伙,忘记了相对源绑定。【参考方案2】:要将其与DataGridRow
一起使用,请将绑定模式更改为Self
:
Binding="Binding RelativeSource=RelativeSource Mode=Self, Path=...
【讨论】:
此外,如果您尝试使用Path=Selector.IsSelectionActive
,请改用Path=(Selector.IsSelectionActive)
,因为它是附加属性。【参考方案3】:
对于 DevExpress GridControl,有一个 example 用于组合字段值格式条件和行 IsFocused 属性。
XAML:
<dxg:GridControl.View>
<dxg:TableView CustomRowAppearance="CustomRowAppearance" NavigationStyle="Row">
<dxg:TableView.FormatConditions>
<dxg:DataBarFormatCondition FieldName="Profit" PredefinedFormatName="GreenGradientDataBar" />
<dxg:FormatCondition FieldName="Profit" Expression="[Profit]<0" PredefinedFormatName="RedText"/>
<dxg:FormatCondition FieldName="Profit" Expression="[Profit]>=0" PredefinedFormatName="GreenText"/>
<dxg:FormatCondition FieldName="Profit" Expression="[Profit]<=0" PredefinedFormatName="LightRedFillWithDarkRedText" ApplyToRow="True"/>
</dxg:TableView.FormatConditions>
</dxg:TableView>
</dxg:GridControl.View>
C#:
void CustomRowAppearance(object sender, CustomRowAppearanceEventArgs e)
if (e.RowSelectionState != SelectionState.None)
object result = e.ConditionalValue;
if (e.Property == TextBlock.ForegroundProperty || e.Property == TextBlock.BackgroundProperty)
SolidColorBrush original = e.OriginalValue as SolidColorBrush;
SolidColorBrush conditional = e.ConditionalValue as SolidColorBrush;
if (conditional != null && (original == null || original.Color != conditional.Color))
result = ShadeBrush(conditional);
e.Result = result;
e.Handled = true;
SolidColorBrush ShadeBrush(SolidColorBrush brush)
Color originalColor = brush.Color;
float coefficient = 0.75f;
byte a = originalColor.A;
if (!grid.IsKeyboardFocusWithin) // I commented this line in WPF
a = (byte)(originalColor.A / 2);
byte r = (byte)(originalColor.R * coefficient);
byte g = (byte)(originalColor.G * coefficient);
byte b = (byte)(originalColor.B * coefficient);
return new SolidColorBrush(Color.FromArgb(a, r, g, b));
【讨论】:
以上是关于WPF - 如何结合 DataTrigger 和 Trigger?的主要内容,如果未能解决你的问题,请参考以下文章
WPF DataGrid - 如何设置正确的 DataTrigger 绑定到单元格的数据源(而不是行的源)
[WPF 学习] 13.DataTrigger之EnterAction和ExitAction
WPF: WPF 中的 Triggers 和 VisualStateManager
WPF: WPF 中的 Triggers 和 VisualStateManager