BooleanToVisibilityConverter를 어떻게 반전합니까?


143

컨트롤 BooleanToVisibilityConverterVisibility속성 을에 바인딩하기 위해 WPF에서을 사용 하고 Boolean있습니다. 이것은 잘 작동하지만 부울이 true인 경우 숨기고 컨트롤인지 표시하는 컨트롤 중 하나를 원합니다 false.


참고 : 베타 4 현재-silverlight에는 BooleanToVisibility가 포함되어 있지 않으므로 직접 구현해야합니다.
Simon_Weaver


나는 그들이 그런 일을하기 위해 일부 변환기 매개 변수를 구현하지 않았다고 믿을 수 없습니다.
Kamil

답변:



250

반전하는 대신 IValueConverter부울 값을 true 및 false에 대해 구성 가능한 대상 값으로 변환 할 수 있는 일반 구현을 사용하여 동일한 목표를 달성 할 수 있습니다 . 다음은 그러한 구현 중 하나입니다.

public class BooleanConverter<T> : IValueConverter
{
    public BooleanConverter(T trueValue, T falseValue)
    {
        True = trueValue;
        False = falseValue;
    }

    public T True { get; set; }
    public T False { get; set; }

    public virtual object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value is bool && ((bool) value) ? True : False;
    }

    public virtual object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value is T && EqualityComparer<T>.Default.Equals((T) value, True);
    }
}

여기서 다음, 그것을 서브 클래스 T입니다 Visibility:

public sealed class BooleanToVisibilityConverter : BooleanConverter<Visibility>
{
    public BooleanToVisibilityConverter() : 
        base(Visibility.Visible, Visibility.Collapsed) {}
}

마지막으로 BooleanToVisibilityConverterXAML에서 위와 같이 사용 하고 예를 들어 Collapsedtrue와 Visiblefalse에 대해 구성 할 수 있습니다 .

<Application.Resources>
    <app:BooleanToVisibilityConverter 
        x:Key="BooleanToVisibilityConverter" 
        True="Collapsed" 
        False="Visible" />
</Application.Resources>

이 반전은 IsHiddenopposed 라는 부울 속성에 바인딩하려는 경우에 유용합니다 IsVisible.


뭔가 빠졌을 수도 있지만 부정 속성이 필요하지 않습니까? stackoverflow.com/questions/534575/…
OscarRyz

9
@OscarRyz : 더 복잡한 UI를 사용하면 뷰 모델에 실제로 성가신 혼란을 더하기 시작합니다. 코드 범위를 유지하기 위해 이론적으로 단위 테스트를 수행 해야하는 다른 속성은 말할 것도 없습니다. 보기 모델은받을 필요가 없습니다 , 그렇지 않으면 당신은뿐만 아니라 그냥있을 수 있습니다, 뷰의 구현 세부 사항에 가까이 Visibility보기 모델의 특성을.
Aaronaught

이것은 매우 간단하지만 크게 도움이됩니다. @AtifAziz 감사합니다.
TheLastGIS

48
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;

public sealed class BooleanToVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var flag = false;
        if (value is bool)
        {
            flag = (bool)value;
        }
        else if (value is bool?)
        {
            var nullable = (bool?)value;
            flag = nullable.GetValueOrDefault();
        }
        if (parameter != null)
        {
            if (bool.Parse((string)parameter))
            {
                flag = !flag;
            }
        }
        if (flag)
        {
            return Visibility.Visible;
        }
        else
        {
            return Visibility.Collapsed;
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var back = ((value is Visibility) && (((Visibility)value) == Visibility.Visible));
        if (parameter != null)
        {
            if ((bool)parameter)
            {
                back = !back;
            }
        }
        return back;
    }
}

그런 다음 ConverterParameter로 true 또는 false를 전달하십시오.

       <Grid.Visibility>
                <Binding Path="IsYesNoButtonSetVisible" Converter="{StaticResource booleanToVisibilityConverter}" ConverterParameter="true"/>
        </Grid.Visibility>

4
else if (value is bool?)부분에서 ReSharper는 "표현은 항상 거짓입니다"라고 말합니다. 또한 if (flag)부분을보다 간결하게 다시 작성할 수 있습니다 return flag ? Visibility.Visible : Visibility.Collapsed;.
Danilo Bargen

