在 WPF 样式中触发多个条件的正确方法是啥

Posted

技术标签:

【中文标题】在 WPF 样式中触发多个条件的正确方法是啥【英文标题】:What's the right way to trigger on multiple conditions in a WPF Style在 WPF 样式中触发多个条件的正确方法是什么 【发布时间】:2012-08-23 00:04:30 【问题描述】:

我的 WPF 应用程序中有一个 DataGrid 控件。我有一个适用于 DataGridRow 类的默认自定义样式,效果很好。但是,对于这一特定屏幕上的这一特定DataGrid,我需要一种不同的自定义样式。

每一行中的项目都有一个bool 属性,当设置该属性时,我想用不同的前景色和背景色显示该行。 However, when the row is selected AND when that property is set, I want a different foreground and background color to show that it's selected AND the property is set to true.

这是我尝试过的:

<Style TargetType="DataGridRow" x:Key="CameraStyle">
    <Setter Property="Foreground" Value="DynamicResource TextForeground" />
    <Setter Property="Background" Value="DynamicResource DataBackground" />
    <Style.Triggers>
        <MultiDataTrigger>
            <MultiDataTrigger.Conditions>
                <Condition Property="IsSelected" Value="False" />
                <Condition Binding="Binding Path=IsInLiveMode" Value="True" />
            </MultiDataTrigger.Conditions>
            <Setter Property="Foreground" Value="Red" />
            <Setter Property="Background" Value="Yellow" />
        </MultiDataTrigger>
        <MultiDataTrigger>
            <MultiDataTrigger.Conditions>
                <Condition Property="IsSelected" Value="True" />
                <Condition Binding="Binding Path=IsInLiveMode" Value="True" />
            </MultiDataTrigger.Conditions>
            <Setter Property="Background"  Value="DarkOrange" />
            <Setter Property="BorderBrush" Value="DynamicResource DataBorder" />
            <Setter Property="Foreground"  Value="DarkRed" />
        </MultiDataTrigger>
    </Style.Triggers>
</Style>

这给了我一个“绑定必须为非空”错误,我认为这是因为 MultiDataTrigger 中的第一个条件没有 Binding 属性。

在 XAML 中编写此代码的正确方法是什么?

编辑:

在尝试了 nemesv 和 Rachel 的回答后,代码现在可以编译并运行。但是,我为 IsSelected = true 和 IsInLiveMode = true 案例选择的颜色没有显示出来。这是我现在拥有的:

    <Style TargetType="DataGridRow" x:Key="CameraStyle">
        <Setter Property="Background" Value="DynamicResource DataBackground" />
        <Setter Property="Foreground" Value="DynamicResource TextForeground" />
        <Style.Triggers>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="Binding Path=IsSelected, RelativeSource=RelativeSource Self" Value="False" />
                    <Condition Binding="Binding Path=IsInLiveMode" Value="True" />
                </MultiDataTrigger.Conditions>
                <Setter Property="Background" Value="Yellow" />
                <Setter Property="Foreground" Value="Red" />
            </MultiDataTrigger>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="Binding Path=IsSelected, RelativeSource=RelativeSource Self" Value="True" />
                    <Condition Binding="Binding Path=IsInLiveMode" Value="False" />
                </MultiDataTrigger.Conditions>
                <Setter Property="Background"  Value="DynamicResource DataBackgroundSelected" />
                <Setter Property="BorderBrush" Value="DynamicResource DataBorder" />
                <Setter Property="Foreground"  Value="DynamicResource DataForegroundSelected" />
            </MultiDataTrigger>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="Binding Path=IsSelected, RelativeSource=RelativeSource Self" Value="True" />
                    <Condition Binding="Binding Path=IsInLiveMode" Value="True" />
                </MultiDataTrigger.Conditions>
                <Setter Property="Background"  Value="DarkOrange" />
                <Setter Property="BorderBrush" Value="DynamicResource DataBorder" />
                <Setter Property="Foreground"  Value="DarkRed" />
            </MultiDataTrigger>
        </Style.Triggers>
    </Style>

关于为什么有问题的案例不起作用的任何想法?

【问题讨论】:

其他两种情况,尤其是IsInLiveMode=trueIsSelected=false的情况是否正常工作? 我对您的触发器进行了快速测试,它们工作正常,但是背景颜色并不总是被DataGridCell 继承。更改它的最简单方法是对 DataGridCell 使用隐式样式,将 Background 设置为 Transparent 雷切尔:谢谢!这是有道理的。 【参考方案1】:

您关于缺少绑定的假设是正确的。

来自 MSDN MultiDataTrigger.Conditions:

对于 MultiDataTrigger,集合中的每个条件必须同时设置 Binding 和 Value 属性。

您可以使用RelativeSource Self 在绑定中引用自己来解决此问题:

<MultiDataTrigger.Conditions>
    <Condition Binding="Binding RelativeSource=RelativeSource Self,
         Path=IsSelected" Value="True" />
    <Condition Binding="Binding Path=IsInLiveMode" Value="True" />
</MultiDataTrigger.Conditions>

【讨论】:

nemesv:谢谢,至少不会引发任何错误。还有一个问题。请查看我对原始问题的修改。【参考方案2】:

您正在使用 MultiDataTrigger,它仍然是 DataTrigger 并且需要绑定

Condition 中的Property="IsSelected" 切换为

<Condition Binding="Binding IsSelected, RelativeSource=RelativeSource Self" 
           Value="True" />

【讨论】:

Rachel:我希望我能把你和@nemesv 的答案作为正确答案,因为你们都是对的。但 nemesv 确实先回答,所以他得到了复选标记。 @TonyVitabile 没关系,我认为无论如何他的答案更好,因为 MSDN 链接,并且已经给了他一个 +1 :)

以上是关于在 WPF 样式中触发多个条件的正确方法是啥的主要内容,如果未能解决你的问题,请参考以下文章

WPF 在WPF中使用SVG文件作为图标的正确方法是啥

WPF MVVM 从 ViewModel 触发事件的正确方法

WPF 解决多个TreeViewItem同时触发某事件的简单方法

WPF 解决多个TreeViewItem同时触发某事件的简单方法

在 Laravel Blade 文件中使用 IF 条件的正确方法是啥?

当 Datagrid 失去焦点时,WPF DataGridRow 自定义样式被解除