BooleanToVisibilityConverter'ı nasıl ters çevirebilirim?


143

Bir kontrol özelliğini bir BooleanToVisibilityConverterbağlamak için bir WPF kullanıyorum . Bu iyi çalışıyor, ancak denetimlerinden birinin boolean ise gizlenmesini ve olmadığını göstermesini istiyorum .VisibilityBooleantruefalse


not: beta 4 itibarıyla - Silverlight BooleanToVisibility içermez - yine kendiniz uygulamak gerekir bu yüzden
Simon_Weaver


Böyle şeyler yapmak için bazı dönüştürücü parametreleri uygulamadıklarına inanamıyorum.
Kamil

Yanıtlar:



250

Tersine IValueConverterçevirmek yerine, Boole değerini doğru ve yanlış için yapılandırılabilir hedef değerlere dönüştürebilen genel bir uygulama kullanarak aynı hedefe ulaşabilirsiniz . Aşağıda böyle bir uygulama yer almaktadır:

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

Nerede Sonra, alt sınıf Tise Visibility:

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

Son olarak, BooleanToVisibilityConverteryukarıda XAML'de nasıl kullanabilir ve örneğin Collapsedtrue ve Visiblefalse için kullanacak şekilde yapılandırabilirsiniz :

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

Adlı bir Boole özelliğine bağlamak istediğinizde bu inversiyon yararlıdır IsHiddenaksine IsVisible.


Bir şeyleri kaçırıyor olabilirim, ama sadece reddedilen bir mülke ihtiyacınız yok mu? stackoverflow.com/questions/534575/…
OscarRyz

9
@OscarRyz: Daha karmaşık UI'lerle, görünüm modellerine çok fazla can sıkıcı dağınıklık katmaya başlar, kod kapsamını korumak için teorik olarak test etmek zorunda olduğunuz başka bir özellikten bahsetmiyoruz. Görünüm modelleri almak zorunda olmamalıdır olduğunu , aksi takdirde de sadece olabilir, bakış uygulama detaylarına yakından Visibilitygörünümünüzü modelinde özelliklerini.
Aaronaught

Bu çok basit, ama önemli ölçüde yardımcı. Teşekkürler @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;
    }
}

ve ardından ConverterParameter olarak doğru veya yanlış iletin

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

4
At else if (value is bool?)parçası, ReSharper "İfade her zaman yanlış" söylüyor. Ayrıca, if (flag)bölüm daha kısaca yeniden yazılabilir return flag ? Visibility.Visible : Visibility.Collapsed;.
Danilo Bargen

1
Bir şeyleri kaçırıyor olabilirim, ama sadece reddedilen bir mülke ihtiyacınız yok mu? stackoverflow.com/questions/534575/…
OscarRyz

1
var nullable = (bool?)value; flag = nullable.GetValueOrDefault();çok daha kısa ve basit yapılabilir:flag = (bool?)value ?? false;
ANeves

45

Kendi yazınız şimdilik en iyi çözüm. Aşağıda, Normal ve Ters Çevirilmiş her iki şekilde de yapabilen bir Dönüştürücü örneği verilmiştir. Bu konuda herhangi bir sorun yaşarsanız, sorun.