1
뭔가 빠졌을 수도 있지만 부정 속성이 필요하지 않습니까? stackoverflow.com/questions/534575/…
OscarRyz 17시 43 분

1
var nullable = (bool?)value; flag = nullable.GetValueOrDefault();더 짧고 간단하게 만들 수 있습니다 :flag = (bool?)value ?? false;
ANeves

45

나만의 솔루션을 지금 작성하십시오. 다음은 Normal과 Inverted를 모두 수행 할 수있는 변환기의 예입니다. 이것에 문제가 있으면 물어보십시오.

[ValueConversion(typeof(bool), typeof(Visibility))]
public class InvertableBooleanToVisibilityConverter : IValueConverter
{
    enum Parameters
    {
        Normal, Inverted
    }

    public object Convert(object value, Type targetType,
                          object parameter, CultureInfo culture)
    {
        var boolValue = (bool)value;
        var direction = (Parameters)Enum.Parse(typeof(Parameters), (string)parameter);

        if(direction == Parameters.Inverted)
            return !boolValue? Visibility.Visible : Visibility.Collapsed;

        return boolValue? Visibility.Visible : Visibility.Collapsed;
    }

    public object ConvertBack(object value, Type targetType,
        object parameter, CultureInfo culture)
    {
        return null;
    }
}
<UserControl.Resources>
  <Converters:InvertableBooleanToVisibilityConverter x:Key="_Converter"/>
</UserControl.Resources>

<Button Visibility="{Binding IsRunning, Converter={StaticResource _Converter}, ConverterParameter=Inverted}">Start</Button>

2
딱 한 가지만 xaml 코드 "Binding IsRunning", 개체 "IsRunning"의 소스 코드 또는 값은 어디에 있습니까?
What'sUP

IsRunning은 내 뷰 모델의 속성입니다. 이 코드의 컨텍스트는 길지만 짧은 것은 계산을 실행할 때 숨겨져 있지 않은 것을 숨겨야한다는 것입니다. 이 변환기를 만들어 뷰 모델에 여러 속성을 가질 필요가 없도록 만들었습니다.
Michael Hohlios

2
BooleanToVisibilityConverternull에 대한 매개 변수를 확인하여 일반 대체품을 대체 할 수 있습니다 .Parameter direction = Parameter.Normal; if (parameter != null) direction = (Parameter)Enum.Parse(typeof(Parameter), (string)parameter);
JCH2k

20

Codeplex 에는 WPF Converters 프로젝트 도 있습니다 . 그들의 문서에서 그들은 당신이 Visibility 열거에서 bool로 변환 하기 위해 MapConverter 를 사용할 수 있다고 말합니다.

<Label>
    <Label.Visible>
        <Binding Path="IsVisible">
            <Binding.Converter>
                <con:MapConverter>
                    <con:Mapping From="True" To="{x:Static Visibility.Visible}"/>
                    <con:Mapping From="False" To="{x:Static Visibility.Hidden}"/>
                </con:MapConverter>
            </Binding.Converter>
        </Binding>
    </Label.Visible>
</Label>

1
WPF 변환기에는 이제 되돌릴 수있는 BooleanToVisibilityConverter가 포함되어 있습니다.
vinod

17

xaml 컨트롤 가시성 속성을 사용하여 ViewModel 부울 값 (IsButtonVisible)을 바인딩하는 또 다른 방법입니다. 코딩 없음, 변환 없음, 스타일링 만 가능합니다.

<Style TargetType={x:Type Button} x:Key="HideShow">
   <Style.Triggers>
      <DataTrigger Binding="{Binding IsButtonVisible}" Value="False">
          <Setter Property="Visibility" Value="Hidden"/>
      </DataTrigger>
   </Style.Triggers>
</Style>

<Button Style="{StaticResource HideShow}">Hello</Button>

15

또는 진짜 게으른 사람의 방식으로 이미 존재하는 것을 사용하고 뒤집으십시오.

public class InverseBooleanToVisibilityConverter : IValueConverter
{
    private BooleanToVisibilityConverter _converter = new BooleanToVisibilityConverter();

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var result = _converter.Convert(value, targetType, parameter, culture) as Visibility?;
        return result == Visibility.Collapsed ? Visibility.Visible : Visibility.Collapsed;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var result = _converter.ConvertBack(value, targetType, parameter, culture) as bool?;
        return result == true ? false : true;
    }
}

5

