目前我正在将我的视图控件直接绑定到我的模型。
但我想:a) 提供比模型中公开的事件/属性更多的事件/属性。b) 提供基于模型数据的更适合视图的属性
所以为了做到这一点,我决定在两者之间引入一个层,我称之为 ViewModel(不确定这是否是 ViewModel 一词的正确用法)
我的场景中 ViewModel 的工作是订阅 Model 暴露的所有事件,并使用这些事件来修改 ViewModel 中的依赖属性。
我这样做如下。
<ItemsControl ItemsSource="{Binding Items}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:View DataContext="{Binding Converter={StaticResource modelToViewModel}}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
在这里,Items 是“模型”类型数据的集合,我将其转换为视图可以绑定到的“视图模型”类型。
public class Model : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
int m_age;
public int Age
{
get { return m_age; }
set { m_age = value; NotifyPropertyChanged("Age"); }
}
void NotifyPropertyChanged(string _property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(_property));
}
}
}
public class ViewModel : DependencyObject
{
public Model Model { get; private set; }
public ViewModel(Model _model)
{
Model = _model;
Model.PropertyChanged += OnModelPropertyChanged;
}
void OnModelPropertyChanged(object sender, PropertyChangedEventArgs e)
{
// .. here - I would modify this ViewModels dependency properties
}
}
public class ModelToViewModel : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return new ViewModel(value as Model);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
我现在遇到的问题是如何处理 ViewModel,以便它可以取消注册 ViewModel 中的属性更改事件。我认为这样做的最佳位置是在视图的卸载事件中,但希望您有想法。
public partial class View : UserControl
{
public View()
{
Unloaded += OnUnloaded;
InitializeComponent();
}
void OnUnloaded(object sender, RoutedEventArgs e)
{
if (DataContext != null)
{
(DataContext as ViewModel).Dispose();
}
}
}
编辑:我想当视图的数据上下文发生更改时,我还需要调用 dispose,如果替换了项目列表中的项目,则会发生这种情况。