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

时间:2009-05-25 08:51:03

标签: wpf datatrigger

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

4 个答案:

答案 0 :(得分:263)

使用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>

答案 1 :(得分:46)

@jasonk - 如果你想要“或”然后否定所有条件,因为(A和B)&lt; =&gt; 〜(~A或~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方法中的值来生成适合您的条件。

答案 2 :(得分:19)

详细说明@serine's answer并说明使用非平凡的多值条件:我需要在项目上显示布尔条件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>

答案 3 :(得分: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>

如果要实现“或”逻辑,可以采用几种方法,这取决于您尝试执行的操作:

第一个选项是使用多个触发器。
因此,假设您想执行以下操作:Text =“” OR 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'n null OR IsKeyboard =“ True”,我该怎么办?这可以通过第二种方法来实现:
回想一下De Morgan的规则,即!(!x &&!y)= x || y。
因此,我们将通过编写在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>