MVVM模式
一、MVVM模式概述
MVVM Pattern : Model\View\ViewModel
View:視圖、UI界面
ViewModel:ViewModel是對(duì)Model的封裝,通過(guò)一系列屬性暴露Model的狀態(tài),提供給View進(jìn)行顯示
Model:數(shù)據(jù)模型
使用MVVM模式可以將代碼邏輯和UI進(jìn)行分離,因此開(kāi)發(fā)團(tuán)隊(duì)可以關(guān)注創(chuàng)建健壯的ViewModel類(lèi),而設(shè)計(jì)團(tuán)隊(duì)可以關(guān)注設(shè)計(jì)界面友好的View。要融合兩個(gè)團(tuán)隊(duì)輸出只需要在View的xaml上進(jìn)行正確的綁定即可。
二、演示程序
下面通過(guò)一個(gè)Demo演示W(wǎng)PF中如何使用MVVM模式:使用WPF中的data template、commands、data binding、resource結(jié)合MVVM模式,創(chuàng)建一個(gè)簡(jiǎn)單、可測(cè)試、健壯的框架。
演示程序結(jié)構(gòu)圖如下:
1、演示程序 Demo界面如圖所示:
工作區(qū)用于顯示視圖
命令區(qū)分兩部分,上部分為顯示單視圖命令,下部分為顯示多視圖命令
單視圖:工作區(qū)始終只顯示一個(gè)視圖。
多視圖:工作區(qū)可以顯示多個(gè)視圖,以TabControl控件的TabItem進(jìn)行展示。可以通過(guò)previousview命令顯示視圖集合中的上一個(gè)視圖,通過(guò)nextview顯示視圖集合中的下一個(gè)視圖。
Demo的MainWindow.xaml文件中,使用單視圖時(shí),需要注釋多視圖;使用多視圖時(shí),需要注釋單視圖。代碼如下:
<!--single view-->
<ContentPresenter Content="{Binding Path=WorkspaceSingle}"/>
<!--multi view-->
<ContentPresenter Content="{Binding Path=WorkspaceMulti}" ContentTemplate="{StaticResource WorkspacesTemplate}"/>
三、數(shù)據(jù)模型(Model)、視圖(View)
為了使Demo更容易理解,程序中只使用了一個(gè)Model,Model中Name屬性用于顯示視圖名稱(chēng)。
public class InfoModel
{
//視圖名稱(chēng)
public string Name { get; set; }
}
兩個(gè)簡(jiǎn)單的視圖:FirstView、SecondView,視圖中控件顯示當(dāng)前的視圖名稱(chēng),如視圖FirstView:
<StackPanel Background="Aqua">
<TextBlock Text="{Binding Path=Name}" FontSize="20"/>
</StackPanel>
<StackPanel Background="Chartreuse">
<TextBlock Text="{Binding Path=Name}" FontSize="20"/>
</StackPanel>
在實(shí)際開(kāi)發(fā)中,視圖中可以布局其它控件,并進(jìn)行正確的綁定,界面都能正常的顯示。
顯示多視圖時(shí),TabItem的Header能顯示視圖名稱(chēng),如圖所示:
視圖名稱(chēng)DisplayName是基類(lèi)ViewModelBase的屬性
/// <summary>
/// 名稱(chēng)
/// </summary>
public virtual string DisplayName { get; protected set; }
子類(lèi)在構(gòu)造函數(shù)中給DisplayName賦值
public class FirstViewModel : WorkspaceViewModel
{
private const string DisplayViewName = "FirstView";
private readonly InfoModel _info;
public FirstViewModel()
{
//視圖名稱(chēng)
base.DisplayName = DisplayViewName;
if (_info == null)
{
_info = new InfoModel();
}
_info.Name = DisplayViewName;
}
public string Name
{
get { return _info.Name; }
}
}
在View中綁定視圖名稱(chēng)
<DataTemplate x:Key="TabItemTemplate">
<DockPanel>
<ContentPresenter Content="{Binding Path=DisplayName}" VerticalAlignment="Center"/>
</DockPanel>
</DataTemplate>
四、ViewModel類(lèi)圖
大家一看代碼就知道,整個(gè)ViewModel使用的是什么設(shè)計(jì)模式
五、View對(duì)應(yīng)ViewModel
Demo的一個(gè)主要特點(diǎn)是數(shù)據(jù)延遲加載,即在需要數(shù)據(jù)時(shí)創(chuàng)建ViewModel
程序在啟動(dòng)時(shí)即為主界面加載數(shù)據(jù)MainWindowViewModel
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
MainWindow window = new MainWindow();
var viewModel = new MainWindowViewModel();
window.DataContext = viewModel;
window.Show();
}
}
程序啟動(dòng)后,單擊按鈕時(shí)創(chuàng)建FirstViewModel或SecondViewModel
創(chuàng)建單視圖
/// <summary>
/// 顯示視圖一
/// </summary>
private void ShowFirstView()
{
if (_workspaceStory == null)
{
_workspaceStory = new ObservableCollection<WorkspaceViewModel>();
}
var model =
this._workspaceStory.FirstOrDefault(vm => vm is FirstViewModel)
as FirstViewModel;
if (model == null)
{
model = new FirstViewModel();
_workspaceStory.Add(model);
}
WorkspaceSingle = model;
}
/// <summary>
/// 顯示視圖二命令
/// </summary>
private void ShowSecondView()
{
if (_workspaceStory == null)
{
_workspaceStory = new ObservableCollection<WorkspaceViewModel>();
}
var model =
this._workspaceStory.FirstOrDefault(vm => vm is SecondViewModel)
as SecondViewModel;
if (model == null)
{
model = new SecondViewModel();
_workspaceStory.Add(model);
}
WorkspaceSingle = model;
}
創(chuàng)建多視圖
/// <summary>
/// 創(chuàng)建視圖一,并顯示
/// </summary>
private void CreateFirstView()
{
var model = new FirstViewModel();
WorkspaceMulti.Add(model);
ShowCurrentView(model);
}
/// <summary>
/// 創(chuàng)建視圖二
/// </summary>
private void CreateSecondView()
{
var model = new SecondViewModel();
WorkspaceMulti.Add(model);
ShowCurrentView(model);
}
創(chuàng)建后,WPF自動(dòng)為匹配的View Model尋找View來(lái)渲染。
<DataTemplate DataType="{x:Type vm:FirstViewModel}">
<vw:FirstView/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:SecondViewModel}">
<vw:SecondView/>
</DataTemplate>
六、總結(jié)
MVVM模式是設(shè)計(jì)和開(kāi)發(fā)WPF程序一種簡(jiǎn)單、有效的指導(dǎo)方針。它允許你創(chuàng)建數(shù)據(jù)、行為和展示強(qiáng)分離的程序,更容易控制軟件開(kāi)發(fā)中的混亂因素。
Demo:https://github.com/WELL-E/TestMVVMDemo QQ:130108655共同學(xué)習(xí)
|