1

目前我正在将我的视图控件直接绑定到我的模型。

但我想: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,如果替换了项目列表中的项目,则会发生这种情况。

4

1 回答 1

0

那么你可以实现 IDisposible。

public class ViewModel : DependencyObject, IDisposable
{
    public Model Model { get; private set; }

    public ViewModel(Model _model)
    {
        Model = _model;
        Model.PropertyChanged += OnModelPropertyChanged;
    }

    ~ViewModel()
    {
        Dispose(false);
    }

    void OnModelPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        // .. here - I would modify this ViewModels dependency properties
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SupressFinalize();
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing) 
        {
            if (Model != null)
                Model.PropertyChanged -= OnModelPropertyChanged;
        }
    }
}

如果您想知道实施。你可以在这里找到一些信息。您还必须取消分配视图中的回调。

public partial class View : UserControl
{
    public View()
    {
        Unloaded += OnUnloaded;
        InitializeComponent();
    }

    void OnUnloaded(object sender, RoutedEventArgs e)
    {
        if (DataContext != null)
        {
            (DataContext as ViewModel).Dispose();
        }
        Unloaded -= OnUnloaded; // <---
    }
}
于 2013-06-24T05:30:47.817 回答