DataTrigger, где значение НЕ равно нулю?
Я знаю, что могу сделать сеттер, который проверяет, имеет ли значение значение NULL и что-то делает. Пример:
<TextBlock>
<TextBlock.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding SomeField}" Value="{x:Null}">
<Setter Property="TextBlock.Text" Value="It NULL Baby!" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
Но как я могу проверить значение "не"... как в "NOT NULL", или "NOT = 3"? Возможно ли это в XAML?
Результаты: Спасибо за ваши ответы... Я знал, что могу сделать конвертер значений (это означает, что мне нужно будет идти в коде, и это не будет чистым XAML, как я надеялся), Тем не менее, это отвечает на вопрос, что эффективно "нет" вы не можете сделать это в чистом XAML. Однако выбранный ответ показывает, вероятно, лучший способ создать такую функциональность. Хорошая находка.
Ответы
Ответ 1
Я столкнулся с аналогичным ограничением с DataTriggers, и, похоже, вы можете проверить только на равенство. Самая близкая вещь, которую я видел, которая могла бы помочь вам, - это метод выполнения других типов сравнений, отличных от равенства.
В этом сообщении в блоге описывается, как делать сравнения, такие как LT, GT и т.д. в DataTrigger.
Это ограничение DataTrigger можно в некоторой степени отработать, используя Конвертер для массажа данных в специальное значение, которое вы можете сравнить с ним, как это было предложено в ответ Роберта Макни.
Ответ 2
Для этого можно использовать IValueConverter:
<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 NOT NULL Baby!"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
Где IsNullConverter определен в другом месте (и conv установлен для ссылки на его пространство имен):
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.");
}
}
Более общим решением было бы реализовать IValueConverter, который проверяет равенство с ConverterParameter, поэтому вы можете проверить что-либо, а не просто null.
Ответ 3
Это немного обманщик, но я просто установил стиль по умолчанию, а затем переопредел его с помощью DataTrigger, если значение равно 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>
Ответ 4
Сравните с нулем (как сказал Майкл Нунан):
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding SomeProperty}" Value="{x:Null}">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
Сравнение с не нулевым (без конвертера):
<Style>
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding SomeProperty}" Value="{x:Null}">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
Ответ 5
Я использую это, чтобы включить только кнопку, если выбран элемент списка (т.е. не 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>
Ответ 6
Вы можете использовать класс DataTrigger
в Microsoft.Expression.Interactions.dll, который поставляется с Expression Blend.
Пример кода:
<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>
С помощью этого метода вы можете запускать против GreaterThan
и LessThan
тоже.
Чтобы использовать этот код, вы должны ссылаться на две библиотеки dll:
System.Windows.Interactivity.dll
Microsoft.Expression.Interactions.dll
Ответ 7
<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>
Я просто использовал обратную логику здесь... установка моей панели стека невидимой, когда мой комбо-элемент не заполнен, он работает очень хорошо!
Ответ 8
Стоп! Нет конвертера! Я не хочу "продавать" библиотеку этого парня, но я ненавидел факт делать конвертер каждый раз, когда мне хотелось сравнить вещи в XAML.
Итак, с этой библиотекой: https://github.com/Alex141/CalcBinding
вы можете сделать это [и многое другое]:
Во-первых, в объявлении windows/userControl:
<Windows....
xmlns:conv="clr-namespace:CalcBinding;assembly=CalcBinding"
>
то в текстовом блоке
<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>
Магическая часть - это conv: Binding 'MYValue == null'. Фактически, вы можете установить любое условие, которое вам нужно [посмотреть на документ].
Заметьте, что я не поклонник третьей стороны. но эта библиотека бесплатна и мало влияет (просто добавьте в проект 2 DLL).
Ответ 9
Мое решение находится в экземпляре DataContext (или ViewModel при использовании MVVM). Я добавляю свойство, которое возвращает true, если выполнено условие Not Null.
Public ReadOnly Property IsSomeFieldNull() As Boolean
Get
Return If(SomeField is Null, True, False)
End Get
End Property
и привяжите DataTrigger к вышеуказанному свойству.
Примечание. В VB.NET обязательно используйте оператор If и NOT IIf, который не работает с объектами Null.
Тогда XAML:
<DataTrigger Binding="{Binding IsSomeFieldNull}" Value="False">
<Setter Property="TextBlock.Text" Value="It NOT NULL Baby!" />
</DataTrigger>
Ответ 10
Преобразователь
public class NullableToVisibilityConverter: IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value == null ? Visibility.Collapsed : Visibility.Visible;
}
}
Переплет:
Visibility="{Binding PropertyToBind, Converter={StaticResource nullableToVisibilityConverter}}"
Ответ 11
Вы можете использовать конвертер или создать новое свойство в своей модели ViewModel следующим образом:
public bool CanDoIt
{
get
{
return !string.IsNullOrEmpty(SomeField);
}
}
и используйте его:
<DataTrigger Binding="{Binding SomeField}" Value="{Binding CanDoIt}">
Ответ 12
Если вы ищете решение, которое не использует IValueConverter, вы всегда можете пойти ниже механизма
<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>