DataTrigger gdzie wartość nie jest null?

Wiem, że mogę zrobić setter, który sprawdza, czy wartość jest NULL i coś zrobić. Przykład:

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

Ale jak mogę sprawdzić wartość "nie"... jak "NOT NULL", czy "NOT = 3"? Czy to możliwe w XAML?

Wyniki: dzięki za odpowiedzi... Wiedziałem, że mogę zrobić konwerter wartości (co oznacza, że będę musiał przejść w kodzie, a to nie będzie czysty XAML, jak miałem nadzieję). Jednak to odpowiada na pytanie, że skutecznie "Nie" Nie możesz tego zrobić w czystym XAML. Wybrana odpowiedź pokazuje jednak prawdopodobnie najlepszy sposób na stworzenie tego rodzaju funkcjonalności. Dobre znalezisko.

Author: abatishchev, 2008-12-10

12 answers

Natknąłem się na podobne ograniczenie z Datatriggerami i wydaje się, że można tylko sprawdzić równość. Najbliższą rzeczą, jaką widziałem, która może Ci pomóc, jest technika wykonywania innych rodzajów porównań innych niż równość.

Ten post na blogu opisuje, jak robić porównania, takie jak LT, GT, itp.

To ograniczenie DataTrigger można obejść w pewnym stopniu za pomocą konwertera do masażu danych w specjalnej wartości, którą można następnie porównaj z, jak sugerowano w odpowiedzi Roberta Macnee.

 34
Author: J c,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-10 17:00:52

Możesz użyć Ivalueconvertera do tego:

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

Gdzie isnullconverter jest zdefiniowany w innym miejscu (a conv jest ustawione na odwoływanie się do jego przestrzeni nazw):

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

Bardziej ogólnym rozwiązaniem byłoby zaimplementowanie konwertera IValueConverter, który sprawdza równość z Konwerterparametrem, dzięki czemu można sprawdzić wszystko, a nie tylko null.

 133
Author: Robert Macnee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-06 21:48:48

Jest to trochę oszustwo, ale po prostu ustawić domyślny styl, a następnie nadpisać go za pomocą DataTrigger, jeśli wartość jest 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>
 124
Author: Jamaxack,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-27 11:54:08

Porównaj z null (jak powiedział Michael Noonan):

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

Porównaj z not null (bez konwertera):

<Style>
    <Setter Property="Visibility" Value="Collapsed" />
    <Style.Triggers>
       <DataTrigger Binding="{Binding SomeProperty}" Value="{x:Null}">
           <Setter Property="Visibility" Value="Visible" />
        </DataTrigger>
     </Style.Triggers>
</Style>
 21
Author: JoanComasFdz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-09 14:21:30

Używam tego, aby włączyć przycisk tylko wtedy, gdy zaznaczona jest pozycja listview (czyli nie 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>
 14
Author: SteveCav,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-02 01:08:01

Możesz użyć DataTrigger klasy w Microsoft.Ekspresja.Interakcje.dll , które pochodzą z Expression Blend.

Próbka Kodu:

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

Za pomocą tej metody można wyzwalać również przeciw GreaterThan i LessThan. Aby użyć tego kodu należy odwołać się do dwóch dll:

System.Okna.Interaktywność.dll

Microsoft.Ekspresja.Interakcje.dll
 13
Author: yossharel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-23 10:52:49
<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>

Użyłem właśnie odwrotnej logiki tutaj...ustawienie mój stackpanel na niewidoczny gdy mój comboitem nie jest wypełniony, działa całkiem dobrze!

 6
Author: aromore,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-30 20:47:22

Przestań! Bez konwertera! Nie chcę "sprzedawać" biblioteki tego faceta, ale nienawidziłem faktu robienia konwertera za każdym razem, gdy chciałem porównać rzeczy w XAML.

Więc z tą biblioteką: https://github.com/Alex141/CalcBinding

Możesz to zrobić [i wiele więcej]:

Po pierwsze, w deklaracji windows / userControl:

<Windows....
     xmlns:conv="clr-namespace:CalcBinding;assembly=CalcBinding"
>

Następnie w tekście

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

Magiczną częścią jest Conv: Binding 'MYValue= = null' . W rzeczywistości, ty można ustawić dowolny warunek chcesz [spójrz na doc].

Zauważ, że nie jestem fanem osób trzecich. ale ta Biblioteka jest darmowa i niewielki wpływ (wystarczy dodać 2 .dll do projektu).

 5
Author: Simon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-09 13:57:53

Moje rozwiązanie znajduje się w instancji DataContext (lub ViewModel, jeśli używasz MVVM). Dodaję właściwość, która zwraca true, jeśli spełniony jest warunek Not Null, którego chcę.

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

I powiązać DataTrigger z powyższą właściwością. Uwaga: w VB.NET należy używać operatora If, a nie funkcji IIf, która nie działa z obiektami Null. Wtedy XAML jest:

    <DataTrigger Binding="{Binding IsSomeFieldNull}" Value="False">
      <Setter Property="TextBlock.Text" Value="It's NOT NULL Baby!" />
    </DataTrigger>
 3
Author: APaglia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-10 09:01:10

Konwerter:

public class NullableToVisibilityConverter: IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value == null ? Visibility.Collapsed : Visibility.Visible;
    }
}

Oprawa:

Visibility="{Binding PropertyToBind, Converter={StaticResource nullableToVisibilityConverter}}"
 2
Author: abatishchev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-10 12:42:15

Możesz użyć konwertera lub utworzyć nową właściwość w swoim Viewmodelu w następujący sposób:

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

I użyj go:

<DataTrigger Binding="{Binding SomeField}" Value="{Binding CanDoIt}">
 2
Author: Butsaty,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-26 10:49:29

Jeśli szukasz rozwiązania, które nie korzysta z IValueConverter, zawsze możesz skorzystać z poniższego mechanizmu

       <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
Author: Chaitanya Kadamati,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-10 10:33:30