最近由於項目需要,自己學習了一下WPF,之前接觸過sliverlight,所以對理解和編寫XAML不是太陌生。其實XAML和html多少還是有點類似的。只不過XAML上添加上了自動binding機制(這里可以對比datagridview控件的binding理解一下)。
WPF有兩個核心的東西,也是MVVM等一系列框架的基礎。其實說白了,也就是兩個重要的接口(INotifyPropertyChanged和ICommand).
INotifyPropertyChanged接口實現了數據和UI的聯動,數據改變,UI界面隨之改變,反之一樣。(這個接口可以理解為監聽,生成的Model后,通過ViewModel對Model所有相關者進行監聽)
WPF其中一個比較常用的框架MVVM
下面:通過實例來解析一下MVVM(個人的理解,如果有錯誤,請諒解)
1.MVVM:Model-View-ViewModel
Model:就是各個實體類
View:就是顯示的界面,在WPF中一般都是XAML這樣的頁面
ViewModel:這個是最難理解的。ViewModel官方的解釋是連接Model和View的橋梁,封裝和暴露一些邏輯處理方法。但個人認為,其實所有的控制和方法都在ViewModel中,可以理解為頁面所有方法的一個倉庫
2.MVVM的實現原理
MVVM實現簡單的來說就是通過ViewModel來連接Model和View實現的。ViewModel實現了接口INotifyPropertyChanged,在Model屬性改變時可以觸發View頁面數據改變。另外,ViewModel中的command實現ICommand這個接口,使得方法也可以直接綁定在UI控件上,省去頁面后台書寫控件事件的代碼
下面實例代碼:
Model:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace WpfApplication1 { public class DataItem { public int ID { get; set; } public string Name { get; set; } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections.ObjectModel; namespace WpfApplication1 { public static class DataDemo { private static Collection<DataItem> _DataList = null; public static Collection<DataItem> DataList { get { if (_DataList == null) { _DataList = InitDataList(); } return _DataList; } } private static Collection<DataItem> InitDataList() { Collection<DataItem> lists = new Collection<DataItem>(); for (int i = 0; i < 100; i++) { DataItem item = new DataItem(); item.ID = i + 1; item.Name = "例子" + (i + 1); lists.Add(item); } return lists; } } }
在Model完成后,編寫ViewModel,為UI中使用
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel; using System.Collections.ObjectModel; using System.Windows.Input; namespace WpfApplication1 { class QueryDataViewModel:INotifyPropertyChanged { #region 變量 /// <summary> /// 查詢的數據 /// </summary> private Collection<DataItem> _DataList = null; /// <summary> /// 查詢命令 /// </summary> private ICommand _QueryCommand = null; /// <summary> /// 搜索關鍵字 /// </summary> private string _SearchText = string.Empty; /// <summary> /// 搜索結果 /// </summary> private string _SearchResult = string.Empty; #endregion #region 屬性 /// <summary> /// 搜索關鍵字 /// </summary> public string SearchText { get { return this._SearchText; } set { this._SearchText = value; if (this.PropertyChanged != null) this.PropertyChanged(this, new PropertyChangedEventArgs("SearchText")); } } /// <summary> /// 搜索結果 /// </summary> public string SearchResult { get { return this._SearchResult; } set { this._SearchResult = value; if (this.PropertyChanged != null) this.PropertyChanged(this, new PropertyChangedEventArgs("SearchResult")); } } /// <summary> /// 查詢命令 /// </summary> public ICommand QueryCommand { get { return _QueryCommand; } } #endregion #region 構造函數 public QueryDataViewModel(Collection<DataItem> dataList) { this._DataList = dataList; _QueryCommand = new QueryDataCommand(this); } #endregion #region 方法 /// <summary> /// 查詢數據 /// </summary> public void QueryData() { if (!string.IsNullOrEmpty(this.SearchText)) { DataItem dataItem = null; foreach (DataItem item in this._DataList) { if (item.ID.ToString() == this.SearchText) { dataItem = item; break; } } if (dataItem != null) { this.SearchResult = string.Format("ID:{0}\nName:{1}", dataItem.ID, dataItem.Name); } } } #endregion #region INotifyPropertyChanged 成員 public event PropertyChangedEventHandler PropertyChanged; #endregion } }
在ViewModel中,定義了一系列的參數和方法,其中UI頁面是通過ICommand這個實例來調用綁定的方法的
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Input; namespace WpfApplication1 { class QueryDataCommand:ICommand { private QueryDataViewModel _QueryDataViewModel; public QueryDataCommand(QueryDataViewModel queryDataViewModel) { this._QueryDataViewModel = queryDataViewModel; } #region ICommand 成員 public bool CanExecute(object parameter) { return true; } public event EventHandler CanExecuteChanged { add { } remove { } } public void Execute(object parameter) { this._QueryDataViewModel.QueryData(); } #endregion } }
編寫Command命令,編寫前端頁面
<UserControl x:Class="WpfApplication1.UserControl1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"> <Grid x:Name="LayoutRoot"> <Button x:Name="btnSearch" Height="24" HorizontalAlignment="Left" Margin="164,8,0,0" VerticalAlignment="Top" Width="84" Content="搜索" Command="{Binding QueryCommand}"/> //這個是綁定的方法,這里的QueryCommand就是ViewModel中的ICommand實例 <TextBox x:Name="txtKeyword" Height="24" HorizontalAlignment="Left" Margin="8,8,0,0" VerticalAlignment="Top" Width="152" TextWrapping="Wrap" d:LayoutOverrides="HorizontalAlignment" Text="{Binding SearchText,Mode=TwoWay}"/> <TextBox x:Name="txtResult" HorizontalAlignment="Left" Margin="8,36,0,8" Width="240" TextWrapping="Wrap" d:LayoutOverrides="VerticalAlignment" Text="{Binding SearchResult,Mode=OneWay}"/> </Grid> </UserControl>
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace WpfApplication1 { /// <summary> /// UserControl1.xaml 的交互邏輯 /// </summary> public partial class UserControl1 : UserControl { private QueryDataViewModel _QueryDataViewModel = null; public UserControl1() { InitializeComponent(); this._QueryDataViewModel = new QueryDataViewModel(DataDemo.DataList); base.DataContext = this._QueryDataViewModel; // this.btnSearch.Click += new RoutedEventHandler(btnSearch_Click); } void btnSearch_Click(object sender, RoutedEventArgs e) { if (this._QueryDataViewModel != null) { this._QueryDataViewModel.SearchText = this.txtKeyword.Text; this._QueryDataViewModel.QueryCommand.Execute(null); } } } }