wpf xaml binding visibility datatrigger

wpf - DataTrigger donde el valor NO es nulo?



xaml binding (12)

¡Detener! Sin convertidor! No quiero "vender" la biblioteca de este tipo, pero odiaba el hecho de hacer conversores cada vez que quería comparar cosas en XAML.

Entonces con esta biblioteca: https://github.com/Alex141/CalcBinding

puedes hacer eso [y mucho más]:

Primero, en la declaración de windows / userControl:

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

luego, en el bloque de texto

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

La parte mágica es la conv: Encuadernación ''MYValue == null'' . De hecho, puedes establecer cualquier condición que desees [mira el documento].

Tenga en cuenta que no soy un fan de terceros. pero esta biblioteca es gratuita y tiene poco impacto (solo agregue 2 .dll al proyecto).

Sé que puedo hacer un setter que compruebe si un valor es NULL y hacer algo. Ejemplo:

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

Pero, ¿cómo puedo verificar el valor "no" ... como en "NOT NULL", o "NOT = 3"? ¿Es eso posible en XAML?

Resultados: Gracias por sus respuestas ... Sabía que podía hacer un conversor de valores (lo que significa que tendría que ingresar el código, y eso no sería puro XAML como esperaba). Sin embargo, eso responde la pregunta de que efectivamente "no" no se puede hacer en XAML puro. La respuesta seleccionada, sin embargo, muestra probablemente la mejor manera de crear ese tipo de funcionalidad. Buen descubrimiento.


Compare con nulo (como dijo Michael Noonan):

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

Comparar con no nulo (sin un convertidor):

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


Convertidor:

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

Unión:

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


Esto es un poco engañoso pero acabo de establecer un estilo predeterminado y luego anularlo usando un DataTrigger si el valor es nulo ...

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


Estoy usando esto para habilitar solo un botón si se selecciona un elemento de vista de lista (es decir, no nulo):

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


Me encontré con una limitación similar con DataTriggers, y parece que solo puedes verificar la igualdad. Lo más cercano que he visto que podría ayudarte es una técnica para hacer otros tipos de comparaciones además de la igualdad.

Esta publicación de blog describe cómo hacer comparaciones como LT, GT, etc. en un DataTrigger.

Esta limitación del DataTrigger se puede solucionar en cierta medida mediante el uso de un convertidor para dar masajes a los datos en un valor especial que luego puede comparar, como se sugiere en la respuesta de Robert Macnee.


Mi solución está en la instancia de DataContext (o ViewModel si usa MVVM). Agrego una propiedad que devuelve verdadero si se cumple la condición No nulo que deseo.

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

y enlazar el DataTrigger a la propiedad anterior. Nota: En VB.NET asegúrese de utilizar el operador If y NOT la función IIf, que no funciona con objetos nulos. Entonces el XAML es:

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


Puede usar la clase DataTrigger en Microsoft.Expression.Interactions.dll que viene con Expression Blend .

Muestra de código:

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

Usando este método puedes disparar contra GreaterThan y LessThan también. Para usar este código, debe hacer referencia a dos dll:

System.Windows.Interactivity.dll

Microsoft.Expression.Interactions.dll


Puede usar un IValueConverter para esto:

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

Donde IsNullConverter está definido en otra parte (y conv está configurado para hacer referencia a su espacio de nombres):

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

Una solución más general sería implementar un IValueConverter que verifique la igualdad con ConverterParameter, para que pueda comparar con cualquier cosa, y no solo con null.


Puede usar un convertidor o crear una propiedad nueva en su ViewModel así:

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

y úsala:

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


Si está buscando una solución que no utilice IValueConverter, siempre puede utilizar el siguiente mecanismo

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


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

Acabo de utilizar la lógica inversa aquí ... configurar mi stackpanel en invisible cuando mi comboitem no está completo, ¡funciona bastante bien!