Як прив’язати RadioButtons до перерахунку?


406

У мене такий перелік:

public enum MyLovelyEnum
{
    FirstSelection,
    TheOtherSelection,
    YetAnotherOne
};

Я отримав власність у своєму DataContext:

public MyLovelyEnum VeryLovelyEnum { get; set; }

І я отримав три RadioButtons у своєму WPF-клієнті.

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

Тепер, як я прив’язую RadioButtons до властивості для належного двостороннього прив'язки?


3
Якщо ви хочете , щоб зробити це без вказівки індивідуальних Radiobuttons в вашому XAML, я б рекомендував ListBox прив'язана до значень перерахування , як це або це , і що має шаблон елемента переписаний для використання радиокнопки , як це .
Рейчел

Відповіді:


389

Ви можете використовувати більш загальний перетворювач

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
}

І в частині XAML ви використовуєте:

<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
Працювало як шарм для мене. Як додаток, я змінив ConvertBack також повернути UnsetValue на "false", тому що Silverlight (і, імовірно, належний WPF) викликає перетворювач двічі - один раз, коли відміняє старе значення перемикача і знову встановлює нове. Я розвішував інші речі від власника майна, тому хотів, щоб це називали один раз. - якщо (parameterString == null || value.Equals (false)) повертає DependencyProperty.UnsetValue;
MarcE

8
З того, що я можу сказати, це потрібно робити, якщо радіо кнопки не знаходяться в різних групах (а кнопки AFAIK без набору GroupName, у яких однаковий батьківський, за замовчуванням в одній групі). В іншому випадку дзвінки встановити властивість "відскакують" і призводять до незвичайної поведінки.
nlawalker

2
так, але якщо ви встановите Unset у перетворювачі під час встановлення значення false, це не справжній EnumToBooleanConverter, а більше EnumToRadioButtonConverter. Тож замість цього я перевіряю, чи значення у моєму налаштуваннях властивостей відрізняється: if (_myEnumBackingField == value) return;
Стефан

8
Прив’язка до цього рішення працює правильно лише в одну сторону. Я не зміг програматично переключити радіо кнопку, призначивши властивість прив’язаного до іншого значення. Якщо ви хочете належного робочого та кращого рішення, використовуйте підхід Скотта.
l46kok

2
@Marc, чи не належним чином повернути в цьому випадку "Binding.DoNothing", а не "DependencyProperty.UnsetValue"?
Марк А. Донохое

559

Ви можете додатково спростити прийняту відповідь. Замість того, щоб вводити переліки як рядки в xaml і робити більше роботи в конвертері, ніж потрібно, ви можете явно передавати значення enum замість рядкового представлення, і, як прокоментував CrimsonX, помилки викидаються під час компіляції, а не під час виконання:

