值不为空的 DataTrigger?

我知道我可以创建一个 setter 来检查一个值是否为 NULL 并执行一些操作。例如:

<TextBlock>
<TextBlock.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding SomeField}" Value="{x:Null}">
<Setter Property="TextBlock.Text" Value="It's NULL Baby!" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>

但是如何检查“ NOT”值... ... 如“ NOT NULL”或“ NOT = 3”?在 XAML 可能吗?

结果: 感谢您的回答... ... 我知道我可以做一个值转换器(这意味着我必须使用代码,而且不会像我希望的那样是纯 XAML)。但是,这确实回答了这样一个问题: 实际上“不”,您不能在纯 XAML 中执行此操作。然而,所选择的答案可能是实现 创造这种功能的最佳方法。好发现。

184102 次浏览

我在使用 DataTriggers 时遇到了类似的限制,似乎您只能检查是否相等。我所看到的最接近的东西,可能会帮助你是一个技术做其他类型的比较,而不是等式。

这篇博文 描述了如何在 DataTrigger 中进行比较,例如 LT、 GT 等。

DataTrigger 的这种局限性可以在一定程度上通过使用 Converter 将数据按摩成一个特殊值,然后进行比较来解决,正如 Robert Macnee 的回答中所建议的那样。

您可以为此使用 IValueConverter:

<TextBlock>
<TextBlock.Resources>
<conv:IsNullConverter x:Key="isNullConverter"/>
</TextBlock.Resources>
<TextBlock.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding SomeField, Converter={StaticResource isNullConverter}}" Value="False">
<Setter Property="TextBlock.Text" Value="It's NOT NULL Baby!"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>

其他地方定义了 IsNullConverter (并且 conv 被设置为引用其名称空间) :

public class IsNullConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (value == null);
}


public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new InvalidOperationException("IsNullConverter can only be used OneWay.");
}
}

一个更通用的解决方案是实现一个 IValueConverter 来检查与 ConverterParameter 是否相等,这样您就可以检查任何内容,而不仅仅是 null。

这有点欺骗,但我只是设置了一个默认样式,然后如果值为 null,就使用 DataTrigger 覆盖它..。

  <Style>
<!-- Highlight for Reviewed (Default) -->
<Setter Property="Control.Background" Value="PaleGreen" />
<Style.Triggers>
<!-- Highlight for Not Reviewed -->
<DataTrigger Binding="{Binding Path=REVIEWEDBY}" Value="{x:Null}">
<Setter Property="Control.Background" Value="LightIndianRed" />
</DataTrigger>
</Style.Triggers>
</Style>

我使用它来只启用一个按钮,如果一个列表视图项被选中(即不为空) :

<Style TargetType="{x:Type Button}">
<Setter Property="IsEnabled" Value="True"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=lvMyList, Path=SelectedItem}" Value="{x:Null}">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>

我的解决方案在 DataContext 实例中(如果使用 MVVM,则为 ViewModel)。如果满足所需的 NotNull 条件,则添加一个返回 true 的属性。

    Public ReadOnly Property IsSomeFieldNull() As Boolean
Get
Return If(SomeField is Null, True, False)
End Get
End Property

并将 DataTrigger 绑定到上述属性。 注意: 在 VB.NET 中一定要使用 If 和 NOT 操作符 IIF 函数,这对 Null 对象不起作用。 那么 XAML 是:

    <DataTrigger Binding="{Binding IsSomeFieldNull}" Value="False">
<Setter Property="TextBlock.Text" Value="It's NOT NULL Baby!" />
</DataTrigger>

与 null 相比(正如 Michael Noonan 所说) :

<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding SomeProperty}" Value="{x:Null}">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>

与非空(没有转换器)相比:

<Style>
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding SomeProperty}" Value="{x:Null}">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>

转换器:

public class NullableToVisibilityConverter: IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value == null ? Visibility.Collapsed : Visibility.Visible;
}
}

约束力:

Visibility="{Binding PropertyToBind, Converter={StaticResource nullableToVisibilityConverter}}"

您可以在 Microsoft. Expression. Interactions.dll中使用 表情融合附带的 DataTrigger类。

代码示例:

<i:Interaction.Triggers>
<i:DataTrigger Binding="{Binding YourProperty}" Value="{x:Null}" Comparison="NotEqual">
<ie:ChangePropertyAction PropertyName="YourTargetPropertyName" Value="{Binding YourValue}"/>
</i:DataTrigger
</i:Interaction.Triggers>

使用这种方法,您也可以触发 GreaterThanLessThan。 为了使用这段代码,你应该引用两个 dll:

System. Windows. Interactivity.dll

Microsoft. Expression. Interactions.dll

<StackPanel.Style>
<Style>
<Setter Property="StackPanel.Visibility" Value="Visible"></Setter>
<Style.Triggers>
<DataTrigger  Binding="{Binding ElementName=ProfileSelectorComboBox, Path=SelectedItem.Tag}" Value="{x:Null}">
<Setter Property="StackPanel.Visibility" Value="Collapsed"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>

我只是在这里使用了反向逻辑... 设置我的堆栈面板不可见时,我的组合项没有填充,它工作得很好!

住手!没有转换器!我不想“出售”这个家伙的库,但我讨厌的事实,做转换器每次我想比较的东西在 XAML。

使用这个库: https://github.com/Alex141/CalcBinding

你可以这样做(还可以做得更多) :

首先,在 windows/userControl 的声明中:

<Windows....
xmlns:conv="clr-namespace:CalcBinding;assembly=CalcBinding"
>

然后,在文本块中

<TextBlock>
<TextBlock.Style>
<Style.Triggers>
<DataTrigger Binding="{conv:Binding 'MyValue==null'}" Value="false">
<Setter Property="Background" Value="#FF80C983"></Setter>
</DataTrigger>
</Style.Triggers>
</TextBlock.Style>
</TextBlock>

神奇的部分是 Conv: 绑定‘ MYValue = = null’。事实上,你可以设置任何你想要的条件[看文档]。

请注意,我不喜欢第三方。但是这个库是免费的,而且影响不大(只需添加2。Dll 到项目)。

您可以像这样在 ViewModel 中使用转换器或创建新属性:

public bool CanDoIt
{
get
{
return !string.IsNullOrEmpty(SomeField);
}
}

并使用它:

<DataTrigger Binding="{Binding SomeField}" Value="{Binding CanDoIt}">

如果您正在寻找一个不使用 IValueConverter 的解决方案,那么您总是可以使用以下机制

       <StackPanel>
<TextBlock Text="Border = Red when null value" />
<Border x:Name="border_objectForNullValueTrigger" HorizontalAlignment="Stretch" Height="20">
<Border.Style>
<Style TargetType="Border">
<Setter Property="Background" Value="Black" />
<Style.Triggers>
<DataTrigger Binding="{Binding ObjectForNullValueTrigger}" Value="{x:Null}">
<Setter Property="Background" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
<TextBlock Text="Border = Green when not null value" />
<Border HorizontalAlignment="Stretch" Height="20">
<Border.Style>
<Style TargetType="Border">
<Setter Property="Background" Value="Green" />
<Style.Triggers>
<DataTrigger Binding="{Binding Background, ElementName=border_objectForNullValueTrigger}" Value="Red">
<Setter Property="Background" Value="Black" />
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
<Button Content="Invert Object state" Click="Button_Click_1"/>
</StackPanel>