2011-05-21 219 views
2

我具有以下类我使用的单选按钮结合C# - 动态属性和RaisePropertyChanged

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()在我的类。我不确定为了改变这个变化我应该投入什么样的价值。

我试图把:

  • 项目[]
  • 一个
  • [A]

我不断收到以下错误:

Error

这是如此,如果有任何改变,我可以在我看来相应地处理它。请不要给我的解决方案为单选按钮等列表

+0

定义了“ViewModelBase”的位置? – 2011-05-21 02:40:59

+0

'ViewModelBase'扩展了'GalaSoft.MvvMLight'' ViewModelBase'。它实现了'INotifyPropertyChanged'。 'RaisePropertyChanged'几乎只是调用'if(PropertyChanged!= null)PropertyChanged(this,new PropertyChangedEventArgs(property));' – Luke 2011-05-21 02:44:56

+0

嗯,那么错误*来自哪里?你可以发布完整的堆栈跟踪吗? – 2011-05-21 02:46:50

回答

2

的问题是,你正在实施索引,不是一个普通的财产。尽管绑定子系统支持索引器,但是不包括MVVletightINotifyPropertyChanged

如果你想使用你需要一个索引:

  • 使用集合类如ObservableCollection<T>
  • 实施INotifiyCollectionChanged,提高事件,而不是

第一个选项是不现实的,因为你已经从ViewModelBase派生,并且必须继续这样做。自从实施INotifiyCollectionChanged是工作的一点点,最简单的方法是:

  • 属性添加到RadioButtonSwitch这是一个布尔值的可观察集合(ObservableCollection<bool>

然后改变你绑定添加多一个路径元素,你就完成了。

编辑:

基于您的评论和重读你的问题,我想实现INotifyCollectionChanged是最简单的。这里是你的RadioButtonSwitch类的重写,它实际上不再需要从基类中派生出来,尽管如果你愿意的话,你仍然可以这样做。

细心的读者会注意到,当收集的任何元素被修改时,我们使用大锤并“重置”整个集合。这不仅仅是懒惰;这是因为索引器使用字符串索引而不是整数索引,并且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; 
     } 
    } 
} 
+0

第二个选项听起来不错。不过,我不知道如何绑定到ObservableCollection的特定行。你有什么例子吗? – Luke 2011-05-21 06:17:44

+0

我会为你添加一些代码。 – 2011-05-21 06:30:42

+0

太好了,我就是这么想的! – Luke 2011-05-21 22:08:50

2

GalaSoft.MvvmLight在提升PropertyChanged事件之前检查属性名称。

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[]")

+0

我不想从头开始实现一切,也不想改变其他地方使用的现有方法。 – Luke 2011-05-21 06:25:45