由于最近在等待新工作的入職,閑來無事還是完善一下我的WP8開發的博客吧。經過許久回頭看一下我那半成品的WP應用,內牛滿面,之前Google了N久的東西,居然也不記得了,真是不得不認老啊。
這段時間接觸了一下B/S的東西,覺得那東西真不是人用的,一旦工程量上去,后續開發很大一部分時間都是在Debug中渡過,很是糾結?,F在業內普遍的對移動開發的看法是——web應用是種趨勢,可是個人覺得除非現階段的移動網絡環境有質的改變,否則用戶體驗會很有問題。然后簡單的玩了一下node.js,覺得后臺其實也可以不用那么復雜,想想,還是老老實實的寫回自己的客戶端應用好了。
廢話就不多說了,先簡單的介紹一下本篇的目的吧。MVC這個東西,現下看起來很流行,Model-View-Control,其實我個人并不清楚其概念所謂,其實說白了就是當年的“所見即所得”,一個意思。之前接觸了一下WPF,就是給這個概念給搞死,但不管怎么樣,xaml可能是MS的開發趨勢,MCV又是其中一個極重要的概念,不入門不行。
MVC的更多的概念性解析請諸位百度或google吧,它的核心是數據,MVC是一種展現數據呈現方式的一種開發手段,雖然比純代碼性的呈現方式多了一些額外的工作,可是,必須要記住,現在做多一些是為了將來少做一些,其優勢還是相當可觀的。
(1)構造數據類DataItem
WinForm的項目里,我們想在程序設計的階段預覽ListBox是怎么顯示數據,那幾乎是不可能的,除非我將程序跑起來,在人類審美觀崛起的現在,代碼與界面分離設計可以有效的通過分工實現人力資源的最大化的利用,而這也是MVC的主要任務。
寫WinForm時,我會這么設計一個簡單的數據結構體:
struct TestDataItem { int Index; string Name; boo Flag; }
可使用MVC的方式,編譯器沒辦法識別這樣的定義,所以必須將這簡單的結構體擴展成一個特定的類:
//TestDataItem.cs
using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MvcTest { /// <summary> /// 數據集的Item類,繼承INotifyPropertyChanged,INotifyPropertyChanging接口 /// </summary> public partial class TestDataItem : INotifyPropertyChanged, INotifyPropertyChanging { /// <summary> /// 屬性更改的事件參數 /// </summary> private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty); /// <summary> /// 數據屬性變化的事件回調 /// </summary> public event PropertyChangingEventHandler PropertyChanging; public event PropertyChangedEventHandler PropertyChanged; /// <summary> /// Item的成員屬性 /// </summary> private int _index; private string _name; private bool _flag; /// 屬性更改的響應函數 #region partial void OnIndexChanging(int value); partial void OnIndexChanged(); partial void OnNameChanging(string value); partial void OnNameChanged(); partial void OnFlagChanging(bool value); partial void OnFlagChanged(); #endregion /// 類接口的實現 #region /// <summary> /// INotifyPropertyChanging接口的實現函數 /// </summary> protected virtual void SendPropertyChanging() { if ((this.PropertyChanging != null)) { this.PropertyChanging(this, emptyChangingEventArgs); } } /// <summary> /// INotifyPropertyChanged接口的實現 /// </summary> /// <param name="propertyName"></param> protected virtual void SendPropertyChanged(String propertyName) { if ((this.PropertyChanged != null)) { this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } #endregion /// 數據的公共屬性 #region public int Index { get { return this._index; } set { if(this._index != value) { this.OnIndexChanging(value); this.SendPropertyChanging(); this._index = value; this.SendPropertyChanged("Index"); this.OnIndexChanged(); } } } public string Name { get { return this._name; } set { if(this._name != value) { this.OnNameChanging(value); this.SendPropertyChanging(); this._name = value; this.SendPropertyChanged("Name"); this.OnNameChanged(); } } } public bool Flag { get { return this._flag; } set { if (this._flag != value) { this.OnFlagChanging(value); this.SendPropertyChanging(); this._flag = value; this.SendPropertyChanged("Flag"); this.OnFlagChanged(); } } } #endregion } }
此類的核心是INotifyPropertyChanged,INotifyPropertyChanging這兩個接口(不懂請百度唄,我也懂不了多少)。因為數據的窗口(像Grid或LongListSelector)要感知每一條TestDataItem的屬性變化,然后這個類里面就存在各種的回調或事件啦。
(2)構造數據集TestDataItemCollection
這步理解就簡單一點了,數據容器呈現的是整體的數據集合,這個集合也需要一個特殊的類,否則編譯器不知道怎么去解析(我只能這么理解),有玩過數據綁定的童鞋應該能弄懂這點。
當然,TestDataItem的集合類也需要實現一個特殊的接口INotifyPropertyChanged——沒錯,跟上面TestDataItem實現的接口一樣,可以這么理解,這個接口是MVC的核心所在。
//TestDataItemCollection.cs
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MvcTest { /// <summary> /// 數據集的類 /// </summary> public class TestDataCollection : INotifyPropertyChanged { /// <summary> /// 數據集合 /// </summary> public ObservableCollection<TestDataItem> TestDataItems { get; private set; } /// <summary> /// 屬性更改事件回調 /// </summary> public event PropertyChangedEventHandler PropertyChanged; /// <summary> /// 構造函數 /// </summary> public TestDataCollection() { this.TestDataItems = new ObservableCollection<TestDataItem>(); } /// <summary> /// INotifyPropertyChanged接口的實現 /// </summary> private void NotifyPropertyChanged(String propertyName) { PropertyChangedEventHandler handler = PropertyChanged; if (null != handler) { handler(this, new PropertyChangedEventArgs(propertyName)); } } } }
(3)構造數據集示例ViewModel
這一步設計要呈現的數據例子,其用到的xmal的文件,可是在Visual Studio新建項的時候,并沒有這一選項,可是我們會發現WP的頁面文件格式就xaml的,所以不妨新建一個頁面,將其重命名為TestDataViewModel.xaml,然后,刪掉頁面正面的cs等文件,將下面這段xaml代碼粘上去——當然,你直接手敲上去也是沒有問題的。
//TestDataViewModel.xaml
<!-- 這對應的是數據集的類名,表示一組數據--> <vm:TestDataCollection xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:vm="clr-namespace:MvcTest"> <!--clr-namespace:MvcTest這是數據集的命名空間,帶文件夾的要注意啦--> <!--簡單的數據集例子--> <vm:TestDataCollection.TestDataItems> <vm:TestDataItem Index="0" Name="name1" Flag="False"></vm:TestDataItem> <vm:TestDataItem Index="1" Name="name2" Flag="True"></vm:TestDataItem> <vm:TestDataItem Index="2" Name="name3" Flag="True"></vm:TestDataItem> <vm:TestDataItem Index="3" Name="name4" Flag="False"></vm:TestDataItem> <vm:TestDataItem Index="4" Name="name5" Flag="True"></vm:TestDataItem> <vm:TestDataItem Index="5" Name="name6" Flag="True"></vm:TestDataItem> </vm:TestDataCollection.TestDataItems> </vm:TestDataCollection>
注意看xaml的注釋內容,但看起來不難,難的一步是如何呈現上面的數據集于PhonePage上。
(4)呈現ViewModel數據集
首先,我們要選一個數據容器,個人比較喜歡LongListSelector,但似乎沒有其分的選擇,將上面的數據集例子綁定上去;然后,設計一下單條數據呈現的樣式,要用到DataItemTemplate,這也許我將來會詳講。就這兩條,直接上代碼:
//MainPage.xaml
<phone:PhoneApplicationPage x:Class="MvcTest.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DataContext="{d:DesignData TestDataViewModel.xaml}" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="Portrait" Orientation="Portrait" shell:SystemTray.IsVisible="True"> <!--單條數據顯示的樣式--> <phone:PhoneApplicationPage.Resources> <DataTemplate x:Key="TestDataItemTemplate"> <StackPanel Margin="0,0,0,0"> <TextBlock Text="{Binding Index}"/> <TextBlock Text="{Binding Name}" /> <!--TextBlock Text="{Binding Flag}" /--> <StackPanel Height="1" Background="AliceBlue"></StackPanel> </StackPanel> </DataTemplate> </phone:PhoneApplicationPage.Resources> <Grid x:Name="LayoutRoot" Background="Transparent"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"> <TextBlock Text="我的應用程序" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/> <TextBlock Text="頁面名稱" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/> </StackPanel> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <!--用一個LongListSelector來顯示數據集--> <StackPanel> <phone:LongListSelector Margin="0,0,0,0" ItemTemplate="{StaticResource ResourceKey=TestDataItemTemplate}" ItemsSource="{Binding TestDataItems}"/> </StackPanel> </Grid> </Grid> </phone:PhoneApplicationPage>
注意以上代碼的兩行注釋跟第10行的內容,這是其關鍵所在,新建一個默認的WP工程,就多了總共三處地方,于是,你就能看到以下的效果啦:
于是,通過MVC的設計手段,我們就能看到在WP設計頁面上看到數據集合是如何呈現的啦。至于實際運行如何加載數據集就不須要多說吧?只要給LongListSelector的ItemSource屬性賦值就好了,一句話的功夫。
結語:
以上的是一個簡單的MVC模式設計的例子,其實這工作一個人做看不出什么優勢,可是,我們從中看出,這樣的設計手法,可以讓界面邏輯跟功能邏輯分開設計提高效率,還有,如果程序以后要改進,從預覽窗口我們也更容易知道自己需要更改哪些東西,總之,優勢不少就是啦。
自己還有一個問題,如何在同一個頁面呈現兩個數據集呢?嗯,這是個問題。對了,附上工程例子。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。