RadioButtons bir enum'a nasıl bağlanır?


406

Bunun gibi bir numaralandırma var:

public enum MyLovelyEnum
{
    FirstSelection,
    TheOtherSelection,
    YetAnotherOne
};

DataContext'imde bir özellik var:

public MyLovelyEnum VeryLovelyEnum { get; set; }

WPF istemcimde üç tane RadioButton var.

<RadioButton Margin="3">First Selection</RadioButton>
<RadioButton Margin="3">The Other Selection</RadioButton>
<RadioButton Margin="3">Yet Another one</RadioButton>

Şimdi düzgün bir iki yönlü bağlanma için RadioButtons özelliğine nasıl bağlanır?


3
Eğer XAML bireysel RadioButtons belirtmeden bunu arıyorsanız, ben gibi numaralandırma değerlerine bağlı bir ListBox öneriyoruz bu ya bu ve bunun gibi kullanım RadioButtons için yazılır öğe şablonu olan bu .
Rachel

Yanıtlar:


389

Daha genel bir dönüştürücü kullanabilirsiniz

public class EnumBooleanConverter : IValueConverter
{
  #region IValueConverter Members
  public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  {
    string parameterString = parameter as string;
    if (parameterString == null)
      return DependencyProperty.UnsetValue;

    if (Enum.IsDefined(value.GetType(), value) == false)
      return DependencyProperty.UnsetValue;

    object parameterValue = Enum.Parse(value.GetType(), parameterString);

    return parameterValue.Equals(value);
  }

  public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  {
    string parameterString = parameter as string;
    if (parameterString == null)
        return DependencyProperty.UnsetValue;

    return Enum.Parse(targetType, parameterString);
  }
  #endregion
}

Ve XAML-Bölümünde şunları kullanırsınız:

<Grid>
    <Grid.Resources>
      <l:EnumBooleanConverter x:Key="enumBooleanConverter" />
    </Grid.Resources>
    <StackPanel >
      <RadioButton IsChecked="{Binding Path=VeryLovelyEnum, Converter={StaticResource enumBooleanConverter}, ConverterParameter=FirstSelection}">first selection</RadioButton>
      <RadioButton IsChecked="{Binding Path=VeryLovelyEnum, Converter={StaticResource enumBooleanConverter}, ConverterParameter=TheOtherSelection}">the other selection</RadioButton>
      <RadioButton IsChecked="{Binding Path=VeryLovelyEnum, Converter={StaticResource enumBooleanConverter}, ConverterParameter=YetAnotherOne}">yet another one</RadioButton>
    </StackPanel>
</Grid>

51
Benim için bir cazibe gibi çalıştı. Ek olarak, ConvertBack'i de UnsetValue'yu "false" olarak döndürecek şekilde değiştirdim, çünkü silverlight (ve muhtemelen WPF uygun) dönüştürücüyü iki kez çağırır - bir kez eski radyo düğmesi değerini ayarlarken ve tekrar yenisini ayarlamak için. Ben sadece bir kez denilen istedim özelliği ayarlayıcı kapalı başka şeyler asılı idi. - if (parametreString == null || value.Equals (false)), DependencyProperty.UnsetValue döndürürse;
MarcE

8
Ne söyleyebilirim, bundan gerekir radyo düğmeleri farklı gruplarda olmadıkça yapılması (aynı ana öğeye sahip GrupAdı set vermeden ve AFAIK düğmeleri aynı grupta varsayılan olarak). Aksi takdirde, özelliği "sıçrama" ayarlamak ve garip davranış ile sonuçlanır.
nlawalker

2
evet, ancak false olarak ayarlanırken dönüştürücüde Unset'i çağırırsanız, bu gerçek bir EnumToBooleanConverter değil, daha çok bir EnumToRadioButtonConverter olur. Bunun yerine, özellik ayarlayıcıda değerin farklı olup olmadığını kontrol ederim: if (_myEnumBackingField == value) return;
Stéphane

