INotifyCollectionChanged在上一篇讲了《[Silverlight入门系列]使用MVVM模式(1):MVVM核心概念 》,今天讲一下集合Model。所谓集合Model就是给ItemsControl,如DataGrid,Combobox等绑定的集合数据模型。另外,通过定制ItemsControl的数据模板(DataTemplate),还可以控制集合对象中每一项的显示。实现很简单,但数据源集合对象必须继承IEnumerable接口,为了让目标属性与数据源集合的更新(不但包括元素的修改,还包括元素的增加和删除)保持同步,数据源集合还必须实现INotifyPropertyChanged接口和INotifyCollectionChanged接口。
ObservableCollection
在Silverlight中创建数据源集合可以使用内建的ObservableCollection类,因为ObservableCollection类既实现了INotifyPropertyChanged接口,又实现了INotifyCollectionChanged接口。使用ObservableCollection类不但可以实现Add、Remove、Clear和Insert操作,还可以触发PropertyChanged事件。
1
using
System.Collections.ObjectModel;
2
using
System.Collections;
3
4
public
class
MyModelCollection : ObservableCollection
<
MyModel
>
5
{
6
public
MyModelCollection()
7
{
8
}
9
10
public
MyModelCollection(IEnumerable MyModels)
11
{
12
foreach
(MyModel h
in
MyModels)
13
this
.Add(h);
14
}
15
16
public
void
AddRange(IEnumerable MyModels)
17
{
18
foreach
(MyModel h
in
MyModels)
19
this
.Add(h);
20
}
21
}
22
23
public
class
MyModel
24
{
25
public
int
ModelID {
get
;
set
; }
26
public
string
ModelName {
get
;
set
; }
27
}
28
29
public
class
MyViewModel
30
{
31
public
MyModelCollection MyModelDataCollection {
get
;
set
; }
32
public
MyViewModel(MyModelCollection modelCollection)
33
{
34
MyModelDataCollection
=
modelCollection;
35
}
36
}
集合Model绑定到ItemControl也很简单:
1
private
MyViewModel viewModel;
2
3
public
MainPage()
4
{
5
InitializeComponent();
6
7
MyModel m1
=
new
MyModel() { ModelID
=
1
, ModelName
=
"
abc
"
};
8
MyModel m2
=
new
MyModel() { ModelID
=
2
, ModelName
=
"
def
"
};
9
10
viewModel
=
new
MyViewModel(
new
MyModelCollection(
new
List
<
MyModel
>
() { m1, m2 }));
11
12
this
.DataContext
=
viewModel;
13
14
this
.dataGrid1.ItemsSource
=
viewModel.MyModelDataCollection;
15
this
.dataGrid1.AutoGenerateColumns
=
true
;
16
17
this
.comboBox1.ItemsSource
=
viewModel.MyModelDataCollection;
18
this
.comboBox1.DisplayMemberPath
=
"
ModelName
"
;
19
this
.comboBox1.SelectedValuePath
=
"
ModelID
"
;
20
21
this
.comboBox1.SelectionChanged
+=
new
SelectionChangedEventHandler(comboBox1_SelectionChanged);
22
}
23
24
void
comboBox1_SelectionChanged(
object
sender, SelectionChangedEventArgs e)
25
{
26
this
.textBlock1.Text
=
"
Selected value:
"
+
this
.comboBox1.SelectedValue;
27
}
ICollectionView / PagedCollectionView
虽然上述的ObservableCollection很好用而且继承了INotifyPropertyChanged接口,有些时候我们需要对集合进行排序、过滤、分页等操作,这个时候就需要用ICollectionView接口,同样继承了
INotifyCollectionChanged接口。ICollectionView接口在Silverlight下有个子类:PagedCollectionView,在WPF下有个子类:ListCollectionView.
PagedCollectionView例子:
C#:
1
public
class
MyViewModel : INotifyPropertyChanged
2
{
3
public
ICollectionView Customers {
get
;
private
set
; }
4
5
public
MyViewModel( ObservableCollection
<
Customer
>
customers )
6
{
7
//
Initialize the CollectionView for the underlying model
8
//
and track the current selection.
9
Customers
=
new
PagedCollectionView( customers );
10
Customers.CurrentChanged
+=
11
new
EventHandler( SelectedItemChanged );
12
}
13
14
private
void
SelectedItemChanged(
object
sender, EventArgs e )
15
{
16
Customer current
=
Customers.CurrentItem
as
Customer;
17
...
18
}
19
}
XAML:
1
<
ListBox
ItemsSource
="
{Binding Path=Customers}
"
>
2
<
ListBox.ItemTemplate
>
3
<
DataTemplate
>
4
<
StackPanel
>
5
<
TextBlock
Text
="
{Binding Path=Name}
"
/>
6
</
StackPanel
>
7
</
DataTemplate
>
8
</
ListBox.ItemTemplate
>
9
</
ListBox
>