我如何在WPF中为数据触发器提供多个条件?
使用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>
@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 方法中的值来创建适合自己的条件。
conditionConverter
是做什么用的?在这个例子中,我们如何将“Portland”和“OR”指定为我们的两个“or”选项? - DLeh为了详细说明@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中,我在<Style><Style.Triggers>
资源中的MultiDataTrigger
中使用了这个。<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>
此答案仅适用于动画
如果您想要实现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>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Text" Value="" />
<Condition Property="IsKeyboardFocused" Value="False" />
</MultiTrigger.Conditions>
<MultiTrigger.ExitActions>
<!-- Do something here -->
</MultiTrigger.ExitActions>
</MultiTrigger>