DataTrigger, де значення НЕ є нульовим?


162

Я знаю, що можу зробити сеттер, який перевіряє, чи є значення 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>

Але як я можу перевірити значення "не" ... як у "NOT NULL" або "NOT = 3"? Це можливо в XAML?

Результати: Дякую за ваші відповіді ... Я знав, що можу зробити конвертер значень (це означає, що мені доведеться зайти в код, і це не буде чистим XAML, як я сподівався). Однак це відповідає на питання, що ефективно "ні" ви не можете зробити це в чистому XAML. Однак обрана відповідь показує, мабуть, найкращий спосіб створити такий функціонал. Гарна знахідка.

Відповіді:


42

Я зіткнувся з подібним обмеженням з DataTriggers, і, здавалося б, ви можете перевірити лише рівність. Найближче, що я бачив, що може вам допомогти, - це техніка порівняння інших видів, крім рівності.

У цій публікації в блозі описано, як проводити порівняння, такі як LT, GT та ін. В DataTrigger.

Це обмеження DataTrigger можна певною мірою подолати, використовуючи конвертер для масажу даних у спеціальне значення, з яким потім можна порівняти, як пропонується у відповіді Роберта Макні.


10
Досить цікаво, що DataTrigger насправді має внутрішнє поле, яке контролює, перевіряє він на рівність чи ні рівність. На жаль, вам доведеться зробити обґрунтовану кількість роздумів, щоб дістатися до необхідного поля. Проблема полягає в тому, що вона може зламатися в наступній версії .net.
Калеб Вір

154

Для цього можна використовувати 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's 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, так що ви можете перевірити що завгодно, а не просто недійсне.


6
Я припускаю, що ви можете зробити перетворювач трохи більш загальним і використовувати ConverterParameter для передачі значення для порівняння (щоб підтримати як порівняння з NOT null, так і NOT 3.
J c

Це працювало для мене частуванням - за допомогою декількох тригерів це робить його приємним і потужним.
Берті

149

Це трохи обман, але я просто встановив стиль за замовчуванням, а потім замінив його за допомогою DataTrigger, якщо значення є нульовим ...

  <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
Це було найкращим рішенням для мого сценарію! Дякуємо, що надали цю відповідь!
Скотт

14
Я не думаю, що це злом, потрібно робити це багато часу; і це найчистіший спосіб зробити це.
akjoshi

3
За замовчуванням Setter можна використовувати без тега Style.Setter.
Насер Асаді

1
Просто квиток! Я постійно вводив за замовчуванням в елемент управління, що володіє стилем, і не міг зрозуміти, чому він продовжував переосмислювати мої стилі :-) Дякую!
Riegardt Steyn

2
краще відповісти, ніж за допомогою перетворювача ... простий і чистий.
DasDas

27

Порівняйте з null (Як сказав Майкл Нунан):

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

4
Це, безумовно, найбільш пряма відповідь. Мені це подобається!
ТимофійП

15

Я використовую це, щоб увімкнути кнопку, лише якщо вибрано елемент перегляду списку (тобто не нульовий):

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

4
Іноді найпростіше рішення ховається за чітким виглядом. Я вважаю, код XAML інтерпретується зверху вниз. Таким чином, спочатку кнопку буде ввімкнено, а потім відключено, якщо в списку перегляду не вибрано жодного елемента. Але скажіть, будь ласка, чи оновлюється стиль після вибору елемента в перегляді списку?
froeschli

Кнопка вмикається, коли вибрано пункт списку, так.
SteveCav

14

Ви можете використовувати DataTriggerклас у Microsoft.Expression.Interactions.dll, який постачається із сумішшю Expression .

Зразок коду:

<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


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>

Я просто використав тут зворотну логіку ... встановивши свій стекпанель невидимим, коли мій комбітер не заповнений, він працює досить добре!


6

стій! Немає перетворювача! Я не хочу "продавати" бібліотеку цього хлопця, але я ненавидів факт робити конвертер кожного разу, коли я хотів порівнювати речі в 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 до проекту).


5

Моє рішення знаходиться в екземплярі 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's NOT NULL Baby!" />
    </DataTrigger>

3

Якщо ви шукаєте рішення, яке не використовує 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>

2

Конвертор:

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

2

Ви можете використовувати конвертер або створити нову властивість у своєму ViewModel таким чином:

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

і використовуйте його:

<DataTrigger Binding="{Binding SomeField}" Value="{Binding CanDoIt}">
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.