2013-06-23 69 views
1

目前我將我的視圖控制直接綁定到我的模型。清理自動創建視圖模型

但我想: 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是'Model'類型數據的集合,我將其轉換爲視圖可以綁定到的'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中的屬性更改事件。我認爲最好的地方是在視圖的卸載事件中,但希望你的想法。

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

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

編輯:我想我還需要調用Dispose時的景觀變化,如果在項目列表中的項目被換下這將發生在DataContext。

回答

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

如果你想知道實施。你可以找到一些信息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; // <--- 
    } 
} 
+0

謝謝。將您的建議作爲後備,以便事件始終未註冊是很好的選擇。雖然我的問題更多的是關於什麼時候「Dispose」的最佳位置。 – pastillman

+0

*我現在的問題是如何處置ViewModel,以便它可以取消註冊ViewModel中的屬性更改事件。我認爲最好的地方是在視圖的卸載事件中,但是會喜歡你的想法。* - 嗯,沒關係,但下一次你應該強調你的問題。我只讀了第一部分,因爲你的實現不完全正確。並在你的文本牆上; o)如果你問我,你的方法已經很好。爲什麼要尋找另一個,如果它的工作,並實施了一個非常好的方式?我想我會以同樣的方式去做。 – DHN

+0

感謝您的意見:) – pastillman