값이 null이 아닌 DataTrigger?


162

값이 NULL인지 확인하고 무언가를 수행하는 setter를 만들 수 있다는 것을 알고 있습니다. 예:

<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"과 같이 "not"값을 어떻게 확인할 수 있습니까? XAML에서도 가능합니까?

결과 : 귀하의 답변에 감사드립니다 ... 나는 가치 변환기를 사용할 수 있다는 것을 알고있었습니다. 그러나 순수한 XAML에서는 효과적으로 "아니오"라는 질문에 답할 수 있습니다. 그러나 선택된 대답은 아마도 그런 종류의 기능 을 만드는 가장 좋은 방법 일 것입니다 . 잘 찾았어요

답변:


42

DataTriggers와 비슷한 한계에 부딪 쳤으며 평등 만 확인할 수있는 것 같습니다. 내가 본 가장 가까운 것은 평등 이외의 다른 유형의 비교를 수행하는 기술입니다.

이 블로그 게시물 은 DataTrigger에서 LT, GT 등과 같은 비교를 수행하는 방법을 설명합니다.

Robert Macnee의 답변에서 제안한 것처럼 DataTrigger의 이러한 제한은 변환기를 사용하여 데이터를 사용자가 비교할 수있는 특별한 값으로 마사지함으로써 어느 정도 해결 될 수 있습니다.


10
흥미롭게도 DataTrigger에는 실제로 동등성을 테스트할지 여부를 제어하는 ​​내부 필드가 있습니다. 불행히도 필요한 필드에 도달하려면 합리적인 양의 반성을해야합니다. 문제는 다음 버전의 .net에서 중단 될 수 있다는 것입니다.
Caleb Vear

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

보다 일반적인 해결책은 ConverterParameter와의 동등성을 확인하는 IValueConverter를 구현하는 것이므로 null이 아닌 모든 것을 확인할 수 있습니다.


6
변환기를 좀 더 일반적으로 만들고 ConverterParameter를 사용하여 비교할 값을 전달할 수 있다고 가정합니다 (Not null과 NOT 3에 대한 비교를 모두 지원하기 위해
J c

이것은 나를 위해 대접을했습니다-다중 트리거를 사용하면 멋지고 강력합니다.
Bertie

149

이것은 약간의 속임수이지만 기본 스타일을 설정하고 값이 null 인 경우 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
이것이 내 시나리오에 가장 적합한 솔루션이었습니다! 이 답변을 제공해 주셔서 감사합니다!
Scott

14
나는 이것이 핵이라고 생각하지 않는다. 당신은 이것을 많은 시간을 할애해야한다. 이것이 가장 깨끗한 방법입니다.
akjoshi

3
기본 Setter는 Style.Setter 태그없이 사용할 수 있습니다.
Naser Asadi

1
딱 티켓! 나는 스타일을 소유하는 컨트롤에 기본값을 계속 넣었고 왜 내 스타일을 계속 무시했는지 알 수 없었습니다. :-) 감사합니다!
Riegardt Steyn

2
간단하고 깨끗한 변환기를 사용하여 더 나은 답변을 얻을 수 있습니다.
DasDas

27

null과 비교하십시오 (Michael Noonan이 말했듯이).

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

변환기가없는 null이 아닌 비교 :

<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
이것은 지금까지 가장 정답입니다. 나는 그것을 좋아한다!
TimothyP

15

목록보기 항목이 선택된 경우 (예 : 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>

4
때로는 가장 간단한 해결책이 분명하게 숨겨져 있습니다. XAML 코드는 위에서 아래로 해석됩니다. 이렇게하면 목록보기에서 요소를 선택하지 않으면 단추가 먼저 활성화 된 다음 비활성화됩니다. 그러나 목록보기에서 항목을 선택하면 스타일이 업데이트됩니까?
froeschli

목록 항목을 선택하면이 버튼이 활성화됩니다 (예).
SteveCav

14

Expression Blend 와 함께 제공 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


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' 입니다. 실제로 원하는 조건을 설정할 수 있습니다 [문서보기].

나는 제 3 자의 팬이 아닙니다. 그러나이 라이브러리는 무료이며 거의 영향을 미치지 않습니다 (프로젝트에 2 .dll을 추가하십시오).


5

내 솔루션은 DataContext 인스턴스 (또는 MVVM을 사용하는 경우 ViewModel)에 있습니다. 원하는 Null이 아님 조건이 충족되면 true를 반환하는 속성을 추가합니다.

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

DataTrigger를 위의 속성에 바인딩하십시오. 참고 : VB.NET에서는 Null 개체에서 작동하지 않는 IIf 함수 인 연산자 If 및 NOT을 사용해야합니다. 그런 다음 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}">
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.