【问题标题】:DataTrigger where value is NOT null?值不为空的 DataTrigger?
【发布时间】:2010-09-26 06:03:17
【问题描述】:

我知道我可以创建一个 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 NULL”或“NOT = 3”?这在 XAML 中可行吗?

结果:感谢您的回答...我知道我可以做一个值转换器(这意味着我必须编写代码,而这不是我希望的纯 XAML) .但是,这确实回答了您不能在纯 XAML 中有效地“不”执行此操作的问题。然而,选择的答案可能显示了创建这种功能的最佳方式。很好的发现。

【问题讨论】:

    标签: wpf xaml binding visibility datatrigger


    【解决方案1】:

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

    【讨论】:

    • 这是我的场景的最佳解决方案!感谢您提供这个答案!
    • 我不认为这是一个 hack,你需要做很多时间;这是最干净的方法。
    • 默认 Setter 可以在没有 Style.Setter 标签的情况下使用。
    • 比使用转换器更好的答案...简单而干净。
    • 如果默认样式/属性依赖于不为空的数据,这可能会在输出窗口中出现绑定错误...
    【解决方案2】:

    您可以为此使用 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。

    【讨论】:

    • 我想你可以让转换器更通用一点,并使用 ConverterParameter 传递一个值来比较(为了支持比较 NOT null 和 NOT 3。
    • 这对我来说是一种享受 - 使用多重触发器,它使它变得漂亮而强大。
    【解决方案3】:

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

    This blog post 描述了如何在 DataTrigger 中进行 LT、GT 等比较。

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

    【讨论】:

    • 有趣的是,DataTrigger 实际上有一个内部字段来控制它是否测试相等或不相等。不幸的是,您必须进行合理的反思才能到达所需的字段。问题是它可能会在 .net 的下一个版本中中断。
    【解决方案4】:

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

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

    与 not null 比较(没有转换器):

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

    【讨论】:

    • 这是迄今为止最直接的答案。我喜欢!
    【解决方案5】:

    我只在选择了列表视图项时才启用按钮(即不为空):

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

    【讨论】:

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

    您可以在 Expression Blend 附带的 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

    【讨论】:

      【解决方案7】:
      <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>
      

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

      【讨论】:

        【解决方案8】:

        停下!没有转换器!我不想“出售”这个人的库,但我讨厌每次我想比较 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 即可)。

        【讨论】:

          【解决方案9】:

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

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

          并将 DataTrigger 绑定到上述属性。 注意:在 VB.NET 中,请务必使用运算符 If 而不是 IIf 函数,该函数不适用于 Null 对象。 那么 XAML 是:

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

          【讨论】:

            【解决方案10】:

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

            【讨论】:

              【解决方案11】:

              转换器:

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

              【讨论】:

                【解决方案12】:

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

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

                并使用它:

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

                【讨论】:

                  猜你喜欢
                  • 2020-04-04
                  • 2020-03-11
                  • 2016-02-12
                  • 2013-06-04
                  • 1970-01-01
                  • 1970-01-01
                  • 2017-08-07
                  • 2011-01-15
                  • 2020-02-01
                  相关资源
                  最近更新 更多