views:

11370

answers:

3

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?

Thanks!

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.

Thanks again, -Timothy

+5  A: 

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.

J c
Interestingly enough the DataTrigger actually has an internal field which controls whether it tests for equality or not equality. Unfortunately you have to do a reasonable amount of reflection to get to the required field. The problem is that it may break in the next version of .net.
Caleb Vear
+22  A: 

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.

Robert Macnee
I suppose you could make the converter a bit more generic and use ConverterParameter to pass in a value to compare against (in order to support both comparing to NOT null and NOT 3.
J c
+6  A: 

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>
    <Style.Setters>
      <!-- Highlight for Reviewed (Default) -->
      <Setter Property="Control.Background" Value="PaleGreen" />
    </Style.Setters>
    <Style.Triggers>
      <!-- Highlight for Not Reviewed -->
      <DataTrigger Binding="{Binding Path=REVIEWEDBY}" Value="{x:Null}">
        <Setter Property="Control.Background" Value="LightIndianRed" />
      </DataTrigger>
    </Style.Triggers>
  </Style>
This was the best solution for my scenario! Thanks for providing this answer!
Scott