2012-10-04 283 views
0

我正在使用WPF和MVVM作爲項目。我有一個GridView控件的視圖。用戶可以在網格視圖中插入/更新/刪除。當任何動作發生變化反映在ViewModel。這部分工作正常。但是當我想要保存數據庫中的更改時,我需要逐個循環遍歷ItemSource中的每個Item。這需要花費額外的時間來完成。我只想處理那些變化的項目。如何在MVVM中更改其他屬性時更改屬性

爲了實現這一點,我在我的模型中添加了一個布爾屬性來指示項目是否被更改或註釋。但問題是,我無法看到任何方式來設置此布爾屬性,每當任何其他屬性更改。

任何機構可以幫助我如何做到這一點?

編輯 我有一個SelectedItem屬性,和我假設,每當GridView中選擇了一個項目,用戶將更新或插入的行。所以對SelectedItem屬性我已經將SelectedItem的布爾值屬性設置爲True。並循環保存記錄時,我將保存所有那些在其布爾屬性中爲True的記錄。我知道它不是完美的方式,但現在我沒有其他辦法可以做到了。你的想法?

+0

如何用您的數據庫工作存在嗎?如果你使用了一些ORM,比如實體框架,它會自己跟蹤這些變化,所以你不應該擔心。 – Zabavsky

+0

我沒有使用實體框架。我正在使用System.Data.SqlClient類。 –

回答

1

您可以在您的模型上訂閱PropertyChanged事件並將Flag設置爲True。 但請記住,從數據庫加載數據後,必須將Flag設置爲false,因爲模型的初始化也會調用propertychanged事件。

例與IsDirty標誌類:

public class Sample : INotifyPropertyChanged 
{ 
    private int id; 
    private string name; 
    private bool isDirty; 

    public event PropertyChangedEventHandler PropertyChanged; 

    public int Id 
    { 
     get { return id; } 
     set 
     { 
      if(id != value) 
      { 
       id = value; 
       RaisePropertyChanged("Id"); 
      } 
     } 
    } 

    public string Name 
    { 
     get { return name; } 
     set 
     { 
      if (name != value) 
      { 
       name = value; 
       RaisePropertyChanged("Name"); 
      } 
     } 
    } 

    public bool IsDirty 
    { 
     get { return isDirty; } 
     set 
     { 
      if (isDirty != value) 
      { 
       isDirty = value; 
       RaisePropertyChanged("IsDirty"); 
      } 
     } 
    } 

    protected virtual void RaisePropertyChanged(string propertyName) 
    { 
     if (propertyName != "IsDirty") 
     { 
      IsDirty = true; 
     } 

     var handler = PropertyChanged; 

     if (handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 

如果你正在使用一個ObservableCollection,你還可以添加一個事件處理程序來跟蹤新增或刪除

+0

我不知道如何在我的模型上使用PropertyChanged事件。因爲我到處都可以看到人們在ViewModel上使用它。是的,我正在使用ObservableCollection,但我沒有找到一種方法,當一個屬性被更改? –

+1

可以使用實現INotifyPropertyChanged你的模型就像你在一個視圖模型做的,有在實施無差異。爲了簡化注入所需的通知代碼這個界面我使用NotifyPropertyWeaver(http://visualstudiogallery.msdn.microsoft.com/bd351303-db8c-4771-9b22-5e51524fccd3)的使用。 – doerig

+1

的ObservableCollection不會通知你有關項目的變化,但它會通知你,如果一個項目已被添加或從集合中刪除,所以你可能需要兩,INotifyPropertyChanged的和INotifyCollectionChanged – doerig

1

如果您使用MVVM,您應該執行INotifyPropertyChanged。你可以添加一些邏輯來設置你的布爾屬性OnPropertyChanged處理程序。

+0

是的,我已經實現了INotifyPropertyChanged。 –

2

行如果你願意依賴於編譯時工具,您可以使用ILWeaving完成此工作。

因此,如果您將FodyPropertyChanged插件組合在一起,那麼開箱即可支持IsDirty功能。

然後Martins的例子可以被簡化爲這個

public class Sample : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public bool IsChanged { get; set; } 
} 

注意使用如果IsChanged代替IsDirty

然後這將在編譯的程序集

public class Sample : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    public virtual void OnPropertyChanged(string propertyName) 
    { 
     var propertyChanged = PropertyChanged; 
     if (propertyChanged != null) 
     { 
      propertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    int id; 
    public int Id 
    { 
     get { return id; } 
     set 
     { 
      if (id != value) 
      { 
       id = value; 
       IsChanged = true; 
       OnPropertyChanged("Id"); 
      } 
     } 
    } 

    bool isChanged; 
    public bool IsChanged 
    { 
     get { return isChanged; } 
     set 
     { 
      if (isChanged != value) 
      { 
       isChanged = value; 
       OnPropertyChanged("IsChanged"); 
      } 
     } 
    } 

    string name; 
    public string Name 
    { 
     get { return name; } 
     set 
     { 
      if (!string.Equals(name, value, StringComparison.Ordinal)) 
      { 
       name = value; 
       IsChanged = true; 
       OnPropertyChanged("Name"); 
      } 
     } 
    } 
}