我正在为另一个应用程序创建配置编辑器,并使用反射来从配置类中提取可编辑字段。以下类是我的各种“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);
}
});
}
}
正如您在构造函数中看到的,我当前将“Value”镜像到一个名为“ObservableValue”的新ObservableCollection中,然后由XAML中的ListView绑定。它以这种方式运行良好,但克隆List似乎是这样一种hacky方式。虽然绑定到Value,但我尝试添加:
RaisePropertyChanged("Value");
到AddItemCommand和RemoveItemCommand,但这不起作用,ListView将不会更新。这样做的正确方法是什么?
答案 0 :(得分: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
复制了此内容