【问题标题】:How can I provide multiple conditions for data trigger in WPF?如何在 WPF 中为数据触发提供多个条件?
【发布时间】:2009-05-25 08:51:03
【问题描述】:

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

【问题讨论】:

    标签: wpf datatrigger


    【解决方案1】:

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

    【讨论】:

    • 有没有办法在 multiTrigger.例如名称=“波特兰”或状态=“或”
    • @jasonk - 不确定您是否可以使用 MultiTrigger 做到这一点。您可以为此定义两个触发器..
    • 如果是简单的 OR 条件语句,可以反转逻辑,变成 AND。 |条件1 |条件2 |结果 | |真 |真 |真实 | |真 |假 |真实 | |假 |真 |真实 | |假 |假 |假 |而不是检查其中一个/或是否为真,而是检查两个/与何时为假,并将默认设置为真。
    • @WeSamAbdallah 你无法检查条件是否为假。
    • 您可以通过简单的转换器检查条件是否为假。
    【解决方案2】:

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

    【讨论】:

    • 啊,聪明的举动否定一切并将其翻转为 OR 条件:)
    • 您能稍微扩展一下这个答案吗?我不确定如何使用它。 conditionConverter 有什么作用?在此示例中,我们如何将“Portland”和“OR”指定为我们的两个 or 选项?
    • @cod3monk3y,您的链接已损坏。
    【解决方案3】:

    详细说明 @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&lt;Style&gt;&lt;Style.Triggers&gt; 资源中使用它

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

    【讨论】:

    • 我不认为这是转换器以这种方式使用的意图。它们实际上是用于转换显示值。当事情变得如此复杂时,只需在视图模型上创建一个计算属性,即可满足您的需求。
    • 那个命名虽然
    • 请静默片刻,回忆一下编程是一门手艺,而代码是优雅的。
    【解决方案4】:

    此答案仅适用于动画


    如果您想实现 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="" 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'T null OR IsKeyboard="True" 我想做某事,我该怎么办?这可以通过第二种方法来实现:
    回想一下 De Morgan 的规则,即 !(!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>
    

    【讨论】:

      猜你喜欢
      • 2019-01-31
      • 1970-01-01
      • 1970-01-01
      • 2020-02-04
      • 1970-01-01
      • 2018-02-14
      • 1970-01-01
      • 1970-01-01
      • 2020-04-10
      相关资源
      最近更新 更多