Windows 8 学习笔记(四)--创建Variable Sized GridView之PrepareContainerForItemOverride方法
前情提要:若要实现一个类似于Windows Store的界面的话,这个类必须要先继承自GridView,并且要重写PrepareContainerForItemOverride方法。微软提供的模板中又给出了两个依赖属性来帮助我们完成这种可变尺寸的GridView。下面我们来看看重载的PrepareContainerForItemOverride方法都做了些什么。
首先来看微软官方给出的该方法的描述:
Prepares the specified element to display the specified item.
用特定的元素来显示特定的项。
怎么理解?看代码理解:
1
protected
:
2 virtual void PrepareContainerForItemOverride(
3 DependencyObject ^ element,
4 Object ^ item
5 )
6
2 virtual void PrepareContainerForItemOverride(
3 DependencyObject ^ element,
4 Object ^ item
5 )
6
element: The element that's used to display the specified item.
item: The item to display.
即,用此element来表现该item,继而显示这个item。一般情况下,我们的GridView里面都会有N个Item,那么,该方法会执行N遍,使每个Item都能被设定。即我们的GridView就是Container:
1
void
VariableGridView::PrepareContainerForItemOverride(DependencyObject
^
element, Platform::Object
^
item)
2 {
3 GridView::PrepareContainerForItemOverride(element, item);
4 auto viewMode = (Data::DataItem ^ )(item);
5 UIElement ^ uiElement = safe_cast < UIElement ^> (element);
6
7 Binding ^ colBinding = ref new Binding();
8 colBinding -> Source = viewMode;
9 colBinding -> Path = ref new PropertyPath( this -> ItemColSpanPropertyPath);
10 BindingOperations::SetBinding(uiElement,VariableSizedWrapGrid::ColumnSpanProperty, colBinding);
11
12
13 Binding ^ rowBinding = ref new Binding();
14 rowBinding -> Source = viewMode;
15 rowBinding -> Path = ref new PropertyPath( this -> ItemRowSpanPropertyPath);
16 BindingOperations::SetBinding(uiElement,VariableSizedWrapGrid::RowSpanProperty, rowBinding);
17 }
第3行: 先调用父类方法进行基础操作(具体不清楚做什么,但是这一步必须要有,可以放在最前,也可以放在最后)。
2 {
3 GridView::PrepareContainerForItemOverride(element, item);
4 auto viewMode = (Data::DataItem ^ )(item);
5 UIElement ^ uiElement = safe_cast < UIElement ^> (element);
6
7 Binding ^ colBinding = ref new Binding();
8 colBinding -> Source = viewMode;
9 colBinding -> Path = ref new PropertyPath( this -> ItemColSpanPropertyPath);
10 BindingOperations::SetBinding(uiElement,VariableSizedWrapGrid::ColumnSpanProperty, colBinding);
11
12
13 Binding ^ rowBinding = ref new Binding();
14 rowBinding -> Source = viewMode;
15 rowBinding -> Path = ref new PropertyPath( this -> ItemRowSpanPropertyPath);
16 BindingOperations::SetBinding(uiElement,VariableSizedWrapGrid::RowSpanProperty, rowBinding);
17 }
第4行: 要显示的Item。 我们的Item都是Data::DataItem类型的,所以要进行类型转换。这里注意,WinRT中所有的类都是从Platform::Object^ 继承而来,我们可以用(DataItem^)(item)进行转换,也可以用safe_cast<DataItem^>(item)来进行转换。
第5行: 指定的element。这里转换成UIElement类型。
7--10行:将绑定的source(源)设置为我们的item,绑定的path(路径)设置为VariableSizedGridView的ItemColSpanPropertyPath。这里容易产生混淆:一般情况下,我们在进行数据绑定的时候,path一般是source的一个属性,比如说,一般情况下应该是 类似于这样:colBinding->Source = viewMode; colBinding->Path = ref new PropertyPath(viewMode->propertyOfViewMode); 这里竟然设置成了另外一个类的属性,所以之前我迷惑了很长一段时间。但是如果你去XAML文件里面看一下的话,就知道它为什么这么做了。我们先不要着急看XAML文件,还有第10行。
Associates a Binding with a target property on a target object. This method is the code equivalent to declaring a {Binding} in markup.
将目标对象的目标属性进行绑定。
1
2 public :
3 static void SetBinding(
4 DependencyObject ^ target,
5 DependencyProperty ^ dp,
6 BindingBase ^ binding
7 )
8
9
2 public :
3 static void SetBinding(
4 DependencyObject ^ target,
5 DependencyProperty ^ dp,
6 BindingBase ^ binding
7 )
8
9
第10行的意思是说:将uiElment的VariableSizedWrapGrid::ColumnSpan属性同该item的itemColSpanPropertyPath进行绑定。但是item没这个属性。现在是时候来看看XAML文件了:
1
<
common:VariableGridView
2 x:Name ="itemGridView"
3 AutomationProperties.AutomationId ="ItemGridView"
4 AutomationProperties.Name ="Grouped Items"
5 Padding ="0"
6 ItemsSource ="{Binding Source={StaticResource groupedItemsViewSource}}"
7 ItemTemplateSelector ="{StaticResource myDataTemplateSelector}"
8 SelectionMode ="None"
9 IsSwipeEnabled ="false"
10 IsItemClickEnabled ="True"
11 ItemClick ="ItemView_ItemClick"
12 ItemColSpanPropertyPath ="ColumnSpan"
13 ItemRowSpanPropertyPath ="RowSpan" Grid.Row ="2"
14 Margin ="30,20,20,10" ItemTemplate ="{StaticResource BigDateTemplate}" >
2 x:Name ="itemGridView"
3 AutomationProperties.AutomationId ="ItemGridView"
4 AutomationProperties.Name ="Grouped Items"
5 Padding ="0"
6 ItemsSource ="{Binding Source={StaticResource groupedItemsViewSource}}"
7 ItemTemplateSelector ="{StaticResource myDataTemplateSelector}"
8 SelectionMode ="None"
9 IsSwipeEnabled ="false"
10 IsItemClickEnabled ="True"
11 ItemClick ="ItemView_ItemClick"
12 ItemColSpanPropertyPath ="ColumnSpan"
13 ItemRowSpanPropertyPath ="RowSpan" Grid.Row ="2"
14 Margin ="30,20,20,10" ItemTemplate ="{StaticResource BigDateTemplate}" >
我们看到ItemColSpanPropertyPath被赋值成了ColumnSpan,而item中正好有这么个属性:
1
namespace
Data
2 {
3 [Windows::UI::Xaml::Bindable]
4 public ref class DataItem
5 {
6 //
7 //
8 property int RowSpan{ int get (); void set ( int );}
9 property int ColumnSpan{ int get (); void set ( int );}
10 //
11 //
12 };
13 }
2 {
3 [Windows::UI::Xaml::Bindable]
4 public ref class DataItem
5 {
6 //
7 //
8 property int RowSpan{ int get (); void set ( int );}
9 property int ColumnSpan{ int get (); void set ( int );}
10 //
11 //
12 };
13 }
那么一切都说的过去了,原来绑定的Source是DataItem,path是ColumnSpan。
那么这个重载的方法的最终目的就相当于是这么一个语句:
那么这个重载的方法的最终目的就相当于是这么一个语句:
1
<
common:VariableGridView VariableSizedWrapGrid.ColumnSpan
=
"
{Binding Source={data::DataItem}, Path=ColumnSpan}
"
/>
即,在初始化DataItem的时候,只要设置了ColumnSpan这个值,就能使这个Item的列进行相应地改变。
其实整个过程非常之简单,我们的目的就只是上面的一个语句而已,为了达到这个目的,我们设置了两个依赖属性来接收字符串,并且重载PrepareContainerForItemOverride方法进行绑定。大家可以通过示例代码进行领会。
OK,这一篇是补上周六的。尽量做到每天一篇,保质保量。
下期提示:刚刚看过了微软提供的模板,下一篇讲述我们自己的方法。该方法同微软的方法大同小异,但是,是网上的一位牛人自己写的,他也是用C#写出来,我把它改成C++版本。