ConverterParameter = {x: Статичний локальний: 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>

Потім спростіть перетворювач:

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

Редагувати (16 грудня '10):

Завдяки anon за те, що запропонував повернути Binding.DoNothing, а не DependencyProperty.UnsetValue.


Примітка. Кілька груп RadioButtons в одному контейнері (17 лютого 11):

У xaml, якщо перемикачі перемикають один і той же батьківський контейнер, тоді, якщо вибрати один, буде вибрано всі інші в цьому контейнері (навіть якщо вони пов'язані з іншим властивістю). Тому спробуйте зберегти свої RadioButton, які прив'язані до спільної властивості, згрупованої разом у власному контейнері, як панель стеків. У випадках, коли ваші пов'язані RadioButtons не можуть поділитись єдиним батьківським контейнером, тоді встановіть для властивості GroupName кожного RadioButton загальне значення для логічного їх групування.


Редагувати (5 квітня '11):

Спрощена програма ConvertBack, якщо потрібно використовувати термінальний оператор.


Примітка - Тип Enum вкладений у класі (28 квітня '11):

Якщо ваш тип enum вкладений у класі (а не безпосередньо у просторі імен), ви можете використовувати синтаксис '+' для доступу до enum у XAML, як зазначено у (не позначеному) відповіді на запитання Неможливо знайти тип enum для статичної довідки у WPF :

ConverterParameter = {x: Статичний локальний: YourClass + YourNestedEnumType.Enum1}

Завдяки цьому Microsoft Connect Issue , дизайнер у VS2010 більше не завантажує констатування "Type 'local:YourClass+YourNestedEnumType' was not found.", але проект компілюється та працює успішно. Звичайно, ви можете уникнути цього питання, якщо зможете безпосередньо перемістити тип перерахунку до простору імен.


Редагувати (27 січня '12):

Якщо використовується прапорці Enum, перетворювач буде таким:

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

Редагувати (7 травня '15):

У випадку з Nullable Enum (це не задається питанням, але воно може знадобитися в деяких випадках, наприклад, ORM, що повертає нуль з БД, або коли це може мати сенс, що в логіці програми значення не передбачено), не забудьте додати початкова нульова перевірка методу конвертування та повернення відповідного значення bool, яке, як правило, є помилковим (якщо ви не бажаєте, щоб було вибрано жодну радіо-кнопку), як показано нижче:

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

Примітка - NullReferenceException (10 жовтня 18):

Оновлено приклад, щоб видалити можливість викидання NullReferenceException. IsCheckedє змінним типом, тому повернення Nullable<Boolean>здається розумним рішенням.


26
Я згоден, я вважаю, що це краще рішення. Також використання цього перетворення призведе до того, що проект порушиться під час компіляції, а не час запуску, якщо значення перерахунку будуть змінені, що є великою перевагою.
CrimsonX

4
Це, безумовно, набагато краще рішення, ніж прийняте. +1
OrPaz

7
Приємне рішення. Я додам, що це дійсно просто конвертер порівняння, який порівнює 2 значення. Це може мати більш загальну назву, ніж EnumToBooleanConverter, наприклад,
ComparingConverter

5
@ Скотт, Дуже приємно. Цей перетворювач хороший у будь-яких випадках, з атрибутом Прапори або без нього. Але в більшості випадків було б нерозумно використовувати цей фільтр безпосередньо як перетворювач із перерахунком як прапори. Причина полягає в тому, що вам слід досягти булевого calc (| = або ^ =) з попереднім значенням, щоб отримати належний результат, але перетворювач не має доступу до попереднього значення. Потім слід додати значення bool для кожної величини enum і зробити належне булеве вирахування самостійно у своїй моделі MVVM. Але дякую за кожну інформацію, дуже корисно.
Ерік Оуеллет

2
У Windows Phone 8 (можливо, у випадку програми Win Store Apps) у нас немає x: статики, тому ми не можемо тут безпосередньо використовувати рішення. Однак IDE / Complier досить розумний і шукає рядок проти всіх рядкових літералів (я думаю, все одно). наприклад, це працює <RadioButton IsChecked = "{Прив'язка TrackingMode, ConverterParameter = Водіння, Конвертер = {StaticResource EnumToBooleanConverter}, Mode = TwoWay}" /> Будь-які помилки в водінні будуть зафіксовані під час проектування / компіляції, а не часу виконання.
Адарша

26

Для відповіді EnumToBooleanConverter: Замість того, щоб повертати DependencyProperty.UnsetValue, розгляньте про повернення Binding.DoNothing для випадку, коли для перемикача значення IsChecked стає хибним. Перший вказує на проблему (і може показувати користувачеві червоний прямокутник або подібні індикатори перевірки), а другий просто вказує на те, що нічого не слід робити, чого саме потрібно шукати в такому випадку.

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


Немає прив'язки. Нічого в Silverlight. Це лише WPF. Використовуйте замість null.
Олександр Васильєв

1
Пов'язування. Ніщо також не пішло від UWP.
BlackICE

5

Я б використав RadioButtons у ListBox, а потім прив'язав би до SelectedValue.

Це старіші теми щодо цієї теми, але основна ідея повинна бути такою ж: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/323d067a-efef-4c9f-8d99-fecf45522395/


Я отримую двостороння прив'язка, виконуючи подібний метод, використовуючи ListBox і DataTemplate, так що вам слід.
Брайан Андерсон

Ця помилка: geekswithblogs.net/claraoscura/archive/2008/10/17/125901.aspx зіпсувала мені день.
Slampen

3
Це, безумовно, найкраще рішення, все інше викликає зайвий код. ( Ще один приклад використання ListBox)
НВ

3

Для UWP це не так просто: Ви повинні перейти через додатковий обруч, щоб передати значення поля в якості параметра.

Приклад 1

Дійсно як для WPF, так і для UWP.

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

Приклад 2

Дійсно як для WPF, так і для UWP.

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

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

Приклад 3

Діє лише для WPF!

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

UWP не підтримує, x:Staticтому Приклад 3 не підлягає сумніву; якщо припустити, що ви переходите з прикладу 1 , то результат є більш детальним кодом. Приклад 2 трохи кращий, але все ще не ідеальний.

Рішення

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

Потім для кожного типу, який ви хочете підтримати, визначте перетворювач, який містить тип enum.

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

Причиною цього є те, що, мабуть, немає способу посилання на тип у ConvertBack методі; бокс опікується цим. Якщо ви переходите до будь-якого з перших двох прикладів, ви можете просто посилатися на тип параметра, позбавляючи від необхідності успадковувати з клавіатурного класу; якщо ви хочете зробити це все в один рядок і з найменшою можливою багатослівністю, останнє рішення ідеально.

Використання нагадує Приклад 2 , але насправді є менш багатослівним.

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

Мінус - ви повинні визначити перетворювач для кожного типу, який ви хочете підтримати.


1

Я створив новий клас для обробки прив'язки RadioButtons і CheckBoxes до перерахунків. Він працює для перелічених переліків (з декількома відмітками прапорців) та непозначених перерахувань для прапорців одного вибору або радіо кнопок. Також він взагалі не потребує ValueConverters.

Спочатку це може виглядати складніше, проте, як тільки ви скопіюєте цей клас у свій проект, це буде зроблено. Це загальний характер, тому його можна легко використати для будь-якого перерахунку.

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

Щодо того, як його використовувати, скажімо, у вас є перерахунок для виконання завдання вручну або автоматично, і його можна запланувати на будь-які дні тижня та деякі необов'язкові варіанти ...

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
}

Тепер ось, як легко користуватися цим класом:

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

А ось як легко пов’язувати прапорці та радіо кнопки з цим класом:

<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. Коли завантажується інтерфейс користувача, буде вибрана перемикач "Вручну", і ви можете змінити свій вибір між "Ручний" або "Автоматичний", але будь-який з них завжди повинен бути обраний.
  2. Кожен день тижня буде неперевіреним, але будь-яку кількість з них можна перевірити чи не перевірити.
  3. Обидва варіанти "Варіант А" та "Варіант В" спочатку не знімаються. Ви можете перевірити те чи інше, якщо один з них зніме позначку (подібно до RadioButtons), але тепер ви можете зняти прапорець з обох (що ви не можете зробити з RadioButton WPF, через що тут використовується CheckBox)

Припустимо, що у перерахунку StartTask є 3 елементи, такі як {Undefined, Manual, Automatic} Ви хочете встановити за замовчуванням Undefined, оскільки поки користувач не встановить значення, воно не визначене. Також: Як поводиться з вибраним словом? У вашого ViewModel немає вибраного стартового завдання.
користувач1040323

У моєму ViewModel властивість StartUp є EnumSelection<StartTask>об'єктом. Якщо ви подивитесь на визначення, EnumSelection<T>ви побачите, що воно має властивість Value. Таким чином, модель перегляду не повинна мати "SelectedStartTask". Ви б використали StartUp.Value. А що стосується значення за замовчуванням Undefined, дивіться 3-й перерахунок, AdditionalOptions, він має None замість Undefined, але ви можете змінити його ім'я на все, що завгодно.
Нік

1

Ця робота теж для Checkbox .

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

Прив’язування одного перерахунку до кількох прапорців.


1
Я кажу велике "ДЯКУЮ" вам за прихильність, яку ви зробили для мене. Це спрацювало як шарм для мене.
Ельхам Азадфар

0

На основі EnumToBooleanConverter від Скотта. Я помітив, що метод ConvertBack не працює на Enum з кодами прапорців.

Я спробував наступний код:

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

Єдине, що я не можу взяти на роботу, - це зробити акторський склад з, intщоб targetTypeя зробив це жорстким кодом NavigationProjectDates, перерахунок, який я використовую. І, targetType == NavigationProjectDates...


Редагуйте для більш загального перетворювача прапорів Enum:

    Прапори публічного класуEnumToBooleanConverter: IValueConverter {
        private int _flags = 0;
        конвертувати публічний об'єкт (значення об'єкта, тип targetType, параметр об'єкта, мова рядка) {
            якщо (value == null) повернути false;
            _flags = (int) значення;
            Введіть t = value.GetType ();
            об'єкт o = Enum.ToObject (t, параметр);
            повернути ((Enum) значення) .HasFlag ((Enum) o);
        }

        публічний об'єкт ConvertBack (значення об'єкта, тип targetType, параметр об'єкта, мова рядка)
        {
            if (значення? .Eqals (true) ?? false) {
                _flags = _flags | (int) параметр;
            }
            ще {
                _flags = _flags & ~ (int) параметр;
            }
            return _flags;
        }
    }

Хтось відредагував мою відповідь, щоб додати її до коду Flags, тому, чесно кажучи, я ніколи не намагався / не використовував її і розглядав питання про її видалення, оскільки, думаю, це має більше сенсу як власна відповідь. Якщо я можу знайти деякий час пізніше, я можу спробувати скласти щось разом, щоб перевірити цей код, а також те, що у вас є, і, можливо, допоможе знайти кращий варіант вирішення вашої проблеми.
Скотт

0

Ви можете створювати перемикачі динамічно, вони ListBoxможуть допомогти вам зробити це, без перетворювачів, досить просто.

Етапи конкретизації наведені нижче: створіть ListBox та встановіть ItemSource для списку списку як перерахунок MyLovelyEnumі прив’яжіть до властивості SelectedItem ListBox VeryLovelyEnum. Тоді будуть створені кнопки радіо для кожного ListBoxItem.

  • Крок 1 : додайте перерахунок до статичних ресурсів для вашого Windows, UserControl або Grid і т.д.
    <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>
  • Крок 2 : Використовуйте поле списку та Control Templateзаповніть кожен елемент всередині як перемикач
    <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>

Перевага нижче: якщо коли - небудь ваші зміни класу перерахувань, вам не потрібно оновлювати графічний інтерфейс (XAML - файл).

Довідкова інформація: https://brianlagunas.com/a-better-way-to-data-bind-enums-in-wpf/

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.