本來打算用MVVM實現CRUD操作的,這方面例子網上資源還挺多的,畢竟CRUD算是基本功了,因爲最近已經開始學習Cailburn框架了,感覺時間
挺緊的,這篇就實現其中的更新操作吧。
功能很明確,當我們更改DataGrid中的CheckBox時,將源中當前發生變化的數據項在界面上顯示出來。我們仍然在前面項目的基礎上實現這個功能
首先我們需要給實體Person類添加一個Bool的屬性,因爲這裏我們只對這個屬性值操作,所以對於age,name屬性也就無必要實現更改通知了
public class Person:INotifyPropertyChanged
{
public int age { get; set; }
public string name { get; set; }
private bool _isBoy;
public bool IsBoy
{
get { return _isBoy; }
set { _isBoy = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("IsBoy"));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
我們仍然從Persons中獲取數據集合,這裏我們因爲操作時源集合將發生變化,所以這裏我們繼承了ObservableCollection<T>類
public class Persons:ObservableCollection<Person>
{
public Persons() : base()
{
}
public new event PropertyChangedEventHandler PropertyChanged;
public new void Add(Person person)
{
//添加項時自動綁定,並且向上傳遞發生改變的屬性
((INotifyPropertyChanged)person).PropertyChanged += (obj, e) =>
{
if (PropertyChanged != null)
{
PropertyChanged(obj, new PropertyChangedEventArgs(e.PropertyName));
}
};
base.Add(person);
}
}
這裏的Persons類通過new關鍵字隱藏了ObservableCollection<Person>原來的事件和方法,在Persons類中這裏我們還需要
添加一個獲取源數據的集合
public Persons GetPerson()
{
//獲取數據源集合
Persons getAllpersons = new Persons();
for (int i = 1; i < 4; i++)
{
getAllpersons.Add(new Person() {age=i,name="Student"+i,IsBoy=true});
}
return getAllpersons;
}
現在對於Model我們已經完成了工作,下面就是修改ViewModel了,這個部分其實沒有太大的變化
public Persons GetPersons { get; set; }
public PageViewModel()
{
GetPersons = new Persons().GetPerson();
//數據源發生變化時的操作
GetPersons.PropertyChanged += (obj, e) =>
{
Person person = (Person)obj;
MessageBox.Show(string.Format("CurrentDetailes:{0},{1},{2}",person.name,person.age,person.IsBoy));
};
}
我們對於這個GetPersons這個源集合進行了一個操作,就是當它的屬性發生變化時執行一個動作,這裏我們只是用對話框將當前項顯示出來
對於UI,我們仍然只是用之前的Xaml
<data:DataGrid ItemsSource="{Binding GetPersons}" AutoGenerateColumns="True" Height="200" HorizontalAlignment="Left" Name="dataGrid1" />
最後我們將View和Model都放入MainPage頁面中
<UserControl.Resources>
<vm:PageViewModel x:Key="model"></vm:PageViewModel>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White" DataContext="{StaticResource model}">
<viw:PageView></viw:PageView>
</Grid>
好了,這樣我們的功能就實現了。不過在這裏我們還是可以考慮一點東西的,真實情況是我們的實體類不會只是一個,那麼我們就要重複爲每一個實體類實現ObservableCollection<T> 類了,這時可能你已經想到用泛型了,我們把集合用泛型實現.
對於Persons類,我們將其改爲泛型集合
public class ViewModelCollection<T> : ObservableCollection<T>
{
public ViewModelCollection() : base()
{
}
public new void Add(T item)
{
((INotifyPropertyChanged)item).PropertyChanged += new PropertyChangedEventHandler(ViewModelCollection_PropertyChanged);
base.Add(item);
}
public new event PropertyChangedEventHandler PropertyChanged;
void ViewModelCollection_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
{
PropertyChanged(sender, new PropertyChangedEventArgs(e.PropertyName));
}
} }
ViewModel中:
public ViewModelCollection<Person> GetPersons{get;set;}
public PageViewModel()
{
GetPersons = GetMan();
//數據源發生變化時的操作
GetPersons.PropertyChanged += (obj, e) =>
{
Person person = (Person)obj;
MessageBox.Show(string.Format("CurrentDetailes:{0},{1},{2}", person.name, person.age, person.IsBoy));
};
}
public static ViewModelCollection<Person> GetMan()
{
//獲取數據源集合
ViewModelCollection<Person> getAllpersons = new ViewModelCollection<Person>();
for (int i = 1; i < 4; i++)
{
getAllpersons.Add(new Person() { age = i, name = "Student" + i, IsBoy = true });
}
return getAllpersons;
}
整體上的是一致的,只不過之前,因爲實體類單一,所以我一直將數據源固定在Model模塊中的,那麼用泛型之後,我就將這個獲取數據源的行爲就移動到對應的ViewModel中了,這樣實現更爲優雅一些。
其實通過這個循序漸進的過程,很容易讓人感覺的到,從開始到現在除非我們需求的改變,很少修改UI,幾乎大部分重構或者修改都是在ViewModel中實現,這個也的確讓人體會到UI與邏輯分離帶來的方便之處,同時經過MVVM的分離形式,我感覺對於程序的調試也比先前容易定位。
的確,MVVM模式如果再結合一些主流的框架,可以完成許多豐富的功能,當然這已經是另一個話題了,這裏僅僅實現了更新功能,關於MVVM模式的CRUD的完整實現可以參考網上的資源,也可以參考這篇文章。
代碼下載:UpdateByMVVM VS2010+SL3