MVVM 模式介绍

模型-视图-视图模型 (MVVM) 是一种用来分离 UI 和非 UI 代码的应用设计模式

MVVM – 模型(Model)

MVVM 中的 Model 与 MVC 中的一致,用于封装业务逻辑以及数据处理。

Model 不依赖 View 和 ViewModel,可以独立存在,也就是说模型不关心自身被谁操作和展示。

Model 中不允许有任何跟界面相关的逻辑,比如操作界面上的控件。

通常在实际开发过程中 Model 可以再被划分成 Model 和 Service,区分业务和数据。

MVVM – 视图(View)

视图仅仅负责界面展示。

通过 DataContext(数据上下文)进行数据绑定。

不允许直接与 Model 交互。

可以通过绑定 Comand 来调用 ViewModel 的行为。

Command 是 View 到 ViewModel 的单向通行。

用户在 View 中触发事件,在 ViewModel 中处理。

MVVM – 视图模型(ViewModel)

ViewModel 是对 View 的抽象

视图模型包括界面模型数据和 Command 事件响应。

是 View 和 Model 的桥梁,是对 Model 的包装和抽象。

实现视图模型需要让类型实现 INotifyPropertyChanged 接口,用于实现属性和集合的变更通知,使用户在 View 上所做的操作可以实时通知到视图模型。

MVVM - Demo

利用 MVVM 实现一个计算器;

要求界面和业务逻辑完全剥离;

比如我们可以更改界面展示形式,功能仍然相同;

第一步:先对页面进行抽象(建模)

第二步:让视图模型实现INotifyPropertyChanged接口

第三步:后台代码中声明一个视图模型属性交给当前数据上下文

第四步:前台数据绑定

第五步:定义Command命令

 <Page
x:Class="MyJiSuanQi.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MyJiSuanQi"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
DataContext="{Binding ViewModel,RelativeSource={RelativeSource Mode=Self}}"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <StackPanel>
<Slider
Header="参数1"
Value="{Binding Parameter1,Mode=TwoWay}"/>
<!--<TextBox
x:Name="txtP1"
Header="参数1"
Text="{Binding Parameter1,Mode=TwoWay}"/>-->
<TextBox
x:Name="txtP2"
Header="参数2"
Text="{Binding Parameter2,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
<AppBarButton
x:Name="btnAdd"
Icon="Italic"
Label="Except"
Command="{Binding ExceptCommand}"
CommandParameter="{Binding}"/>
<TextBox
x:Name="txtResult"
Header="结果"
Text="{Binding Result,Mode=OneWay}"/>
</StackPanel>
</Page>
 namespace MyJiSuanQi
{
/// <summary>
/// 可用于自身或导航至 Frame 内部的空白页。
/// </summary>
public sealed partial class MainPage : Page
{
public MainPageViewModel ViewModel { get; set; }
public MainPage()
{
ViewModel = new MainPageViewModel();
this.InitializeComponent(); this.NavigationCacheMode = NavigationCacheMode.Required;
} /// <summary>
/// 在此页将要在 Frame 中显示时进行调用。
/// </summary>
/// <param name="e">描述如何访问此页的事件数据。
/// 此参数通常用于配置页。</param>
protected override void OnNavigatedTo(NavigationEventArgs e)
{
// TODO: 准备此处显示的页面。 // TODO: 如果您的应用程序包含多个页面,请确保
// 通过注册以下事件来处理硬件“后退”按钮:
// Windows.Phone.UI.Input.HardwareButtons.BackPressed 事件。
// 如果使用由某些模板提供的 NavigationHelper,
// 则系统会为您处理该事件。
}
//第一步:先对页面进行抽象(建模)
//第二步:让视图模型实现INotifyPropertyChanged接口
//第三步:后台代码中声明一个视图模型属性交给当前数据上下文
//第四步:前台数据绑定
//第五步:定义Command命令
private void btnAdd_Click(object sender, RoutedEventArgs e)
{
//var d1 = double.Parse(txtP1.Text);
//var d2 = double.Parse(txtP2.Text);
//txtResult.Text = (d1 + d2).ToString();
ViewModel.Result = ViewModel.Parameter1 + ViewModel.Parameter2;
}
}
public class MainPageViewModel : INotifyPropertyChanged
{
public MainPageViewModel()
{
AddCommand = new AddCommand();
ExceptCommand = new ExceptCommand();
}
public double Parameter1 { get; set; }
private double parameter2;
//影响当前命令是否可以被执行的依据
public double Parameter2
{
get { return parameter2; }
set
{
if (parameter2 == value)
{
return;
}
parameter2 = value;
//通知命令对象重新判断是否可以执行
ExceptCommand.OnCanExecuteChanged();
}
}
//public double Result { get; set; }
private double result;
public double Result
{
get { return result; }
set { result = value; OnPropertyChanged("Result"); }
}
public ICommand AddCommand { get; set; }
public ExceptCommand ExceptCommand { get; set; }
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
//命令对象必须实现ICommand接口
public class AddCommand : ICommand
{
//判断当前命令对象是否可以被执行
public bool CanExecute(object parameter)
{
throw new NotImplementedException();
} public event EventHandler CanExecuteChanged;
//如何执行
public void Execute(object parameter)
{
var model = parameter as MainPageViewModel;
model.Result = model.Parameter1 + model.Parameter2;
}
}
//命令对象必须实现ICommand接口
public class ExceptCommand : ICommand
{
//判断当前命令对象是否可以被执行
public bool CanExecute(object parameter)
{
var model = parameter as MainPageViewModel;
return model != null && model.Parameter2 != ;
}
//当CanExecute判断依据发生变化时,触发事件
public event EventHandler CanExecuteChanged;
public void OnCanExecuteChanged()
{
if (CanExecuteChanged != null)
CanExecuteChanged(this, EventArgs.Empty);
}
//如何执行
public void Execute(object parameter)
{
var model = parameter as MainPageViewModel;
model.Result = model.Parameter1 / model.Parameter2;
}
}
}
MVVM 模式优点

低耦合:View 可以独立于 Model 变化和修改,一个 ViewModel 可以绑定到不同的 View 上,当 View 变化的时候 Model 可以不变,当 Model 变化的时候 View 也可以不变。

可重用性:可以把一些视图的逻辑放在 ViewModel 里面,让很多View重用这段视图逻辑。

独立开发:开发人员可以专注与业务逻辑和数据的开发(ViewModel)。设计人员可以专注于界面(View)的设计。

可测试性:可以针对ViewModel来对界面(View)进行测试。

Windows Phone 十一、MVVM模式的更多相关文章