8
Bu çözelti üzerindeki ciltleme sadece tek yönlü çalışır. Bağlanan özelliği farklı bir değere atayarak programlı olarak radyo düğmesini değiştiremedim. Uygun bir çalışma VE daha iyi bir çözüm istiyorsanız, scott yaklaşımını kullanın.
l46kok

2
@Marc, bu durumda geri dönmek için uygun bir şey değil mi?
Mark A. Donohoe

559

Kabul edilen cevabı daha da basitleştirebilirsiniz. Numaraları xaml'de dizeler olarak yazmak ve dönüştürücünüzde gerekenden daha fazla iş yapmak yerine, dize temsili yerine numaralandırma değerini açık bir şekilde iletebilirsiniz ve CrimsonX yorumladığında, hatalar çalışma zamanı yerine derleme zamanında atılır:

ConverterParameter = {x: Statik yerel: YourEnumType.Enum1}

<StackPanel>
    <StackPanel.Resources>          
        <local:ComparisonConverter x:Key="ComparisonConverter" />          
    </StackPanel.Resources>
    <RadioButton IsChecked="{Binding Path=YourEnumProperty, Converter={StaticResource ComparisonConverter}, ConverterParameter={x:Static local:YourEnumType.Enum1}}" />
    <RadioButton IsChecked="{Binding Path=YourEnumProperty, Converter={StaticResource ComparisonConverter}, ConverterParameter={x:Static local:YourEnumType.Enum2}}" />
</StackPanel>

Ardından dönüştürücüyü basitleştirin:

public class ComparisonConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return value?.Equals(parameter);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return value?.Equals(true) == true ? parameter : Binding.DoNothing;
    }
}

