C # - динамические свойства и RaisePropertyChanged - PullRequest
2 голосов
/ 21 мая 2011

У меня есть следующий класс, который я использую для привязки радиокнопок

public class RadioButtonSwitch : ViewModelBase
    {

        IDictionary<string, bool> _options;
        public RadioButtonSwitch(IDictionary<string, bool> options)
        {
            this._options = options;
        }

        public bool this[string a]
        {
            get
            {
                return _options[a];
            }
            set
            {
                if (value)
                {
                    var other = _options.Where(p => p.Key != a).Select(p => p.Key).ToArray();
                    foreach (string key in other)
                        _options[key] = false;
                    _options[a] = true;

                    RaisePropertyChanged("XXXX");
                else
                    _options[a] = false;
            }
        }
    }

XAML

<RadioButton Content="Day" IsChecked="{Binding RadioSwitch[radio1], Mode=TwoWay}" GroupName="Monthly" HorizontalAlignment="Left" VerticalAlignment="Center" />

ViewModel

RadioSwitch = new RadioButtonSwitch(
                new Dictionary<string, bool> {{"radio1", true},{"radio2", false}}
                );

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

Я пытался поставить:

  • Item []
  • a
  • [a]

Я получаю следующую ошибку:

Error

Это так, в случае любого изменения я могу справитьсяэто на мой взгляд соответственно.Пожалуйста, не дайте мне решения для списка переключателей и т. Д.

Ответы [ 2 ]

2 голосов
/ 21 мая 2011

GalaSoft.MvvmLight имеет следующий код для проверки имени свойства перед вызовом события PropertyChanged.

public void VerifyPropertyName(string propertyName)
{
    if (GetType().GetProperty(propertyName) == null)
        throw new ArgumentException("Property not found", propertyName);
}

GetType().GetProperty("Item[]") очевидно возвращает ноль.
Вот почему это терпит неудачу.

Я думаю, самым быстрым обходным путем для вас было бы не использовать ViewModelBase из этой библиотеки, а реализовать собственную версию, которая не выполняет эту проверку:

public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void RaisePropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

Если вы реализуете этот класс, вы сможете запустить RaisePropertyChanged("Item[]").

2 голосов
/ 21 мая 2011

Проблема в том, что вы используете индексатор , а не обычное свойство .Хотя подсистема привязки поддерживает индексаторы, MVVMLight и INotifyPropertyChanged нет.

Если вы хотите использовать индексатор, вам необходимо:

  • Использовать коллекциюбазовый класс, такой как ObservableCollection<T>
  • Реализация INotifiyCollectionChanged и повышение этого события вместо

Первый вариант нереалистичен, поскольку вы уже производны отViewModelBase и должен продолжать это делать.Поскольку реализация INotifiyCollectionChanged - это небольшая работа, самый простой подход заключается в следующем:

  • добавить свойство к RadioButtonSwitch, которое является наблюдаемым набором логических значений (ObservableCollection<bool>)

Затем измените свою привязку, чтобы добавить еще один элемент пути, и все готово.

Редактировать:

На основании вашего комментария и перечитав ваш вопрос,Я думаю, что реализация INotifyCollectionChanged является самой простой.Вот переписывание вашего RadioButtonSwitch класса, который на самом деле больше не нужно наследовать от базового класса MVVMLight , хотя вы все равно можете, если хотите.

Внимательный читатель заметит, чтомы используем кувалду и «сбрасываем» всю коллекцию при изменении любого элемента коллекции.Это не просто лень;это потому, что индексатор использует строковый индекс вместо целочисленного индекса, а INotifyCollectionChanged не поддерживает это.В результате, когда что-то меняется, мы просто поднимаем руки и говорим, что вся коллекция изменилась.

public class RadioButtonSwitch : INotifyCollectionChanged
{
    public event NotifyCollectionChangedEventHandler CollectionChanged;

    protected void RaiseCollectionChanged()
    {
        if (CollectionChanged != null)
            CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
    }

    IDictionary<string, bool> _options;
    public RadioButtonSwitch(IDictionary<string, bool> options)
    {
        this._options = options;
    }

    public bool this[string a]
    {
        get
        {
            return _options[a];
        }
        set
        {
            if (value)
            {
                var other = _options.Where(p => p.Key != a).Select(p => p.Key).ToArray();
                foreach (string key in other)
                    _options[key] = false;
                _options[a] = true;

                RaiseCollectionChanged();
            }
            else
                _options[a] = false;
        }
    }
}
...