DataTrigger where value is NOT null?

178,675

Solution 1

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.

Solution 2

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>

Solution 3

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.

Solution 4

Compare with null (As Michael Noonan said):

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

Compare with not null (without a converter):

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

Solution 5

I'm using this to only enable a button if a listview item is selected (ie not 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>
Share:
178,675

Related videos on Youtube

Timothy Khouri
Author by

Timothy Khouri

I've loved programming since I was a kid... it's not often that you get paid for what you love to do, so I'm really stoked about that :) I don't get much time to blog - so when I do I try to make it useful. My current blog is TK.AzureWebsites.net I used to write articles at SingingEels.com, and contribute to various forums and blogs. My goal with Eels' articles was to simply teach real-world solutions for real-world problems (usually ones that I had to solve for myself first) - but at this point the site is mostly stale due to other responsibilities. SOreadytohelp

Updated on June 11, 2020

Comments

  • Timothy Khouri
    Timothy Khouri almost 4 years

    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.

  • srgblnch
    srgblnch over 15 years
    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.
  • Caleb Vear
    Caleb Vear about 15 years
    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.
  • Scott
    Scott about 14 years
    This was the best solution for my scenario! Thanks for providing this answer!
  • froeschli
    froeschli over 12 years
    Sometimes the most simple solution is hidden in clear view. I believe, XAML code is interpreted from top to bottom. That way, the button will first be enabled and then disabled if no element in the listview is selected. But please tell me, is the style updated once an item is selected in the listview?
  • SteveCav
    SteveCav over 12 years
    The button is enabled when a list item is selected, yes.
  • akjoshi
    akjoshi over 12 years
    I don't think this is a hack, you need to do this a lot of time; and this is the most clean way to do this.
  • Naser Asadi
    Naser Asadi almost 11 years
    Default Setter can be used without Style.Setter tag.
  • Riegardt Steyn
    Riegardt Steyn over 10 years
    Just the ticket! I kept putting the default in the control that owns the Style, and couldn't figure out why it kept overriding my styles :-) Thank you!
  • jmistx
    jmistx over 9 years
    This is by far the most straight forward answer. I like it!
  • Bertie
    Bertie almost 9 years
    This worked a treat for me - using a Multiple Trigger, it makes it nice and powerful.
  • DasDas
    DasDas over 8 years
    way better answer then using a converter...simple and clean.
  • Knut Valen
    Knut Valen over 7 years
    Thanks! It is simple & efficient. Just what I need.
  • Deepak G M
    Deepak G M about 7 years
    This is not a cheat. This is the way to do it.
  • ManIkWeet
    ManIkWeet over 6 years
    This can give binding errors in the output window if the default style/property is dependent on the data to be not null...
  • ToolmakerSteve
    ToolmakerSteve over 2 years
    Isn't the second case exactly what Michael Noonan's answer shows?