Düzenleme (Aralık 16 '10):

DependencyProperty.UnsetValue yerine Binding.DoNothing döndürmeyi önerdiği için anon'a teşekkürler.


Not - Aynı kapta birden fazla RadioButton grubu (17 Şubat 11):

Xaml'de, radyo düğmeleri aynı üst kapsayıcıyı paylaşıyorsa, bir kapsayıcı seçildiğinde o kaptaki diğer tüm öğelerin seçimi kaldırılır (farklı bir özelliğe bağlı olsalar bile). Bu nedenle, kendi kabında bir yığın paneli gibi birlikte gruplandırılmış ortak bir özelliğe bağlı RadioButton'unuzu tutmaya çalışın. İlgili RadioButton'larınızın tek bir üst kapsayıcıyı paylaşamadığı durumlarda, her RadioButton öğesinin GroupName özelliğini mantıksal olarak gruplandırmak için ortak bir değere ayarlayın.


Düzenle (5 Nisan '11):

Üçlü İşleç kullanmak için ConvertBack'in if-else yöntemi basitleştirildi.


Not - Bir sınıfta yuvalanmış numaralandırma türü (28 Nisan '11):

Numaralandırma türünüz bir sınıfta içiçe yerleştirilmişse (doğrudan ad alanında değil), XAML içindeki numaralandırmaya erişmek için 'işaretlenmemiş' sorusunda bulunamadı (Bulunamıyor) sorusu bulunamıyor WPF'de statik referans için enum tipi :

ConverterParameter = {x: Statik yerel: Sınıfınız + YourNestedEnumType.Enum1}

Bununla birlikte, bu Microsoft Connect Sorunu nedeniyle , VS2010'daki tasarımcı artık yükleme yüklemeyecek "Type 'local:YourClass+YourNestedEnumType' was not found.", ancak proje başarıyla derleniyor ve çalışıyor. Tabii ki, enum türünüzü doğrudan ad alanına taşıyabiliyorsanız bu sorunu önleyebilirsiniz.


Düzenleme (Oca 27 '12):

Enum bayrakları kullanılıyorsa, dönüştürücü aşağıdaki gibi olacaktır:

public class EnumToBooleanConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return ((Enum)value).HasFlag((Enum)parameter);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return value.Equals(true) ? parameter : Binding.DoNothing;
    }
}

Düzenleme (7 Mayıs '15):

(Bir null Enum durumunda değil , söz konusu istedi, ama mesela ORM DB'den null adlı dönen ya yazmasa bile programın mantığında değer sağlanmamış olması mantıklı olabilir, bazı durumlarda gerekli olabilir), eklemeyi unutmayın Dönüştürme Yöntemi'nde bir ilk null denetimi yapın ve aşağıdaki gibi (genellikle herhangi bir radyo düğmesinin seçilmesini istemiyorsanız) uygun olan bool değerini döndürün:

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value == null) {
            return false; // or return parameter.Equals(YourEnumType.SomeDefaultValue);
        }
        return value.Equals(parameter);
    }

Not - NullReferenceException (10 Ekim 18):

NullReferenceException özel durumunu atma olasılığını kaldırmak için örnek güncellendi. IsCheckeddöndürülebilir Nullable<Boolean>bir çözümdür.


26
Katılıyorum, bunun daha iyi bir çözüm olduğuna inanıyorum. Ayrıca, bu dönüşümün kullanılması, numaralandırma değerleri değiştirilirse, projenin derleme zamanında değil, çalışma zamanında kırılmasına neden olur, bu da büyük bir avantajdır.
CrimsonX

4
Bu kesinlikle kabul edilenden çok daha iyi bir çözümdür. +1
OrPaz

7
Güzel çözüm. Bu gerçekten sadece 2 değerleri karşılaştıran bir karşılaştırma dönüştürücü olduğunu ekleyebilirim. KarşılaştırmaConverter gibi enumToBooleanConverter'dan daha genel bir adı olabilir
MikeKulls

5
@ Scott, Çok hoş. Bu dönüştürücü, Flags özniteliği olan veya olmayan her durumda iyidir. Ancak çoğu durumda bu filtreyi bayrak olarak enum içeren dönüştürücü olarak kullanmak aptalca olur. Bunun nedeni, doğru sonuç almak için önceki değere sahip boole calc (| = veya ^ =) elde etmelisiniz, ancak dönüştürücünün önceki değere erişimi yok. Daha sonra her bir enum değeri için bir bool eklemeli ve MVVM modelinizde uygun boolean calc'i kendiniz yapmalısınız. Ama her bilgi için teşekkürler, çok yararlı.
Eric Ouellet

2
Windows Phone 8'de (Muhtemelen Win Store Uygulamaları durumunda) x: static'imiz yoktur, bu yüzden çözümü burada doğrudan kullanamayız. Ancak IDE / Complier yeterince akıllı ve dizeyi tüm dize değişmezlerine (sanırım yine de) karşı arar. örneğin bu <RadioButton IsChecked = "{Bağlama TrackingMode, ConverterParameter = Sürüş, Dönüştürücü = {StaticResource EnumToBooleanConverter}, Mode = TwoWay}" /> Sürüş'teki herhangi bir yazım hatası, çalışma zamanı yerine tasarım / derleme zamanı sırasında yakalanır.
Adarsha

26

EnumToBooleanConverter yanıtı için: DependencyProperty.UnsetValue döndürmek yerine, Binding.DoNothing öğesini radyo düğmesi IsChecked değerinin yanlış olduğu durumda döndürmeyi düşünün. Birincisi bir sorunu belirtir (ve kullanıcıya kırmızı bir dikdörtgen veya benzer doğrulama göstergeleri gösterebilir), ikincisi ise hiçbir şey yapılmaması gerektiğini gösterir, bu durumda istenen şey budur.

http://msdn.microsoft.com/tr-tr/library/system.windows.data.ivalueconverter.convertback.aspx http://msdn.microsoft.com/tr-tr/library/system.windows.data.binding .donothing.aspx


Silverlight'ta hiçbir şey yok. Sadece WPF. Bunun yerine null kullanın.
Alexander Vasilyev

1
UWP'den hiçbir şey gitmedi.
BlackICE

5

Bir ListBox RadioButtons kullanmak ve sonra SelectedValue için bağlamak.

Bu konu hakkında daha eski bir konu ama temel fikir aynı olmalı: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/323d067a-efef-4c9f-8d99-fecf45522395/


Böylece bir ListBox ve DataTemplate kullanarak benzer bir yöntem yapıyor iki yönlü bağlama olsun.
Bryan Anderson


3
Bu en iyi çözümdür, diğer her şey gereksiz kodlara neden olur. ( ListBox kullanımına bir başka örnek )
HB

3

UWP için, o kadar basit değil: Bir alan değerini parametre olarak iletmek için fazladan bir kasnaktan atlamanız gerekir.

örnek 1

Hem WPF hem de UWP için geçerlidir.

<MyControl>
    <MyControl.MyProperty>
        <Binding Converter="{StaticResource EnumToBooleanConverter}" Path="AnotherProperty">
            <Binding.ConverterParameter>
                <MyLibrary:MyEnum>Field</MyLibrary:MyEnum>
            </Binding.ConverterParameter>
        </MyControl>
    </MyControl.MyProperty>
</MyControl>

ÖRNEK 2

Hem WPF hem de UWP için geçerlidir.

...
<MyLibrary:MyEnum x:Key="MyEnumField">Field</MyLibrary:MyEnum>
...

<MyControl MyProperty="{Binding AnotherProperty, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={StaticResource MyEnumField}}"/>

ÖRNEK 3

Sadece WPF için geçerlidir!

<MyControl MyProperty="{Binding AnotherProperty, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static MyLibrary:MyEnum.Field}}"/>

UWP desteklemiyor x:Static böylece Örnek 3 dışarı soru budur; Örnek 1 ile gittiğinizi varsayarsak , sonuç daha ayrıntılı bir koddur. Örnek 2 biraz daha iyidir, ancak yine de ideal değildir.

Çözüm

public abstract class EnumToBooleanConverter<TEnum> : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        var Parameter = parameter as string;

        if (Parameter == null)
            return DependencyProperty.UnsetValue;

        if (Enum.IsDefined(typeof(TEnum), value) == false)
            return DependencyProperty.UnsetValue;

        return Enum.Parse(typeof(TEnum), Parameter).Equals(value);
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        var Parameter = parameter as string;
        return Parameter == null ? DependencyProperty.UnsetValue : Enum.Parse(typeof(TEnum), Parameter);
    }
}

