我正在为另一个应用程序制作一个配置编辑器,并使用反射从配置类中提取可编辑字段。下面的类是各种“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”镜像到一个名为“observeValue”的新observeCollection中,然后由XAML中的ListView绑定到该集合。这样做效果很好,但克隆列表似乎是一种很难做到的方法。在绑定到值的同时,我尝试添加:
RaisePropertyChanged("Value");
添加到AddItemCommand和removItemCommand,但这不起作用,ListView将不会得到更新。正确的方法是什么?