例子就取一個生活中的,用mvvm模式完成家庭的操作,比如顯示查詢家庭成員,增加家庭成員(娶妻生子等),減少家庭成員(嫁女老去等).
確定好這個例子我們就需要先準備一下數據,我們首先想到可能是用數據庫,不過silverlight是瀏覽器客戶端的東西,是不能和你以前使用asp.net一樣主動直接連接數據庫的,如果你真的要開始就連接數據庫,你還得準備另外學習一些知識。
我們先構思一下自己的類的樣子:
class familymember
{
public string Name{get,set;}//姓名
public string Sex{get,set;}//性別(不使用bool,因爲現在有中性人了)
public string Title{get,set;}//稱謂
public int Age{set,get;}//年齡
}
然後我們就可以開始工作,打開vs2010 創建一個silverlight應用程序 family.sln.進入設計界面,照着步驟往下,想不明白也別管,到了最後你就完全明白了。
1.在解決方案管理按MVVM的模式新建Views、Models、viewmodels、commands文件夾,這個不是必須的,但是真正做項目的時候是必須,你的組織你的程序文件啊!否則成百上千的文件,你要找個文件都得找成近視眼;
2.在models文件夾下新建一個類familymember.cs,照抄上面的;
public class familymember//家庭成員類
{
public string Name{get;set;}--姓名
public string Sex{get;set;}--性別(不使用bool,因爲現在有中性人了)
public string Title{get;set;}--稱謂
public int Age{set;get;}--年齡
}
3.繼續在models文件下再新建一個類family.cs,當然你可以不另外創建,直接寫在familymember.cs裏面
using System.Collections.Generic; //List類在此名稱空間下
public class family//家庭類(就是familymember類的集合)
public class family
{
private List<familymember> _family;
public List<familymember> initfamily()
{
_family = new List<familymember>()
{
new familymember{Name="王大爺",Age=120,Sex="男",Title="太爺"},
new familymember{Name="王老爺",Age=80,Sex="男",Title="爺爺"},
new familymember {Name="王中錢",Age=50,Sex="男",Title="老爸"},
new familymember {Name="王夫人",Age=48,Sex="女",Title="老媽"},
new familymember {Name ="王大二",Age=25,Sex="男",Title="大兒子"},
new familymember {Name="王八蛋",Age=20,Sex="男",Title="小兒子"},
new familymember {Name ="王小妹",Age=18,Sex="女",Title="小女兒"}
};
return _family ;
}
}
4.設計我們的viewmodel文件,在viemodels文件夾下我們新建一個familyviewmodel.cs類
public class familymodelview
{
public List<familymember> myfamily { get; set; }
public familymodelview()
{
//構造函數中初始化家庭成員列表
myfamily = new family().initfamily();
}
}
5.在views下面建一個文件familyview.xaml,這個是用來顯示家庭成員的;
<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions >
<RowDefinition Height="auto"/>
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" >
<TextBlock Text="輸入查詢條件"/>
<TextBox Name="txtsearch" Width="100" Height="23"/>
<Button Name="btnsearch" Content="查詢"/>
<Button Name="btnadd" Content="添加"/>
<Button Name="btndel" Content="刪除"/>
</StackPanel>
<sdk:DataGrid Grid.Row="1" Width="300" Name="mygrid" ItemsSource="{Binding myfamily}" HorizontalAlignment="Left" IsReadOnly="True">
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn Binding="{Binding Name}" Header="姓名" Width="80"/>
<sdk:DataGridTextColumn Binding="{Binding Title}" Header="稱謂" Width="80"/>
<sdk:DataGridTextColumn Binding="{Binding Sex}" Header="性別" Width="50"/>
<sdk:DataGridTextColumn Binding="{Binding Age}" Header="年齡" Width="50"/>
<sdk:DataGridTemplateColumn x:Name="c1" Header="刪除" >
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Name="btndelete" Content="Del" Click="btndelete_Click"/>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
</sdk:DataGrid.Columns>
</sdk:DataGrid>
</Grid>
6.開始拼裝,在Mainpage.xaml文件中寫上
<Grid x:Name="LayoutRoot" Background="White" >
<local:familyview/>
</Grid>
同時在cs文件中,將mainpage的構造函數修改一下:
public MainPage()
{
InitializeComponent();
this.LayoutRoot.DataContext = new familymodelview();
}
7.運行一下,是不是看見了家庭成員列表。比起以前的asp.net開發是不是很繁雜啊,一點都不習慣啊!例子到這裏好像還是沒有看出太大的端倪,但應該可以看出view文件已經很白了,我們繼續往下。
8.現在王小二娶了媳婦董雨進門,那麼這個家庭列表就增加了,我們需要添加方法,如果是asp.net,在view.cs文件調用一下解決了,但這樣那個xaml文件又複雜了,理性人和感性人又得糾結了。在mvvm中這個要玩的是familymodelview.cs這個文件。添加一個addmember方法
public void addmember(familymember p)
{
MessageBox.Show("恭喜,你的家庭成員增加了");
}
同時我們把查詢和刪除的方法也添加上.......
9.方法添加完了,我們需要把這個方法綁定到view裏面的添加按鈕上,這個時候就需要用到Icommand接口了。在commad下建一個relaycommand.cs
public class relaycommand:ICommand
{
private bool _isenabled;
private Action _handler;
public relaycommand(Action handler)
{
handler = _handler;
}
public bool IsEnabled
{
get { return _isenabled; }
set
{
_isenabled = value;
if (CanExecuteChanged != null)
{
this.CanExecuteChanged(this, EventArgs.Empty);
}
}
}
public bool CanExecute(object parameter)
{
//throw new NotImplementedException();
return IsEnabled;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
//throw new NotImplementedException();
_handler();
}
}
10.回到familymodelview.cs裏面添加上一些語句,完整程序的如下
public List<familymember> myfamily { get; set; }
public string searchtext { get; set; }//這個是用於和那個搜索條件綁定用的
private ICommand _addfamilymembercommand;
private ICommand _deletefamilymembercommand;
private ICommand _searchmembercommand;
public ICommand addfamilymembercommand
{
get { return _addfamilymembercommand; }
}
public ICommand deletefamilymembercommand
{
get { return _deletefamilymembercommand; }
}
public ICommand searchmembercommand
{
get { return _searchmembercommand; }
}
//構造函數
public familymodelview()
{
myfamily = new family().initfamily();
_searchmembercommand = new relaycommand(searchfamilymember) { IsEnabled = true };
_addfamilymembercommand = new relaycommand(addfamilymember) { IsEnabled = true };
_deletefamilymembercommand = new relaycommand(removefamilymember) { IsEnabled = true };
}
//實現功能的方法
public void addfamilymember()
{
MessageBox.Show("恭喜,你的家庭成員增加了");
}
public void removefamilymember()
{
MessageBox.Show("sorry,你的家庭成員減少了");
}
public void searchfamilymember()
{
List<familymember> mylists = null;
if (!string.IsNullOrEmpty(searchtext))
{
mylists = new List<familymember>();
foreach (familymember p in myfamily)
{
if (p.Name.Contains(searchtext))
mylists.Add(p);
}
myfamily = mylists;
}
}
}
10.這個時候回到view界面,程序再狠,也不可能知道藝術家在xaml文件中發揮到天上還是地上,所以作爲程序員的你還需要在多廢點腦細胞,誰讓你能呢!如果說view是個美人,那viewmodel是view背後的那個男人,view要發揮作用是離不開viewmodel的,在view的cs文件中寫上:
public partial class familyview : UserControl
{
familymodelview family1 = new familymodelview();
public familyview()
{
InitializeComponent();
}
private void btndelete_Click(object sender, RoutedEventArgs e)
{
family1.
}
private void btnsearch_Click(object sender, RoutedEventArgs e)
{
family1.searchtext = this.txtsearch.Text.Trim();
family1.searchmembercommand.Execute(null );
}
}
運行一下看看,點擊添加和刪除,是不是提示成功了。別以爲到這裏就真的會了mvvm,仔細想想,是不是有一點感覺:繞老繞去的寫了好多代碼其實都是在做無用功,特別是那個Icommand接口。如果你這麼想,就說明你真的用心學了。
11.真諦:如果mvvm是象上面那樣寫程序,那還不如不要呢!記得前面我們白話的時候提過,view就像美女一樣,基本靠“綁”,所以刪除我們的哪些語句,讓click事件滾蛋,直接在view的xaml文件中把命令綁上去。代碼如下:
<Button Name="btnsearch" Content="查詢" Command="{Binding searchmembercommand}"/>
<Button Name="btnadd" Content="添加" Command="{Binding addfamilymembercommand}" />
<Button Name="btndel" Content="刪除" Command="{Binding deletefamilymembercommand}" />
12.再次運行,看看是不是一樣的效果。現在你應該明白這種模式的優勢了吧,界面設計和程序設計者之間的自由度是不是發揮到了極致。