Ardından, desteklemek istediğiniz her tür için, enum türünü kutulayan bir dönüştürücü tanımlayın.

public class MyEnumToBooleanConverter : EnumToBooleanConverter<MyEnum>
{
    //Nothing to do!
}

Kutulu olmasının nedeni, görünüşte ConvertBackyöntemdeki türe başvurmanın bir yolu olmadığıdır ; boks bununla ilgilenir. İlk iki örnekten biriyle giderseniz, sadece parametre türüne başvurarak kutulu bir sınıftan miras alma ihtiyacını ortadan kaldırabilirsiniz; hepsini tek bir satırda ve mümkün olan en az ayrıntıyla yapmak istiyorsanız, ikinci çözüm idealdir.

Kullanım benzer Örnek 2'ye , ancak aslında daha az ayrıntılıdır.

<MyControl MyProperty="{Binding AnotherProperty, Converter={StaticResource MyEnumToBooleanConverter}, ConverterParameter=Field}"/>

Dezavantajı, desteklemek istediğiniz her tip için bir dönüştürücü tanımlamanız gerekir.


1

Enums için RadioButtons ve CheckBoxes bağlayıcı işlemek için yeni bir sınıf oluşturdum. İşaretli numaralandırmalar (birden çok onay kutusu seçimli) ve bayraksız numaralandırmalar için tek seçim onay kutuları veya radyo düğmeleri için çalışır. Ayrıca hiçbir ValueConverter gerektirmez.

Bu başlangıçta daha karmaşık görünebilir, ancak bu sınıfı projenize kopyaladıktan sonra bitti. Geneldir, böylece herhangi bir numaralandırma için kolayca tekrar kullanılabilir.