  1. WPF自学入门(十一)WPF MVVM模式Command命令 WPF自学入门(十)WPF MVVM简单介绍

    WPF自学入门(十一)WPF MVVM模式Command命令   在WPF自学入门(十)WPF MVVM简单介绍中的示例似乎运行起来没有什么问题,也可以进行更新.但是这并不是我们使用MVVM的正确方式 ...

  2. 重新想象 Windows 8 Store Apps (55) - 绑定: MVVM 模式

    [源码下载] 重新想象 Windows 8 Store Apps (55) - 绑定: MVVM 模式 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 绑定 通过 M ...

  3. 企业级架构 MVVM 模式指南 (WPF 和 Silverlight 实现) 译(2)

    本书包含的章节内容 第一章:表现模式,以一个例子呈献给读者表现模式的发展历程,我们会用包括MVC和MVP在内的各种方式实现一个收费项目的例子.沿此方向,我们会发现每一种模式的问题所在,这也是触发设计模 ...

  4. MVVM模式解析和在WPF中的实现(三)命令绑定

    MVVM模式解析和在WPF中的实现(三) 命令绑定 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在WPF中 ...

  5. [转载]MVVM模式原理分析及实践

    没有找到很好的MVVM模式介绍文章,简单找了一篇,分享一下.MVVM实现了UI\UE设计师(Expression Blend 4设计界面)和软件工程师的合理分工,在SilverLight.WPF.Wi ...

  6. silverlighter下MVVM模式中利用Behavior和TargetedTriggerAction实现文本框的一些特效

    在silverlight一般开发模式中,给文本框添加一些事件是轻而易举的,然而MVVM开发模式中,想要给文本框添加一些事件并非那么容易,因为MVVM模式中,只有ICommand接口,而且也只有Butt ...

  7. 在 WPF 程序中使用 MVVM 模式

    MVVM 模式是一个很久之前的技术了,最近因为一个项目的原因,需要使用 WPF 技术,所以,重新翻出来从前的一段程序,重温一下当年的技术. MVVM 模式 MVVM 实际上涉及三个部分,Model, ...

  8. MVVM模式应用 之的RelayCommand的使用

    实现MVVM模式Command是立下了汗马功劳.当然ICommand要引用using System.Windows.Input命名空间. 比如: (1)我们在xaml页面有一个Button按钮,我们需 ...

  9. 什么是MVVM模式

    问题引入1 场景一:团队辛辛苦苦完成了一个项目,抱着激动的心情去给用户做demo,而用户给你的反馈是UI很不满意,要重新修改,否则拒绝验收.大规模修改UI,晴天霹雳!2 场景二:产品在一家客户上线运行 ...

随机推荐

  1. CentOS7下安装chrome浏览器

    在CentOS 7环境下安装chrome浏览器 1.修改yum源 在/etc/yum.repos.d/目录下新建文件google-chrome.repo,向其中添加如下内容: [google-chro ...

  2. HDU3371 最小生成树

    Connect the Cities Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  3. java并发编程(九)死锁

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17200937 大部分代码并不容易产生死锁,死锁可能在代码中隐藏相当长的时间,等待不常见的条 ...

  4. ssh项目部署到weblogic中问题总结

    部署到weblogic还是比较费劲的 ,不过基本上问题全是由于classloader顺序的问题引起的. 首先在web-inf底下添加weblogic.xml文件如下 <?xml version= ...

  5. WM_COPYDATA进程间通信方案

    连续在两个公司使用WM_COPYDATA实现进程间通信了,整理一下 具体步骤: 一.   进程A通过ShellExecute启动进程B, 将用于通信的窗口句柄hWndA(已强转为int值)通过命令行参 ...

  6. DoModal时带出次级窗口闪现

    最近在做MFC 界面开发. 在一个CDialog窗口DoModal模态显示时, 会将次级窗口带出闪现(比如将一个窗口active, 然后点击我现在程序需要弹框的按钮,弹出弹出正常,但原来active的 ...

  7. Jvascript简介

    一.Javascript就是我们所说的脚本语言.它不同于C++/java等语言,它更加灵活! 正因为其灵活性,没有那么多的规章制度,也是我们容易学的地方,但很多时候也是 令人无奈的地方! 二.我们要知 ...

  8. opencv的问题

    opencv中图像文件格式是BRG的顺序 而QImage是RGB形式 H:色彩 S:深浅 s=0 只有灰度 V:明暗

  9. C 符号

    语言的运算符可分为以下几类: 1 算术运算符 用于各类数值运算.包括加(+).减(-).乘(*).除(/).求余(或称模运算,%).自增(++).自减(–)共七种. 2.关系运算符 用于比较运算.包括 ...

  10. MongoDB的配置、启动、关闭

    MongoDB 是一个基于分布式文件存储的数据库.由 C++ 语言编写.旨在为 WEB 应用提供可扩展的高性能数据存储解决方案. MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系 ...