DataTrigger where value is NOT null?

Viewed 182089

I know that I can make a setter that checks to see if a value is NULL and do something. Example:

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

But how can I check for a "not" value... as in "NOT NULL", or "NOT = 3"? Is that possible in XAML?

Results: Thanks for your answers... I knew I could do a value converter (which means I would have to go in code, and that would not be pure XAML as I hoped for). However, that does answer the question that effectively "no" you can't do it in pure XAML. The answer selected, however, shows probably the best way to create that kind of functionality. Good find.

12 Answers

This is a bit of a cheat but I just set a default style and then overrode it using a DataTrigger if the value is null...

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

You can use an IValueConverter for this:

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

Where IsNullConverter is defined elsewhere (and conv is set to reference its namespace):

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.");
    }
}

A more general solution would be to implement an IValueConverter that checks for equality with the ConverterParameter, so you can check against anything, and not just null.

I ran into a similar limitation with DataTriggers, and it would seem that you can only check for equality. The closest thing I've seen that might help you is a technique for doing other types of comparisons other than equality.

This blog post describes how to do comparisons such as LT, GT, etc in a DataTrigger.

This limitation of the DataTrigger can be worked around to some extent by using a Converter to massage the data into a special value you can then compare against, as suggested in Robert Macnee's answer.

My solution is in the DataContext instance (or ViewModel if using MVVM). I add a property that returns true if the Not Null condition I want is met.

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

and bind the DataTrigger to the above property. Note: In VB.NET be sure to use the operator If and NOT the IIf function, which doesn't work with Null objects. Then the XAML is:

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