DataTrigger, где значение НЕ равно нулю?

Я знаю, что могу создать сеттер, который проверяет, равно ли значение 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. Однако выбранный ответ показывает, вероятно, лучший способ Создайте такой функциональности. Хорошая находка.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
172
0
167 280
12
Перейти к ответу Данный вопрос помечен как решенный

Ответы 12

Ответ принят как подходящий

Я столкнулся с аналогичным ограничением с DataTriggers, и казалось бы, можно только проверить на равенство. Самое близкое, что я видел, что могло бы вам помочь, - это техника выполнения других типов сравнений, отличных от равенства.

Это сообщение в блоге описывает, как выполнять сравнения, такие как LT, GT и т. д. В DataTrigger.

Это ограничение DataTrigger можно в некоторой степени обойти, используя Converter для преобразования данных в специальное значение, с которым вы затем можете сравнивать, как это предлагается в ответе Роберта Макни.

Достаточно интересно, что DataTrigger на самом деле имеет внутреннее поле, которое контролирует, проверяет ли он равенство или нет. К сожалению, чтобы добраться до нужного поля, вам придется поразмыслить над этим. Проблема в том, что он может сломаться в следующей версии .net.

Caleb Vear 27.02.2009 07:22

Для этого можно использовать 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, чтобы вы могли проверять что угодно, а не только null.

Я полагаю, вы могли бы сделать преобразователь более универсальным и использовать ConverterParameter для передачи значения для сравнения (чтобы поддерживать оба сравнения с NOT null и NOT 3.

J c 10.12.2008 19:56

Это сработало для меня - использование множественного триггера делает его приятным и мощным.

Bertie 28.07.2015 16:10

Это немного обман, но я просто установил стиль по умолчанию, а затем переопределил его с помощью 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>

Это было лучшее решение для моего сценария! Спасибо за такой ответ!

Scott 25.03.2010 00:39

Не думаю, что это хакерство, на это нужно много времени; и это наиболее чистый способ сделать это.

akjoshi 29.11.2011 18:44

Сеттер по умолчанию можно использовать без тега Style.Setter.

Naser Asadi 27.07.2013 10:20

Просто билет! Я продолжал устанавливать значение по умолчанию в элементе управления, который владеет стилем, и не мог понять, почему он продолжал переопределять мои стили :-) Спасибо!

Riegardt Steyn 06.01.2014 15:02

лучше ответить, чем использовать конвертер ... простой и чистый.

DasDas 03.09.2015 11:04

Спасибо! Это просто и эффективно. Как раз то, что мне нужно.

Knut Valen 01.11.2016 16:55

Это не чит. Вот как это сделать.

Deepak G M 05.03.2017 20:12

Это может привести к ошибкам привязки в окне вывода, если стиль / свойство по умолчанию зависит от того, что данные не равны нулю ...

ManIkWeet 02.02.2018 19:29

Я использую это, только чтобы включить кнопку, если выбран элемент списка (т.е. не 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>

Иногда самое простое решение скрыто на виду. Я считаю, что код XAML интерпретируется сверху вниз. Таким образом, кнопка сначала будет включена, а затем отключена, если в списке не выбран ни один элемент. Но, пожалуйста, скажите мне, обновляется ли стиль после выбора элемента в списке?

froeschli 02.09.2011 10:06

Кнопка активна, когда выбран элемент списка, да.

SteveCav 05.09.2011 08:13

Мое решение находится в экземпляре 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, а НЕ функцию IIf, которая не работает с объектами Null. Тогда XAML:

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

Сравните с нулем (как сказал Майкл Нунан):

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

Это, безусловно, самый прямой ответ. Мне это нравится!

TimothyP 07.08.2014 14:24

Конвертер:

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

Вы можете использовать класс DataTrigger в Microsoft.Expression.Interactions.dll, который поставляется с Смесь выражений.

Пример кода:

<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

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

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

Стоп! Нет конвертера! Я не хочу «продавать» библиотеку этого парня, но мне не нравился факт создания конвертера каждый раз, когда я хотел сравнить вещи в 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: Привязка 'MYValue == null'. Фактически, вы можете установить любое условие, какое захотите [см. Документ].

обратите внимание, что я не являюсь поклонником третьей стороны. но эта библиотека бесплатна и мало влияет (просто добавьте в проект 2 .dll).

Вы можете использовать конвертер или создать новое свойство в вашей ViewModel следующим образом:

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

и используйте это:

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

Если вы ищете решение, в котором не используется 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>

Другие вопросы по теме