public class EnumSelection<T> : INotifyPropertyChanged where T : struct, IComparable, IFormattable, IConvertible
{
  private T value; // stored value of the Enum
  private bool isFlagged; // Enum uses flags?
  private bool canDeselect; // Can be deselected? (Radio buttons cannot deselect, checkboxes can)
  private T blankValue; // what is considered the "blank" value if it can be deselected?

  public EnumSelection(T value) : this(value, false, default(T)) { }
  public EnumSelection(T value, bool canDeselect) : this(value, canDeselect, default(T)) { }
  public EnumSelection(T value, T blankValue) : this(value, true, blankValue) { }
  public EnumSelection(T value, bool canDeselect, T blankValue)
  {
    if (!typeof(T).IsEnum) throw new ArgumentException($"{nameof(T)} must be an enum type"); // I really wish there was a way to constrain generic types to enums...
    isFlagged = typeof(T).IsDefined(typeof(FlagsAttribute), false);

    this.value = value;
    this.canDeselect = canDeselect;
    this.blankValue = blankValue;
  }

  public T Value
  {
    get { return value; }
    set 
    {
      if (this.value.Equals(value)) return;
      this.value = value;
      OnPropertyChanged();
      OnPropertyChanged("Item[]"); // Notify that the indexer property has changed
    }
  }

  [IndexerName("Item")]
  public bool this[T key]
  {
    get
    {
      int iKey = (int)(object)key;
      return isFlagged ? ((int)(object)value & iKey) == iKey : value.Equals(key);
    }
    set
    {
      if (isFlagged)
      {
        int iValue = (int)(object)this.value;
        int iKey = (int)(object)key;

        if (((iValue & iKey) == iKey) == value) return;

        if (value)
          Value = (T)(object)(iValue | iKey);
        else
          Value = (T)(object)(iValue & ~iKey);
      }
      else
      {
        if (this.value.Equals(key) == value) return;
        if (!value && !canDeselect) return;

        Value = value ? key : blankValue;
      }
    }
  }

  public event PropertyChangedEventHandler PropertyChanged;

  private void OnPropertyChanged([CallerMemberName] string propertyName = "")
  {
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  }
}

Ve nasıl kullanılacağı için, bir görevi manuel veya otomatik olarak çalıştırmak için bir numaralandırmanız olduğunu ve haftanın herhangi bir günü için planlanabileceğini ve bazı isteğe bağlı seçeneklerin olduğunu varsayalım ...

public enum StartTask
{
  Manual,
  Automatic
}

[Flags()]
public enum DayOfWeek
{
  Sunday = 1 << 0,
  Monday = 1 << 1,
  Tuesday = 1 << 2,
  Wednesday = 1 << 3,
  Thursday = 1 << 4,
  Friday = 1 << 5,
  Saturday = 1 << 6
}

public enum AdditionalOptions
{
  None = 0,
  OptionA,
  OptionB
}

Şimdi, bu sınıfı kullanmak ne kadar kolay:

public class MyViewModel : ViewModelBase
{
  public MyViewModel()
  {
    StartUp = new EnumSelection<StartTask>(StartTask.Manual);
    Days = new EnumSelection<DayOfWeek>(default(DayOfWeek));
    Options = new EnumSelection<AdditionalOptions>(AdditionalOptions.None, true, AdditionalOptions.None);
  }

  public EnumSelection<StartTask> StartUp { get; private set; }
  public EnumSelection<DayOfWeek> Days { get; private set; }
  public EnumSelection<AdditionalOptions> Options { get; private set; }
}

Ve bu sınıfla onay kutularını ve radyo düğmelerini bağlamak ne kadar kolay:

<StackPanel Orientation="Vertical">
  <StackPanel Orientation="Horizontal">
    <!-- Using RadioButtons for exactly 1 selection behavior -->
    <RadioButton IsChecked="{Binding StartUp[Manual]}">Manual</RadioButton>
    <RadioButton IsChecked="{Binding StartUp[Automatic]}">Automatic</RadioButton>
  </StackPanel>
  <StackPanel Orientation="Horizontal">
    <!-- Using CheckBoxes for 0 or Many selection behavior -->
    <CheckBox IsChecked="{Binding Days[Sunday]}">Sunday</CheckBox>
    <CheckBox IsChecked="{Binding Days[Monday]}">Monday</CheckBox>
    <CheckBox IsChecked="{Binding Days[Tuesday]}">Tuesday</CheckBox>
    <CheckBox IsChecked="{Binding Days[Wednesday]}">Wednesday</CheckBox>
    <CheckBox IsChecked="{Binding Days[Thursday]}">Thursday</CheckBox>
    <CheckBox IsChecked="{Binding Days[Friday]}">Friday</CheckBox>
    <CheckBox IsChecked="{Binding Days[Saturday]}">Saturday</CheckBox>
  </StackPanel>
  <StackPanel Orientation="Horizontal">
    <!-- Using CheckBoxes for 0 or 1 selection behavior -->
    <CheckBox IsChecked="{Binding Options[OptionA]}">Option A</CheckBox>
    <CheckBox IsChecked="{Binding Options[OptionB]}">Option B</CheckBox>
  </StackPanel>
</StackPanel>
  1. Kullanıcı arayüzü yüklendiğinde, "Manuel" radyo düğmesi seçilir ve seçiminizi "Manuel" veya "Otomatik" arasında değiştirebilirsiniz ancak bunlardan birinin her zaman seçilmesi gerekir.
  2. Haftanın her günü kontrol edilmeyecek, ancak herhangi bir sayı kontrol edilebilir veya kontrol edilemez.
  3. "Seçenek A" ve "Seçenek B" başlangıçta işaretlenmeyecektir. Birini veya diğerini kontrol edebilirsiniz, birinin diğerinin işaretini kaldıracağını kontrol edebilirsiniz (RadioButtons'a benzer), ancak şimdi her ikisinin de işaretini kaldırabilirsiniz (WPF'nin RadioButton'uyla yapamazsınız, bu yüzden CheckBox burada kullanılıyor)

StartTask numaralandırmasında {Tanımlanmamış, Manuel, Otomatik} gibi 3 öğeniz olduğunu varsayalım. Bir kullanıcı bir değer ayarlayana kadar tanımsız olduğu için varsayılan olarak Tanımsız olarak ayarlamak istiyorsunuz. Ayrıca: SelectedItem nasıl ele alınır? ViewModel'inizde SelectedStartTask yok.
user1040323

ViewModel'imde, StartUp özelliği bir EnumSelection<StartTask>nesnedir. Tanımına bakarsanız EnumSelection<T>, bir Value özelliğine sahip olduğunu görebilirsiniz. Bu nedenle görünüm modelinde "SelectedStartTask" bulunması gerekmez. Kullanırdınız StartUp.Value. Varsayılan Tanımsız değerine sahip olmak için, 3. sıralamaya, EkOptions'a bakın, Tanımsız yerine Hiçbiri vardır, ancak adını istediğiniz gibi değiştirebilirsiniz.
Nick

1

Bu onay kutusu için de geçerlidir.

public class EnumToBoolConverter:IValueConverter
{
    private int val;
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        int intParam = (int)parameter;
        val = (int)value;

        return ((intParam & val) != 0);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        val ^= (int)parameter;
        return Enum.Parse(targetType, val.ToString());
    }
}

Tek bir numaralandırmayı birden çok onay kutusuna bağlama.


1
Benim için yaptığın iyilik için sana büyük bir "TEŞEKKÜRLER" diyorum. Benim için bir cazibe gibi çalıştı.
Elham Azadfar

0

Scott EnumToBooleanConverter temel alınmıştır. ConvertBack yöntemi Enum bayrak kodu ile çalışmadığını fark ettim.

Aşağıdaki kodu denedim:

public class EnumHasFlagToBooleanConverter : IValueConverter
    {
        private object _obj;
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            _obj = value;
            return ((Enum)value).HasFlag((Enum)parameter);
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value.Equals(true))
            {
                if (((Enum)_obj).HasFlag((Enum)parameter))
                {
                    // Do nothing
                    return Binding.DoNothing;
                }
                else
                {
                    int i = (int)_obj;
                    int ii = (int)parameter;
                    int newInt = i+ii;
                    return (NavigationProjectDates)newInt;
                }
            }
            else
            {
                if (((Enum)_obj).HasFlag((Enum)parameter))
                {
                    int i = (int)_obj;
                    int ii = (int)parameter;
                    int newInt = i-ii;
                    return (NavigationProjectDates)newInt;

                }
                else
                {
                    // do nothing
                    return Binding.DoNothing;
                }
            }
        }
    }

İşe alamayan tek şey bir döküm yapmaktır intiçin targetTypebunu için kodlanmış yapılan bu yüzden NavigationProjectDatesben kullandıkları enum. Ve targetType == NavigationProjectDates...


Daha genel Flags Enum dönüştürücü için düzenleyin:

    public class FlagsEnumToBooleanConverter: IValueConverter {
        özel int _flags = 0;
        public object Convert (nesne değeri, Type targetType, nesne parametresi, dize dili) {
            (value == null) false değerini döndürürse;
            _flags = (int) değer;
            T = değer yazın. GetType ();
            object o = Enum.ToObject (t, parametre);
            return ((Enum) değeri) .HasFlag ((Enum) o);
        }

        ortak nesne ConvertBack (nesne değeri, Type targetType, nesne parametresi, dize dili)
        {
            if (value? .Equals (true) ?? false) {
                _flags = _flags | (int) parametresi;
            }
            Başka {
                _flags = _flags & ~ (int) parametresi;
            }
            return _flags;
        }
    }

Birisi Flags kodunu eklemek için cevabımı düzenledi, bu yüzden dürüst olmak gerekirse, ben hiç denemedim / kullanmadım ve kendi cevabı olarak daha mantıklı olduğunu düşündüğüm için kaldırmayı düşünmüştüm. Daha sonra biraz zaman bulabilirsem, bu kodu ve sahip olduklarınızı test etmek için bir şeyler bir araya getirebilirim ve belki de sorununuz için daha iyi bir çözüme gelebilirsiniz.
Scott

0

Radyo düğmelerini dinamik olarak oluşturabilir, ListBoxdönüştürücüler olmadan bunu yapmanıza yardımcı olabilir, oldukça basit.

Sonuç adımları aşağıdadır: bir ListBox oluşturun ve listbox için ItemsSource'u enum olarak ayarlayın MyLovelyEnumve ListBox'ın SelectedItem'ini VeryLovelyEnumözelliğe bağlayın . Ardından her ListBoxItem için Radyo Düğmeleri oluşturulacaktır.

  • 1.Adım : Pencereniz, UserControl veya Grid vb. İçin statik kaynaklara enum ekleyin.
    <Window.Resources>
        <ObjectDataProvider MethodName="GetValues"
                            ObjectType="{x:Type system:Enum}"
                            x:Key="MyLovelyEnum">
            <ObjectDataProvider.MethodParameters>
                <x:Type TypeName="local:MyLovelyEnum" />
            </ObjectDataProvider.MethodParameters>
        </ObjectDataProvider>
    </Window.Resources>
  • Adım 2 : Liste Kutusunu ve Control Templateiçindeki her öğeyi Radyo düğmesi olarak doldurmak için
    <ListBox ItemsSource="{Binding Source={StaticResource MyLovelyEnum}}" SelectedItem="{Binding VeryLovelyEnum, Mode=TwoWay}" >
        <ListBox.Resources>
            <Style TargetType="{x:Type ListBoxItem}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate>
                            <RadioButton
                                Content="{TemplateBinding ContentPresenter.Content}"
                                IsChecked="{Binding Path=IsSelected,
                                RelativeSource={RelativeSource TemplatedParent},
                                Mode=TwoWay}" />
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </ListBox.Resources>
    </ListBox>

Avantajı aşağıdaki gibidir: birgün enum sınıfı değişirse GUI (XAML dosyası) güncellemeniz gerekiyor yoksa.

Kaynaklar: https://brianlagunas.com/a-better-way-to-data-bind-enums-in-wpf/

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.