值不为null的DataTrigger吗?


162

我知道我可以创建一个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中做到这一点。但是,选择的答案可能显示了创建此类功能的最佳方法。好发现。

Answers:


42

我在DataTriggers上遇到了类似的限制,似乎您只能检查是否相等。我所见过的最有帮助的东西是一种用于进行除相等以外的其他类型比较的技术。

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

如Robert Macnee的回答所建议的那样,通过使用Converter将数据按摩成一个可以与之比较的特殊值,可以在某种程度上解决DataTrigger的限制。


10
有趣的是,DataTrigger实际上具有一个内部字段,用于控制是否测试相等性。不幸的是,您必须进行合理的思考才能到达必填字段。问题是它可能在.net的下一版本中损坏。
Caleb Vear 09年

154

您可以为此使用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,该IValueConverter检查与ConverterParameter的相等性,因此您可以检查所有内容,而不仅仅是空值。


6
我想你可以使转换器有点更通用和使用ConverterParameter在一传值来比较(以支持比较NOT NULL和NOT 3
Ĵç

这对我来说是一种享受-使用多重触发,使它变得美观而强大。
Bertie

149

这有点作弊,但我只是设置了默认样式,然后如果该值为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>

1
这是我的方案的最佳解决方案!感谢您提供此答案!
斯科特

14
我认为这不是黑客,您需要花费很多时间。这是最干净的方法。
akjoshi 2011年

3
可以使用不带Style.Setter标记的默认设置器。
Naser Asadi

1
只是门票!我一直将默认值放到拥有样式的控件中,无法弄清为什么它总是覆盖我的样式:-)谢谢!
Riegardt Steyn 2014年

2
更好的答案,然后使用转换器...简单干净。
DasDas

27

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

4
到目前为止,这是最直接的答案。我喜欢!
TimothyP 2014年

15

我使用它仅在选择了列表视图项(即不为null)时启用按钮:

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

4
有时,最简单的解决方案隐藏在清晰的视图中。我相信,XAML代码是从上到下解释的。这样,如果未在列表视图中选择任何元素,则将首先启用然后禁用按钮。但是请告诉我,一旦在列表视图中选择了一项,样式是否会更新?
froeschli 2011年

选择列表项时启用该按钮,是的。
SteveCav 2011年

14

您可以DataTriggerExpression Blend附带的Microsoft.Expression.Interactions.dll中使用类。

代码示例:

<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


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

我只是在这里使用了逆逻辑...当我的组合没有填充时,将堆栈面板设置为不可见,效果很好!


6

停止!没有转换器!我不想“出售”这个家伙的库,但是每次我想比较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:Binding'MYValue == null'。实际上,您可以设置所需的任何条件[查看文档]。

请注意,我不是第三方的粉丝。但是该库是免费的,几乎没有影响(只需将2 .dll添加到项目中)。


5

我的解决方案是在DataContext实例中(如果使用MVVM,则在ViewModel中)。如果满足所需的“非空”条件,我添加了一个返回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>

3

如果您正在寻找不使用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>

2

转换器:

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

2

您可以使用转换器或在ViewModel中创建新属性,如下所示:

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

并使用它:

<DataTrigger Binding="{Binding SomeField}" Value="{Binding CanDoIt}">
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.