最近由于项目需要,自己学习了一下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} Name:{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); } } } }