其實C#版本微軟已經實現了,大家可以在VS2012上面去找找,方法是:新建-〉Online-〉Templates-〉Visual C#,右邊選項欄里面就有這個Variable Sized Grid Template了,創建之后,部署,運行,你就可以得到一個類似于Windows Store 的Ui,下面看兩張圖吧,我們講究有圖有真相。
1. 找到這個Template:

2. 運行效果:

這個Template中的代碼我感覺有點繞圈圈,不知道它為什么這么做,但是可以實現這種效果,我會試著來講解一下代碼的具體意思。
先把代碼帖出來:
1 public ref class VariableGridView sealed : public Windows::UI::Xaml::Controls::GridView
2 {
3 public:
4 property Platform::String^ ItemRowSpanPropertyPath
5 {
6 Platform::String^ get()
7 {
8 return safe_cast<Platform::String^>(GetValue(ItemRowSpanPropertyPathProperty));
9 }
10 void set(Platform::String^ value)
11 {
12 SetValue(ItemRowSpanPropertyPathProperty, value);
13 }
14 }
15 static property Windows::UI::Xaml::DependencyProperty^ ItemRowSpanPropertyPathProperty
16 {
17 Windows::UI::Xaml::DependencyProperty^ get();
18 }
19
20
21
22 property Platform::String^ ItemColSpanPropertyPath
23 {
24 Platform::String^ get()
25 {
26 return safe_cast<Platform::String^>(GetValue(ItemColSpanPropertyPathProperty));
27 }
28 void set(Platform::String^ value)
29 {
30 SetValue(ItemColSpanPropertyPathProperty, value);
31 }
32 }
33 static property Windows::UI::Xaml::DependencyProperty^ ItemColSpanPropertyPathProperty
34 {
35 Windows::UI::Xaml::DependencyProperty^ get();
36 }
37 protected:
38 virtual void PrepareContainerForItemOverride(Windows::UI::Xaml::DependencyObject^ element, Platform::Object^ item) override;
39 private:
40 static Windows::UI::Xaml::DependencyProperty^ _itemRowSpanPropertyPathProperty;
41 static Windows::UI::Xaml::DependencyProperty^ _itemColSpanPropertyPathProperty;
42
43 };
2 {
3 public:
4 property Platform::String^ ItemRowSpanPropertyPath
5 {
6 Platform::String^ get()
7 {
8 return safe_cast<Platform::String^>(GetValue(ItemRowSpanPropertyPathProperty));
9 }
10 void set(Platform::String^ value)
11 {
12 SetValue(ItemRowSpanPropertyPathProperty, value);
13 }
14 }
15 static property Windows::UI::Xaml::DependencyProperty^ ItemRowSpanPropertyPathProperty
16 {
17 Windows::UI::Xaml::DependencyProperty^ get();
18 }
19
20
21
22 property Platform::String^ ItemColSpanPropertyPath
23 {
24 Platform::String^ get()
25 {
26 return safe_cast<Platform::String^>(GetValue(ItemColSpanPropertyPathProperty));
27 }
28 void set(Platform::String^ value)
29 {
30 SetValue(ItemColSpanPropertyPathProperty, value);
31 }
32 }
33 static property Windows::UI::Xaml::DependencyProperty^ ItemColSpanPropertyPathProperty
34 {
35 Windows::UI::Xaml::DependencyProperty^ get();
36 }
37 protected:
38 virtual void PrepareContainerForItemOverride(Windows::UI::Xaml::DependencyObject^ element, Platform::Object^ item) override;
39 private:
40 static Windows::UI::Xaml::DependencyProperty^ _itemRowSpanPropertyPathProperty;
41 static Windows::UI::Xaml::DependencyProperty^ _itemColSpanPropertyPathProperty;
42
43 };
這里有幾個概念,今天先說一下Dependecy Property 這個東西吧,其他的下次繼續:
1. 我現在接觸到的Dependency Property,就是依賴屬性,主要用來進行數據綁定。我們知道WinRT一個比較重要的功能就是數據的綁定,而綁定的目標(target)屬性必須為依賴屬性屬性,而源(source)則沒有要求,你可以是依賴屬性,也可以不是依賴屬性。這部分內容我在MVVM那一張已經翻譯過了。源和目標都是依賴屬性的好處是,在binding的時候WinRT會自動地幫你做一些事情,這樣源屬性改變,目標屬性會立即改變。如果源屬性不是依賴屬性,那么,包含該屬性的類必須實現 INotifyPropertyChanged 這個借口,不然,就不行了。
2. 依賴屬性的定義有一套的流程。首先,我們看代碼中,在私有域:需要有一個靜態的DependencyProperty 變量,在公共域:需要一個對應的靜態DependencyProperty屬性。注意,一個是變量,一個是屬性,公共域的要有一個Property關鍵字。私有域的這個變量作為公共域屬性的back store。
另外,為了方便存取,還需要一個額外的屬性來獲得這個依賴屬性。注意到:DependecyProperty 屬性只有get()方法,相關屬性的set()、get()方法中分別調用SetValue(),GetValue(),方法。
頭文件中就需要這些東西,還沒有結束,聲明完依賴屬性,我們還需要注冊,讓WinRT這個綁定系統知道有這么一個類,有這樣一個依賴屬性。注冊的代碼如下:
1 DependencyProperty^ VariableGridView::_itemColSpanPropertyPathProperty =
2 DependencyProperty::Register("ItemColSpanPropertyPath", TypeName(String::typeid), TypeName(VariableGridView::typeid),
3 ref new PropertyMetadata(nullptr));
注冊完,這個類就有了一個依賴屬性了。2 DependencyProperty::Register("ItemColSpanPropertyPath", TypeName(String::typeid), TypeName(VariableGridView::typeid),
3 ref new PropertyMetadata(nullptr));
不錯,現在我們實現了這個類的一半了,為了達到可變尺寸的GridView,還有另一個重載方法是必不可少的。不過我打算明天再跟大家分享了,今天要早點回家做飯啦。哈哈。先把代碼貼上,C++的代碼跟C#很類似,
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 }
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 }
下期預告:即使完成了上面的兩步,其實還沒有完全實現VariableSized GridView,還需要在XAML文件中進行相應的修改,下期將介紹其余的部分。