사용자 정의 변환기 작성이 마음에 들지 않으면 데이터 트리거를 사용하여이를 해결할 수 있습니다.

<Style.Triggers>
        <DataTrigger Binding="{Binding YourBinaryOption}" Value="True">
                 <Setter Property="Visibility" Value="Visible" />
        </DataTrigger>
        <DataTrigger Binding="{Binding YourBinaryOption}" Value="False">
                 <Setter Property="Visibility" Value="Collapsed" />
        </DataTrigger>
</Style.Triggers>

3

방금 이것에 대한 게시물을 보냈습니다. Michael Hohlios와 비슷한 아이디어를 사용했습니다. "object parameter"대신에 Properties 만 사용했습니다.



속성을 사용하여 WPF에서 가시성을 부울 값에 바인딩 하면 내 의견으로는 더 읽기 쉽습니다.

<local:BoolToVisibleOrHidden x:Key="BoolToVisConverter" Collapse="True" Reverse="True" />

내 의견에 대한 후속 조치. 속성을 사용하는 경우 변환기를 만들려면 별개의 개체를 만들어야합니다. 매개 변수를 사용하면 여러 항목에 대해 하나의 개체를 사용할 수 있지만주의를 기울이지 않으면 혼동 될 수 있습니다. 따라서 둘 다 장단점이 있습니다.
Rhyous

부울 대 색상 변환기를 구현하는 데 매우 유용한 것으로 나타났습니다. 감사합니다
Federinik

3

여기 제가 많이 쓰고 사용하는 것이 있습니다. 값을 반전 시킬지 여부를 나타내는 부울 변환기 매개 변수를 사용한 다음 XOR을 사용하여 부정을 수행합니다.

[ValueConversion(typeof(bool), typeof(System.Windows.Visibility))]
public class BooleanVisibilityConverter : IValueConverter
{
    System.Windows.Visibility _visibilityWhenFalse = System.Windows.Visibility.Collapsed;

    /// <summary>
    /// Gets or sets the <see cref="System.Windows.Visibility"/> value to use when the value is false. Defaults to collapsed.
    /// </summary>
    public System.Windows.Visibility VisibilityWhenFalse
    {
        get { return _visibilityWhenFalse; }
        set { _visibilityWhenFalse = value; }
    }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        bool negateValue;
        Boolean.TryParse(parameter as string, out negateValue);

        bool val = negateValue ^ System.Convert.ToBoolean(value); //Negate the value when negateValue is true using XOR
        return val ? System.Windows.Visibility.Visible : _visibilityWhenFalse;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        bool negateValue;
        Boolean.TryParse(parameter as string, out negateValue);

        if ((System.Windows.Visibility)value == System.Windows.Visibility.Visible)
            return true ^ negateValue;
        else
            return false ^ negateValue;
    }
}

다음은 참조 용 XOR 진리표입니다.

        XOR
        x  y  XOR
        ---------
        0  0  0
        0  1  1
        1  0  1
        1  1  0

2

더 일반적인 답변을 찾고 있었지만 찾을 수 없었습니다. 다른 사람들을 도울 수있는 변환기를 작성했습니다.

6 가지 경우를 구별해야한다는 사실에 근거합니다.

  • True 2 표시, False 2 숨김
  • True 2 표시, False 2 축소
  • True 2 숨김, False 2 표시
  • True 2 접기, False 2 표시
  • True 2 숨김, False 2 접기
  • 참 2 축소, 거짓 2 숨김

다음은 처음 4 가지 경우에 대한 구현입니다.

[ValueConversion(typeof(bool), typeof(Visibility))]
public class BooleanToVisibilityConverter : IValueConverter
{
    enum Types
    {
        /// <summary>
        /// True to Visible, False to Collapsed
        /// </summary>
        t2v_f2c,
        /// <summary>
        /// True to Visible, False to Hidden
        /// </summary>
        t2v_f2h,
        /// <summary>
        /// True to Collapsed, False to Visible
        /// </summary>
        t2c_f2v,
        /// <summary>
        /// True to Hidden, False to Visible
        /// </summary>
        t2h_f2v,
    }
    public object Convert(object value, Type targetType,
                          object parameter, CultureInfo culture)
    {
        var b = (bool)value;
        string p = (string)parameter;
        var type = (Types)Enum.Parse(typeof(Types), (string)parameter);
        switch (type)
        {
            case Types.t2v_f2c:
                return b ? Visibility.Visible : Visibility.Collapsed; 
            case Types.t2v_f2h:
                return b ? Visibility.Visible : Visibility.Hidden; 
            case Types.t2c_f2v:
                return b ? Visibility.Collapsed : Visibility.Visible; 
            case Types.t2h_f2v:
                return b ? Visibility.Hidden : Visibility.Visible; 
        }
        throw new NotImplementedException();
    }

