最近由于項目需要,自己學習了一下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);
}
}
}
}