2

我有以下用于单选按钮绑定的类

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" />

视图模型

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

我在课堂上遇到 RaisePropertyChanged() 问题。我不确定我应该投入什么价值来提高变革。

我试着把:

  • 物品[]
  • 一种
  • [一种]

我不断收到以下错误:

错误

如果有任何更改,我可以在我的视图中相应地处理它。请不要给我解决单选按钮列表等的解决方案。

4

2 回答 2

2

问题是您正在实现一个索引器,而不是一个普通的属性。尽管绑定子系统支持索引器,但MVVMLightINotifyPropertyChanged并不支持。

如果要使用索引器,您需要:

  • 使用集合基类,例如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;
        }
    }
}
于 2011-05-21T03:30:33.353 回答
2

PropertyChangedGalaSoft.MvvmLight 有以下代码在引发事件之前检查属性名称。

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

GetType().GetProperty("Item[]")显然返回null。
这就是它失败的原因。

我认为,对你来说最快的解决方法是不要使用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[]").

于 2011-05-21T03:40:00.563 回答