[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
Sadece bir şey merak ediyorum. "IsRunning Bağlama" xaml kodu, "IsRunning" nesnesinin kaynak kodu veya değeri nerede?
What'sUP

IsRunning benim modelimde bir özellik. Bu kodun bağlamı uzun ama kısa da olsa bazı hesaplama ve gizli olmayan diğer şeyler çalışırken bir şeyler gizli olması gerekiyordu. Bu dönüştürücüyü, görünüm modelimde birden çok özelliğe sahip olmam gerekecek şekilde oluşturdum.
Michael Hohlios

2
BooleanToVisibilityConverterParametreyi null için kontrol ederek normalin yerine bir değiştirme yapabilirsiniz :Parameter direction = Parameter.Normal; if (parameter != null) direction = (Parameter)Enum.Parse(typeof(Parameter), (string)parameter);
JCH2k

20

Ayrıca Codeplex'te WPF Dönüştürücüler projesi var. Belgelerinde , Görünürlük numaralandırmasından boole dönüştürmek için MapConverter'lerini kullanabileceğinizi söylüyorlar

<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 Dönüştürücüler artık ters çevrilebilen bir BooleanToVisibilityConverter içerir.
Mart'ta vinod

17

ViewModel Boolean Değerini (IsButtonVisible) xaml Denetim Görünürlük Özelliği ile birleştirmenin bir yolu daha. Kodlama yok, dönüştürme yok, sadece stil.

<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

Ya da gerçek tembel adamın yolu, zaten var olanı kullan ve çevir:

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

Özel dönüştürücü yazmayı sevmiyorsanız, bunu çözmek için veri tetikleyicileri kullanabilirsiniz:

<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

Bu konuda bir yazı yaptım. Michael Hohlios'un yaptığıyla benzer bir fikir kullandım. Yalnızca "object parametresi" yerine Özellikler kullandım.

Görünürlüğü WPF

Kullanım Özelliklerinde bir bool değerine bağlamak Bağlama Bence onu daha okunabilir hale getirir.

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

Sadece kendi yorumumu takip ediyorum. Özellikler'i kullanırsanız, dönüştürücüler oluşturmak istiyorsanız, biri Ters, diğeri değil ayrı bir nesne oluşturmanız gerekir. Parametreleri kullanırsanız, birden fazla öğe için bir nesne kullanabilirsiniz, ancak dikkat etmezseniz kafa karıştırıcı olabilir. Yani her ikisinin de artıları ve eksileri var.
Rhyous

Boolean to Colours dönüştürücülerini gerçekleştirmede çok yararlı buldum. Teşekkür ederim
Federinik

3

İşte yazdığım ve çok kullandığım. Değerin ters çevrilip çevrilmeyeceğini gösteren bir boolean dönüştürücü parametresi kullanır ve ardından negatifliği gerçekleştirmek için XOR kullanır:

[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;
    }
}

İşte referans için bir XOR doğruluk tablosu:

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

2

Daha genel bir cevap arıyordum, ama bulamadım. Başkalarına yardımcı olabilecek bir dönüştürücü yazdım.

Altı farklı vakayı ayırt etmemiz gerektiğine dayanmaktadır:

  • Doğru 2 Görünür, Yanlış 2 Gizli
  • Gerçek 2 Görünür, Yanlış 2 Daraltılmış
  • True 2 Hidden, False 2 Görünür
  • Doğru 2 Daraltılmış, Yanlış 2 Görünür
  • Doğru 2 Gizli, Yanlış 2 Daraltılmış
  • Doğru 2 Daraltılmış, Yanlış 2 Gizli

İşte ilk 4 vaka için benim uygulama:

[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();
    }
}

misal:

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

Bence parametrelerin hatırlanması kolay.

Umarım birine yardımcı olur.


2

QuickConverter'ı kullanabilirsiniz .

QuickConverter ile dönüştürücü mantığını BindingExpression'unuzla satır içine yazabilirsiniz

İşte ters BooleanToVisibility dönüştürücü:

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

NuGet aracılığıyla QuickConverter ekleyebilirsiniz. Kurulum belgelerine göz atın. Bağlantı: https://quickconverter.codeplex.com/


1

Kendi dönüştürmenizi yazın.

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

0

Bunun gibi kullanılabilecek basit bir tek yönlü sürüm:

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

şu şekilde uygulanabilir:

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

Her şeyi her şeye dönüştürün (bool, string, enum, vb.):

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 Örnekleri:

<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

Kendi kodunuzu yazmak / yeniden keşfetmek yerine CalcBinding kullanmayı düşünün :

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, diğer birçok senaryo için de oldukça kullanışlıdır.


-2

Bunun tarihlendiğini biliyorum, ancak hiçbir şeyi yeniden uygulamanıza gerek yok.

Ne yaptım böyle mülkiyet özelliği değerini reddetmek oldu:

<!-- 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); }
}

Ve gayet iyi çalışıyor!

Bir şey mi kaçırıyorum?


7
Bunun daha kolay bir çözüm olduğunu düşünüyorsunuz ve tek bir mülk için bu bile geçerli olabilir (birden fazla mülk için tekrar kullanılamaz, her biri için uygulamanız gerekir). Ben viewmodel / codeBehind ve manzaralı her şeyi ile ilgisi yok gibi olsa da, uygulama için yanlış bir yer olduğunu hissediyorum.
Mike Fuchs
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.