    public object ConvertBack(object value, Type targetType,
        object parameter, CultureInfo culture)
    {
        var v = (Visibility)value;
        string p = (string)parameter;
        var type = (Types)Enum.Parse(typeof(Types), (string)parameter);
        switch (type)
        {
            case Types.t2v_f2c:
                if (v == Visibility.Visible)
                    return true;
                else if (v == Visibility.Collapsed)
                    return false;
                break;
            case Types.t2v_f2h:
                if (v == Visibility.Visible)
                    return true;
                else if (v == Visibility.Hidden)
                    return false;
                break;
            case Types.t2c_f2v:
                if (v == Visibility.Visible)
                    return false;
                else if (v == Visibility.Collapsed)
                    return true;
                break;
            case Types.t2h_f2v:
                if (v == Visibility.Visible)
                    return false;
                else if (v == Visibility.Hidden)
                    return true;
                break;
        }
        throw new InvalidOperationException();
    }
}

예:

Visibility="{Binding HasItems, Converter={StaticResource BooleanToVisibilityConverter}, ConverterParameter='t2v_f2c'}"

나는 매개 변수가 기억하기 쉽다고 생각합니다.

누군가에게 도움이되기를 바랍니다.


2

QuickConverter 를 사용할 수 있습니다 .

QuickConverter를 사용하면 BindingExpression과 함께 변환기 논리를 인라인으로 작성할 수 있습니다

반전 된 BooleanToVisibility 변환기는 다음과 같습니다.

Visibility="{qc:Binding '!$P ? Visibility.Visible : Visibility.Collapsed', P={Binding Example}}"

NuGet을 통해 QuickConverter를 추가 할 수 있습니다. 설정 설명서를 살펴보십시오. 링크 : https://quickconverter.codeplex.com/


1

자신의 개종자를 작성하십시오.

public class ReverseBooleanToVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
   {
       // your converter code here
   }
}

0

다음과 같이 사용할 수있는 간단한 편도 버전 :

Visibility="{Binding IsHidden, Converter={x:Static Ui:Converters.BooleanToVisibility}, ConverterParameter=true}

다음과 같이 구현할 수 있습니다.

public class BooleanToVisibilityConverter : IValueConverter
{
  public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  {
    var invert = false;

    if (parameter != null)
    {
      invert = Boolean.Parse(parameter.ToString());
    }

    var booleanValue = (bool) value;

    return ((booleanValue && !invert) || (!booleanValue && invert)) 
      ? Visibility.Visible : Visibility.Collapsed;
  }

  public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  {
    throw new NotImplementedException();
  }
}

0

모든 것을 모든 것으로 변환하십시오 (bool, string, enum 등).

public class EverythingConverterValue
{
    public object ConditionValue { get; set; }
    public object ResultValue { get; set; }
}

public class EverythingConverterList : List<EverythingConverterValue>
{

}

public class EverythingConverter : IValueConverter
{
    public EverythingConverterList Conditions { get; set; } = new EverythingConverterList();

    public object NullResultValue { get; set; }
    public object NullBackValue { get; set; }

    public object Convert(object value, Type targetType,
        object parameter, CultureInfo culture)
    {
        return Conditions.Where(x => x.ConditionValue.Equals(value)).Select(x => x.ResultValue).FirstOrDefault() ?? NullResultValue;
    }
    public object ConvertBack(object value, Type targetType,
        object parameter, CultureInfo culture)
    {
        return Conditions.Where(x => x.ResultValue.Equals(value)).Select(x => x.ConditionValue).FirstOrDefault() ?? NullBackValue;
    }
}

XAML 예 :

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:conv="clr-namespace:MvvmGo.Converters;assembly=MvvmGo.WindowsWPF"
                xmlns:sys="clr-namespace:System;assembly=mscorlib">

