清理自动创建的View Model

时间:2013-06-23 09:53:32

标签: wpf viewmodel

目前我正在将我的View Control直接绑定到我的模型。

但我想: a)提供比模型中公开的事件/属性更多的事件/属性。 b)根据更适合视图的模型数据提供属性

为此,我决定在其间引入一个层,我称之为ViewModel(不确定这是否适用于术语ViewModel)

我的场景中ViewModel的工作是订阅模型公开的所有事件,并使用这些事件来修改ViewModel中的依赖项属性。

我这样做了如下。

<ItemsControl ItemsSource="{Binding Items}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <local:View DataContext="{Binding Converter={StaticResource modelToViewModel}}"/>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>

此处,Items是“模型”类型数据的集合,我将其转换为视图可以绑定到的“ViewModel”类型。

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中属性更改的事件。我认为最好的地方就是View的卸载事件,但是想要你的想法。

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

        void OnUnloaded(object sender, RoutedEventArgs e)
        {
            if (DataContext != null)
            {
                (DataContext as ViewModel).Dispose();
            }
        }
    }

编辑:我想我还需要在视图的datacontext发生更改时调用dispose,如果替换了Items列表中的Item,就会发生这种情况。

1 个答案:

答案 0 :(得分:0)

你可以实现IDisposable。

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;
        }
    }
}

如果您对实施感到疑惑。您可以找到一些信息here。您还必须在视图中分配回调。

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; // <---
    }
}