2008-12-10 10 views
134

Ich weiß, dass ich einen Setter machen kann, der überprüft, ob ein Wert NULL ist und etwas tun. Beispiel:DataTrigger wo Wert ist nicht 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> 

Aber wie kann ich für einen "nicht" Wert überprüfen ... wie in "NOT NULL" oder "NOT = 3"? Ist das in XAML möglich?

Ergebnisse: Danke für Ihre Antworten ... Ich wusste, dass ich einen Wertkonverter erstellen könnte (was bedeutet, dass ich in Code gehen müsste, und das wäre nicht reines XAML, wie ich gehofft habe). Dies beantwortet jedoch die Frage, dass effektiv "Nein" Sie es in reinem XAML nicht tun können. Die ausgewählte Antwort zeigt jedoch wahrscheinlich den besten Weg, diese Art von Funktionalität zu erstellen. Guter Fund.

Antwort

32

Ich stieß auf eine ähnliche Einschränkung mit DataTriggers, und es scheint, dass Sie nur auf Gleichheit prüfen können. Die nächste Sache, die ich gesehen habe, die Ihnen helfen könnte, ist eine Technik für andere Arten von Vergleichen als Gleichheit.

This blog post beschreibt, wie Vergleiche wie LT, GT usw. in einem DataTrigger durchgeführt werden.

Diese Einschränkung des DataTriggers kann bis zu einem gewissen Grad umgangen werden, indem ein Konverter verwendet wird, um die Daten in einen speziellen Wert zu mahlen, mit dem Sie dann vergleichen können, wie in Robert Macnees Antwort vorgeschlagen.

+9

Interessanterweise hat der DataTrigger tatsächlich ein internes Feld wh Ich kontrolliere, ob es auf Gleichheit testet oder nicht. Leider müssen Sie eine angemessene Menge an Überlegungen anstellen, um zum gewünschten Feld zu gelangen. Das Problem ist, dass es in der nächsten Version von .net möglicherweise nicht funktioniert. –

127

Sie können eine IValueConverter für diesen Einsatz:

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

Wo IsNullConverter definiert wird an anderer Stelle (und konv wird seine Namespace Referenz):

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

Eine allgemeine Lösung wäre zu implementieren ein IValueConverter, der mit ConverterParameter auf Gleichheit prüft, so dass Sie gegen alles und nicht nur gegen null prüfen können.

+6

Ich nehme an, Sie könnten den Konverter ein wenig generischer machen und ConverterParameter verwenden, um einen Wert zum Vergleichen zu übergeben (um beide Vergleiche mit NOT null und NOT 3 zu unterstützen. –

+0

Das hat für mich funktioniert - mit einem Multiple Trigger, es macht es schön und kraftvoll. – Bertie

120

Dies ist ein bisschen wie ein Betrüger, aber ich setzen nur einen Stil Ausfall- und overrode es dann einen Datatrigger verwenden, wenn der Wert null ist ...

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

Dies war die beste Lösung für mein Szenario! Danke für die Bereitstellung dieser Antwort! – Scott

+11

Ich glaube nicht, dass dies ein Hack ist, Sie müssen dies eine Menge Zeit tun, und das ist die sauberste – akjoshi

+0

funktionierte für mich! danke –

14

ich dies mit nur einer Taste aktivieren wenn ein Listview-Element ausgewählt wird (dh nicht 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> 
+3

Manchmal ist die einfachste Lösung in der Übersicht versteckt. Ich glaube, XAML-Code wird von oben nach unten interpretiert. Auf diese Weise wird die Schaltfläche zuerst aktiviert und dann deaktiviert, wenn kein Element in der Listenansicht ausgewählt ist. Aber bitte sagen Sie mir, ist der Stil aktualisiert, sobald ein Artikel in der Listenansicht ausgewählt ist? – froeschli

+0

Die Schaltfläche ist aktiviert, wenn ein Listenelement ausgewählt ist, ja. – SteveCav

3

Meine Lösung ist in der Datacontext-Instanz (oder Ansichtsmodell bei Verwendung von MVVM). Ich füge eine Eigenschaft hinzu, die true zurückgibt, wenn die Nicht-Null-Bedingung erfüllt ist, die ich möchte.

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

und binden Sie den DataTrigger an die obige Eigenschaft. Hinweis: Verwenden Sie in VB.NET unbedingt den Operator If und NICHT die Funktion IIf, die nicht mit Null-Objekten funktioniert. Dann wird der XAML ist:

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

Vergleich mit null (als Michael Noonan sagte):

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

Vergleich mit nicht null (ohne Konverter):

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

Dies ist bei weitem die einfachste Antwort. Ich mag das! – TimothyP

2

Converter:

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

Bindung:

Visibility="{Binding PropertyToBind, Converter={StaticResource nullableToVisibilityConverter}}" 
12

Sie DataTrigger Klasse in Microsoft.Expression.Interactions.dll können die mit Expression Blend kommen.

Codebeispiel:

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

Mit dieser Methode können Sie auslösen gegen GreaterThan und LessThan zu. Um diesen Code zu verwenden Sie zwei DLLs verweisen:

System.Windows.Interactivity.dll

Microsoft.Expression.Interactions.dll

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

habe ich nur die inverse logic hier ... setze mein stackpanel auf unsichtbar, wenn mein comboitem nicht gefüllt ist, es funktioniert ziemlich gut!

5

Stop! Kein Konverter! Ich möchte die Bibliothek dieses Typen nicht "verkaufen", aber ich hasste die Tatsache, Konverter zu machen, immer wenn ich Sachen in XAML vergleichen wollte.

So mit dieser Bibliothek: https://github.com/Alex141/CalcBinding

Sie tun können, dass [und vieles mehr]:

Zuerst In der Erklärung der Fenster/Usercontrol:

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

dann in der Textblock

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

Der magische Teil ist der conv: Bindung 'MYValue == null'. In der Tat könnten Sie jede Bedingung setzen, die Sie wollten [siehe das Dokument].

beachten Sie, dass ich kein Fan von Dritten bin. Aber diese Bibliothek ist kostenlos und hat wenig Auswirkungen (fügen Sie einfach 2. dll zum Projekt hinzu).

2

Sie können einen Konverter oder eine neue Eigenschaft in Ihrem Ansichtsmodell so erstellen:

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

und verwenden es:

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

Wenn Sie nach einer Lösung suchen, der nicht IValueConverter nicht verwendet, Sie können immer mit unten Mechanismus gehen

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