<conv:EverythingConverter x:Key="BooleanToVisibilityConverter">
    <conv:EverythingConverter.Conditions>
        <conv:EverythingConverterValue ResultValue="{x:Static Visibility.Visible}">
            <conv:EverythingConverterValue.ConditionValue>
                <sys:Boolean>True</sys:Boolean>
            </conv:EverythingConverterValue.ConditionValue>
        </conv:EverythingConverterValue>
        <conv:EverythingConverterValue ResultValue="{x:Static Visibility.Collapsed}">
            <conv:EverythingConverterValue.ConditionValue>
                <sys:Boolean>False</sys:Boolean>
            </conv:EverythingConverterValue.ConditionValue>
        </conv:EverythingConverterValue>
    </conv:EverythingConverter.Conditions>

</conv:EverythingConverter>

<conv:EverythingConverter x:Key="InvertBooleanToVisibilityConverter">
    <conv:EverythingConverter.Conditions>
        <conv:EverythingConverterValue ResultValue="{x:Static Visibility.Visible}">
            <conv:EverythingConverterValue.ConditionValue>
                <sys:Boolean>False</sys:Boolean>
            </conv:EverythingConverterValue.ConditionValue>
        </conv:EverythingConverterValue>
        <conv:EverythingConverterValue ResultValue="{x:Static Visibility.Collapsed}">
            <conv:EverythingConverterValue.ConditionValue>
                <sys:Boolean>True</sys:Boolean>
            </conv:EverythingConverterValue.ConditionValue>
        </conv:EverythingConverterValue>
    </conv:EverythingConverter.Conditions>
</conv:EverythingConverter>

<conv:EverythingConverter x:Key="MarriedConverter" NullResultValue="Single">
    <conv:EverythingConverter.Conditions>
        <conv:EverythingConverterValue ResultValue="Married">
            <conv:EverythingConverterValue.ConditionValue>
                <sys:Boolean>True</sys:Boolean>
            </conv:EverythingConverterValue.ConditionValue>
        </conv:EverythingConverterValue>
        <conv:EverythingConverterValue ResultValue="Single">
            <conv:EverythingConverterValue.ConditionValue>
                <sys:Boolean>False</sys:Boolean>
            </conv:EverythingConverterValue.ConditionValue>
        </conv:EverythingConverterValue>
    </conv:EverythingConverter.Conditions>
    <conv:EverythingConverter.NullBackValue>
        <sys:Boolean>False</sys:Boolean>
    </conv:EverythingConverter.NullBackValue>
</conv:EverythingConverter>


0

자신의 코드를 작성하거나 재발 명하는 대신 CalcBinding 사용을 고려 하십시오 .

Automatic two way convertion of bool expression to Visibility and back if target property has such type: description

    <Button Visibility="{c:Binding !IsChecked}" /> 
    <Button Visibility="{c:Binding IsChecked, FalseToVisibility=Hidden}" />

CalcBinding은 수많은 다른 시나리오에도 유용합니다.


-2

나는 이것이 날짜가 있다는 것을 알고 있지만, 당신은 아무것도 다시 구현할 필요가 없습니다.

내가 한 일은 다음과 같이 속성의 가치를 부정하는 것이 었습니다.

<!-- XAML code -->
<StackPanel Name="x"  Visibility="{Binding    Path=Specials, ElementName=MyWindow, Converter={StaticResource BooleanToVisibilityConverter}}"></StackPanel>    
<StackPanel Name="y"  Visibility="{Binding Path=NotSpecials, ElementName=MyWindow, Converter={StaticResource BooleanToVisibilityConverter}}"></StackPanel>        

....

//Code behind
public bool Specials
{
    get { return (bool) GetValue(SpecialsProperty); }
    set
    {
        NotSpecials= !value; 
        SetValue(SpecialsProperty, value);
    }
}

public bool NotSpecials
{
    get { return (bool) GetValue(NotSpecialsProperty); }
    set { SetValue(NotSpecialsProperty, value); }
}

그리고 그것은 잘 작동합니다!

뭔가 빠졌습니까?


7
이것이 더 쉬운 해결책이라고 생각하고 단일 속성의 경우에도 마찬가지 일 수 있습니다 (여러 속성에는 재사용 할 수 없으므로 모든 속성에 대해 구현해야 함). viewmodel / codeBehind 및 뷰와 관련된 모든 것과 관련이 없기 때문에 구현에 잘못된 위치라고 생각합니다.
Mike Fuchs
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.