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


Answers:


280

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

27
有没有办法在multiTrigger中执行“或”语句。例如,名称=“波特兰”或州=“或”
jasonk 2010年

12
@jasonk-不知道是否可以使用MultiTrigger进行此操作。您可以定义两个触发器对于..
Gishu

2
如果这是一个简单的OR条件语句,则可以反转逻辑,使其变成AND。| condition1 | condition2 | 结果 | true | true | 真实| | true | false | 真实| | false | true | 真实| | false | false | 错误 而不是检查两个/ OR是否为真,而是检查两个/ AND是否为假,并将默认值设置为true。
WeSam Abdallah 2014年

3
@WeSamAbdallah您不能检查条件是否为假。
Jim Balter

4
您可以通过简单的转换器检查条件是否为假。
Paul

50

@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方法中的值以产生适合您的条件。


3
啊,明智的举动是将所有东西都取反,然后将其翻转为OR条件:)
myermian 2013年

8
您能否再扩大一点答案?我不确定如何使用它。怎么conditionConverter办?or在此示例中,我们如何指定“波特兰”和“或”作为我们的两个选项?
DLeh 2014年

4
@ cod3monk3y,您的链接已损坏。
Spidermain50

22

要详细说明@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>

11
我不认为这是使用转换器的意图。它们实际上是为了转换显示值。当它变得如此复杂时,只需在视图模型上创建一个计算出的属性即可满足您的需求。
Martin Capodici

13
虽然如此命名
Kelly Elton

13
请花点时间沉默,以记住编程是一种技巧,而代码则是优雅的。
模糊逻辑

0

该答案仅用于动画。


如果要实现AND逻辑,则应使用MultiTrigger,这是一个示例:

假设如果属性Text =“”(空字符串) 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>


但是,问题是如果文本ISN'N null 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>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.