2010-04-15 64 views
2

我正在为另一个应用程序制作配置编辑器,并且正在使用反射从配置类中提取可编辑的字段。以下类是我的各种“DataTypeViewModels”的基类,并显示了我如何获取和设置适当的属性。如何在这种情况下模拟可观察集合的影响?

public abstract class DataTypeViewModel<T> : ViewModelBase 
{ 
    Func<T> getFunction; 

    Action<T> setAction; 

    public const string ValuePropertyName = "Value"; 

    public string Label { get; set; } 

    public T Value 
    { 
     get 
     { 
      return getFunction.Invoke(); 
     } 

     set 
     { 
      if (getFunction.Invoke().Equals(value)) 
      { 
       return; 
      } 

      setAction.Invoke(value); 

      // Update bindings, no broadcast 
      RaisePropertyChanged(ValuePropertyName); 
     } 
    } 

    /// <summary> 
    /// Initializes a new instance of the StringViewModel class. 
    /// </summary> 
    public DataTypeViewModel(string sectionName, string label) 
    { 
     if (IsInDesignMode) 
     { 
      // Code runs in Blend --> create design time data. 
     } 
     else 
     { 
      Label = label; 

      getFunction = new Func<T>(() => 
       { 
        return (T)Settings.Instance.GetType().GetProperty(sectionName).PropertyType. 
         GetProperty(label).GetValue(Settings.Instance.GetType().GetProperty(sectionName).GetValue(Settings.Instance, null), null); 
       }); 

      setAction = new Action<T>(value => 
       { 
        Settings.Instance.GetType().GetProperty(sectionName).PropertyType.GetProperty(label). 
         SetValue(Settings.Instance.GetType().GetProperty(sectionName).GetValue(Settings.Instance, null), value, null); 
       }); 
     } 
    } 
} 

这部分以我想要的方式工作,下一部分是字符串列表中的示例DataTypeViewModel。

public class StringListViewModel : DataTypeViewModel<ICollection<string>> 
{ 
    /// <summary> 
    /// The <see cref="RemoveItemCommand" /> property's name. 
    /// </summary> 
    public const string RemoveItemCommandPropertyName = "RemoveItemCommand"; 

    private RelayCommand<string> _removeItemCommand = null; 

    public ObservableCollection<string> ObservableValue { get; set; } 

    /// <summary> 
    /// Gets the RemoveItemCommand property. 
    /// TODO Update documentation: 
    /// Changes to that property's value raise the PropertyChanged event. 
    /// This property's value is broadcasted by the Messenger's default instance when it changes. 
    /// </summary> 
    public RelayCommand<string> RemoveItemCommand 
    { 
     get 
     { 
      return _removeItemCommand; 
     } 

     set 
     { 
      if (_removeItemCommand == value) 
      { 
       return; 
      } 

      var oldValue = _removeItemCommand; 
      _removeItemCommand = value; 

      // Update bindings, no broadcast 
      RaisePropertyChanged(RemoveItemCommandPropertyName); 
     } 
    } 

    /// <summary> 
    /// The <see cref="AddItemCommand" /> property's name. 
    /// </summary> 
    public const string AddItemCommandPropertyName = "AddItemCommand"; 

    private RelayCommand<string> _addItemCommand = null; 

    /// <summary> 
    /// Gets the AddItemCommand property. 
    /// TODO Update documentation: 
    /// Changes to that property's value raise the PropertyChanged event. 
    /// This property's value is broadcasted by the Messenger's default instance when it changes. 
    /// </summary> 
    public RelayCommand<string> AddItemCommand 
    { 
     get 
     { 
      return _addItemCommand; 
     } 

     set 
     { 
      if (_addItemCommand == value) 
      { 
       return; 
      } 

      var oldValue = _addItemCommand; 
      _addItemCommand = value; 

      // Update bindings, no broadcast 

      RaisePropertyChanged(AddItemCommandPropertyName); 
     } 
    } 

    /// <summary> 
    /// Initializes a new instance of the StringListViewModel class. 
    /// </summary> 
    public StringListViewModel(string sectionName, string label) : base(sectionName, label) 
    { 
     ObservableValue = new ObservableCollection<string>(Value); 
     AddItemCommand = new RelayCommand<string>(param => 
      { 
       if (param != string.Empty) 
       { 
        Value.Add(param); 
        ObservableValue.Add(param); 
       } 
      }); 

     RemoveItemCommand = new RelayCommand<string>(param => 
      { 
       if (param != null) 
       { 
        Value.Remove(param); 
        ObservableValue.Remove(param); 
       } 
      }); 
    } 
} 

正如你可以在构造函数中看到,我现在有“价值”镜像到一个名为“ObservableValue”新的ObservableCollection,然后通过在XAML一个ListView必然。它的工作方式很好,但克隆List似乎是一件很难办的事情。虽然绑定到的价值,我已经尝试添加:

RaisePropertyChanged("Value"); 

到AddItemCommand和RemoveItemCommand,但这不起作用,ListView控件将不会更新。什么是正确的方法来做到这一点?

回答

2

实施INotifyCollectionChanged它就像NotifyPropertyChanged但使用的ObservableCollection通知上,插入/移除/复位......

public class MyCustomCollection : INotifyCollectionChanged 
    { 
     public event NotifyCollectionChangedEventHandler CollectionChanged; 

     protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e) 
     { 
      if (CollectionChanged != null) 
      { 
       CollectionChanged(this, e); 
      } 
     } 

     public void Add(Object o) 
     { 
      OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, o)); 
     } 

     public void Remove(Object o) 
     { 
      OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, 0)); 
     } 

     public void Clear() 
     { 
      OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); 
     } 

     public void Move(Object o, Int32 newIndex) 
     { 
      Int32 oldIndex = 0; // can get the old index position using collection.IndexOf(o); 
      OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Move, 
       o, newIndex, oldIndex)); 
     } 

     public Object this[Int32 index] 
     { 
      get 
      { 
       return null; // return collection[index]; 
      } 
      set 
      { 
       Object oldValue = null; // get old value using collection[index]; 
       OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, 
        value, oldValue)); 
      } 
     } 
    } 

...我复制这从here

+0

我尝试这样做,NotifyPropertyChanged无一不没有按预期工作。 – MGSoto 2010-04-20 15:59:01

+0

看看上面的编辑,这是你做的? – 2010-04-21 00:41:16

+0

我在适当的调用中添加了add和remove命令,但是我没有创建自定义集合,我使用了基类中的属性,该基类是从子类中模板化的List。 – MGSoto 2010-04-27 23:22:21