При повторной привязке RadioButtons к Enum не происходит привязка - PullRequest
2 голосов
/ 15 июля 2010

При поиске решений для привязки enum к группе RadioButton s я обнаружил Sam ' post полтора года назад.

Lars 'ответ был именно тем, что я искал: простым и эффективным.

Пока я не начал менять объект, связанный с группой RadioButton. Далее следует простая версия.

XAML:

<Window x:Class="RadioEnum.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:re="clr-namespace:RadioEnum"
        Height="200" Width="150">
  <Window.DataContext>
    <re:ViewModel />
  </Window.DataContext>
  <Window.Resources>
    <re:EnumBooleanConverter x:Key="enumBooleanConverter" />
  </Window.Resources>
    <DockPanel>
    <ComboBox DockPanel.Dock="Top" IsSynchronizedWithCurrentItem="True"
              ItemsSource="{Binding Things}" DisplayMemberPath="Name" />
    <GroupBox>
      <StackPanel>
        <RadioButton IsChecked="{Binding Path=Things/Choice, Converter={StaticResource enumBooleanConverter}, ConverterParameter=First}">First</RadioButton>
        <RadioButton IsChecked="{Binding Path=Things/Choice, Converter={StaticResource enumBooleanConverter}, ConverterParameter=Second}">Second</RadioButton>
        <RadioButton IsChecked="{Binding Path=Things/Choice, Converter={StaticResource enumBooleanConverter}, ConverterParameter=Third}">Third</RadioButton>
      </StackPanel>
    </GroupBox>
  </DockPanel>
</Window>

Теперь C #:

namespace RadioEnum
{
    public class ViewModel {
        public ObservableCollection<Thing> Things { get; set; }

        public ViewModel() {
            Things = new ObservableCollection<Thing> {
                new Thing{ Name = "Thing1", Choice = Choice.First, },
                new Thing{ Name = "Thing2", Choice = Choice.Second, },
            };
        }
    }

    public class Thing {
        public string Name { get; set; }
        public Choice Choice { get; set; }
    }

    public enum Choice { None, First, Second, Third, }

    public class EnumBooleanConverter : IValueConverter {
        // Yes, there are slight differences here from Lars' code, but that
        // was to ease debugging. The original version has the same symptom.
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
            object ret = DependencyProperty.UnsetValue;
            var parameterString = parameter as string;

            if (parameterString != null && Enum.IsDefined(value.GetType(), value)) {
                object parameterValue = Enum.Parse(value.GetType(), parameterString);
                ret = parameterValue.Equals(value);
            }

            return ret;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
            object ret = DependencyProperty.UnsetValue;
            var parameterString = parameter as string;

            if (parameterString != null && !value.Equals(false))
                ret = Enum.Parse(targetType, parameterString);

            return ret;
        }
    }
}

Когда приложение загружается с Thing1 в ComboBox, в радиогруппе выбирается правильный Выбор . Выбор Thing2 из ComboBox правильно обновляет Choice . Но с этого момента переключение больше не обновляет привязку к Second RadioButton и, следовательно, больше не вызывает метод Convert с parameter, установленным в " Second ".

Другими словами, хотя значения Thing2 не изменились, все RadioButton очищаются с этого момента. Thing1 продолжает работать, хотя.

Ошибок не обнаружено - ни исключений, ни сообщений в окне вывода. Я пробовал связывать по-разному. Я попытался сделать Choice a DependencyProperty тоже (и Thing затем DependencyObject).

Есть идеи?

Ответы [ 2 ]

1 голос
/ 15 июля 2010

Оригинальный ответ: Не уверен, решит ли это вашу проблему или нет ... так как я думаю, что разрыв в привязке может быть где-то с вашим комбинированным списком ... но для улучшения вашего EnumConverter и убедитесь, что он работает правильно ... Я предлагаю взглянуть на мой ответ на этот вопрос:

Как привязать RadioButtons к перечислению?

(Не выбранный ответ ... но мой ответ с обычным преобразователем, а не с преобразованием строковых значений)

Edit: Я просто взял твой код и попробовал его, и все, казалось, работало отлично! (с использованием visual studio 2010 .net 4)

У вас есть список вещей (в вашем поле со списком), и вы можете установить выбранный в данный момент предмет с помощью переключателя. Я могу изменить выбор каждой вещи, и когда я переключаюсь между вещами, она корректно обновляет радиокнопку для меня!

Поправьте меня, если я ошибаюсь в желаемой функциональности:

Приложение загружается - ComboBox: Thing1 RadioButton: First
Выберите Thing2 - ComboBox: Thing2 RadioButton: Секунда
Выберите Thing1 - ComboBox: Thing1 RadioButton: First
Выберите третий - ComboBox: Thing1 RadioButton: третий
Выберите Thing2 - ComboBox: Thing2 RadioButton: Секунда
Сначала выберите - ComboBox: Thing2 RadioButton: First
Выберите Thing1 - ComboBox: Thing1 RadioButton: Третий
Выберите Thing2 - ComboBox: Thing2 RadioButton: First

Выше представлена ​​функциональность, которую я получаю при запуске вашего приложения с предоставленным вами кодом (и с измененным EnumConverter). Это также, кажется, желаемый результат. Правильно ли это и не работает ли это для вас?

Редактировать 2: я могу подтвердить, что проблема связана с .NET 3.5

Я запускаю профиль клиента .NET 4 ... все работает как нужно ... работает профиль клиента .NET 3.5 ... Я получаю указанный вами результат.

0 голосов
/ 16 июля 2010

Для тех из вас, кто может застрять в .NET 3.5, у меня есть кое-что работающее. Он не так элегантен, как приведенный выше код, но работает.

Я более чем рад видеть отзывы других об альтернативных методах. Пример кода ниже для ThingB , который работает как в .NET 3.5, так и в 4.

Сначала измените XAML на RadioButtons следующим образом (обратите внимание, что имя группы должно быть разным для каждого):

<RadioButton GroupName="One" IsChecked="{Binding Path=Things/ChoiceOne}">First</RadioButton>
<RadioButton GroupName="Two" IsChecked="{Binding Path=Things/ChoiceTwo}">Second</RadioButton>
<RadioButton GroupName="Three" IsChecked="{Binding Path=Things/ChoiceThree}">Third</RadioButton>

Во-вторых, ThingB код:

public class ThingB : INotifyPropertyChanged {
    public string Name { get; set; }

    public Choice Choice {
        get {
            return choiceOne ? Choice.First
                   : choiceTwo ? Choice.Second
                   : choiceThree ? Choice.Third : Choice.None;
        }
        set {
            choiceOne = Choice.First.Equals(value);
            choiceTwo = Choice.Second.Equals(value);
            choiceThree = Choice.Third.Equals(value);
        }
    }

    private bool choiceOne;
    public bool ChoiceOne {
        get { return choiceOne; }
        set {
            if(value) {
                Choice = Choice.First;
                NotifyChoiceChanged();
            }
        }
    }

    private bool choiceTwo;
    public bool ChoiceTwo {
        get { return choiceTwo; }
        set {
            if (value) {
                Choice = Choice.Second;
                NotifyChoiceChanged();
            }
        }
    }

    private bool choiceThree;
    public bool ChoiceThree {
        get { return choiceThree; }
        set {
            if (value) {
                Choice = Choice.Third;
                NotifyChoiceChanged();
            }
        }
    }

    private void NotifyChoiceChanged() {
        OnPropertyChanged("ChoiceOne");
        OnPropertyChanged("ChoiceTwo");
        OnPropertyChanged("ChoiceThree");
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string property) {
        if (PropertyChanged != null) {
            PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }
}
...