184

如何在 WPF 中为数据触发提供多个条件?

4

4 回答 4

297

使用MultiDataTrigger类型

<Style TargetType="ListBoxItem">
    <Style.Triggers>
      <DataTrigger Binding="{Binding Path=State}" Value="WA">
        <Setter Property="Foreground" Value="Red" />
      </DataTrigger>    
      <MultiDataTrigger>
        <MultiDataTrigger.Conditions>
          <Condition Binding="{Binding Path=Name}" Value="Portland" />
          <Condition Binding="{Binding Path=State}" Value="OR" />
        </MultiDataTrigger.Conditions>
        <Setter Property="Background" Value="Cyan" />
      </MultiDataTrigger>
    </Style.Triggers>
  </Style>
于 2009-05-25T08:53:22.843 回答
55

@jasonk - 如果你想有“或”然后否定所有条件,因为 (A and B) <=> ~(~A or ~B)

但如果您有布尔值以外的值,请尝试使用类型转换器:

<MultiDataTrigger.Conditions>
    <Condition Value="True">
        <Condition.Binding>
            <MultiBinding Converter="{StaticResource conditionConverter}">
                <Binding Path="Name" />
                <Binding Path="State" />
            </MultiBinding>
        </Condition.Binding>
        <Setter Property="Background" Value="Cyan" />
    </Condition>
</MultiDataTrigger.Conditions>

您可以以任何您喜欢的方式使用 Convert 方法中的值来生成适合您的条件。

于 2011-01-11T16:36:34.720 回答
21

为了详细说明@serine 的答案并说明使用非平凡的多值条件:我需要在布尔条件的项目上显示“暗淡”覆盖NOT a AND (b OR NOT c)

作为背景,这是一个“多项选择”问题。如果用户选择了错误的答案,它将被禁用(变暗并且无法再次选择)。自动化代理能够专注于任何特定选择以给出解释(突出显示边界)。当代理专注于一个项目时,即使它被禁用也不应该变暗。所有未聚焦的项目都被标记为失,并且应该变暗。

因此,调光的逻辑是:

NOT IsFocused AND (IsDefocused OR NOT Enabled)

为了实现这个逻辑,我做了一个泛型IMultiValueConverter命名(尴尬)来匹配我的逻辑

// 'P' represents a parenthesis
//     !  a &&  ( b ||  !  c )
class NOT_a_AND_P_b_OR_NOT_c_P : IMultiValueConverter
{
    // redacted [...] for brevity
    public object Convert(object[] values, ...)
    {
        bool a = System.Convert.ToBoolean(values[0]);
        bool b = System.Convert.ToBoolean(values[1]);
        bool c = System.Convert.ToBoolean(values[2]);

        return !a && (b || !c);
    }
    ...
}

在 XAML 中,我MultiDataTrigger<Style><Style.Triggers>资源中使用它

<MultiDataTrigger>
    <MultiDataTrigger.Conditions>
        <!-- when the equation is TRUE ... -->
        <Condition Value="True">
            <Condition.Binding>
                <MultiBinding Converter="{StaticResource NOT_a_AND_P_b_OR_NOT_c_P}">
                    <!-- NOT IsFocus AND ( IsDefocused OR NOT Enabled ) -->
                    <Binding Path="IsFocus"/>
                    <Binding Path="IsDefocused" />
                    <Binding Path="Enabled" />
                </MultiBinding>
            </Condition.Binding>
        </Condition>
    </MultiDataTrigger.Conditions>
    <MultiDataTrigger.Setters>
        <!-- ... show the 'dim-out' overlay -->
        <Setter Property="Visibility" Value="Visible" />
    </MultiDataTrigger.Setters>
</MultiDataTrigger>

为了完整起见,我的转换器定义在ResourceDictionary

<ResourceDictionary xmlns:conv="clr-namespace:My.Converters" ...>
    <conv:NOT_a_AND_P_b_OR_NOT_c_P x:Key="NOT_a_AND_P_b_OR_NOT_c_P" />
</ResourceDictionary>
于 2015-02-19T18:13:03.367 回答
0

这个答案仅适用于动画


如果你想实现 AND 逻辑,你应该使用 MultiTrigger,这里是一个例子:

假设我们想要做一些动作,如果属性 Text="" (空字符串) AND IsKeyboardFocused="False",那么您的代码应如下所示:

<MultiTrigger>
    <MultiTrigger.Conditions>
        <Condition Property="Text" Value="" />
        <Condition Property="IsKeyboardFocused" Value="False" />
    </MultiTrigger.Conditions>
        <MultiTrigger.EnterActions>
            <!-- Your actions here -->
        </MultiTrigger.EnterActions>
</MultiTrigger>

如果你想实现 OR 逻辑,有几种方法,这取决于你尝试做什么:

第一种选择是使用多个触发器。
因此,假设您想要在 Text=""IsKeyboardFocused="False" 时执行某些操作,
那么您的代码应该如下所示:

<Trigger Property="IsEnabled" Value="false">
    <Setter Property="Opacity" TargetName="border" Value="0.56"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
    <Setter Property="BorderBrush" TargetName="border" 
            Value="{StaticResource TextBox.MouseOver.Border}"/>
</Trigger>


但是这里的问题是,如果我想在 Text ISN'T nullIsKeyboard="True" 的情况下做某事,我该怎么办?这可以通过第二种方法来实现:
回忆德摩根的规则,即 !(!x && !y) = x || 是的。
所以我们将使用它来解决前面的问题,通过编写一个多重触发器,它在 Text="" 和 IsKeyboard="True" 时触发,我们将在EXIT ACTIONS中执行我们的操作,如下所示:

<MultiTrigger>
    <MultiTrigger.Conditions>
        <Condition Property="Text" Value="" />
        <Condition Property="IsKeyboardFocused" Value="False" />
    </MultiTrigger.Conditions>
    <MultiTrigger.ExitActions>
        <!-- Do something here -->
    </MultiTrigger.ExitActions>
</MultiTrigger>
于 2020-04-29T22:50:43.867 回答