WPF简单MVVM实现
1. MVVM介绍:
MVVM就是: Model -- 模型(现实中对象的抽象)
View -- UI(用户界面)
ViewModel -- UI界面的抽象(给View提供数据,并响应View的操作)
2. 关键是要能准确的进行ViewModel的建模,处理好View与ViewModel之间的关系
2.1. 只有2种关系:
数据传递 --- 双向,使用Binding实现;
操作传递 --- 单向(只从View传递给ViewModel),使用命令Command实现;
3. 开始
3.1. 首先创建NotificationObject,它是所以ViewModel的基类
因为要使用Binding,而ViewModel就充当数据源的角色,而要实现当值有变化时会自动响应,就必须实现INotifyPropertyChanged接口,代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace MVVMTest.ViewModels
{
public class NotificationObject:INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged; public void RaisePropertyChanged(string property)
{
if (this.PropertyChanged != null)
this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(property)); }
}
}
3.2.接着要创建DelegateCommand,实现了ICommand接口,用来处理View发送到ViewModel的命令,代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input; namespace MVVMTest.Commands
{
public class DelegateCommand:ICommand
{
public bool CanExecute(object parameter)
{
if (this.CanExecuteFunc == null)
{
return true;
} return this.CanExecuteFunc(parameter);
} public event EventHandler CanExecuteChanged; public void Execute(object parameter)
{
if (this.ExecuteAction == null)
{
return;
}
this.ExecuteAction(parameter);
} public Action<object> ExecuteAction { get; set; }
public Func<object, bool> CanExecuteFunc { get; set; }
}
}
3.3.为了方便开发,这里推荐自定义一个code snippet(代码块):
放到此目录下C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC#\Snippets\1033\Visual C#
<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>propn</Title>
<Shortcut>propn</Shortcut>
<Description>Code snippet for NotificationObject property and backing field</Description>
<Author>Microsoft Corporation</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>type</ID>
<ToolTip>Property type</ToolTip>
<Default>int</Default>
</Literal>
<Literal>
<ID>property</ID>
<ToolTip>Property name</ToolTip>
<Default>MyProperty</Default>
</Literal>
<Literal>
<ID>field</ID>
<ToolTip>The variable backing this property</ToolTip>
<Default>myVar</Default>
</Literal>
</Declarations>
<Code Language="csharp"><![CDATA[private $type$ $field$; public $type$ $property$
{
get { return $field$;}
set {
$field$ = value;
this.RaisePropertyChanged("$property$");
}
}
$end$]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
3.4. 由于这个例子较简单,所以没有设计到Model的设计,而直接到ViewModel的设计,一般的规则是每个View就有一个对应的ViewModel,而ViewModel是充当View的数据源的,所以只需要考虑View需要什么数据、含有哪些操作,创建MainWindow的ViewModel,MainWindowViewModel,代码如下:
using MVVMTest.Commands;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace MVVMTest.ViewModels
{
public class MainWindowViewModel:NotificationObject
{
private string txt1; public string Txt1
{
get { return txt1; }
set
{
txt1 = value;
this.RaisePropertyChanged("Txt1");
}
} private string txt2; public string Txt2
{
get { return txt2; }
set
{
txt2 = value;
this.RaisePropertyChanged("Txt2");
}
} private string result; public string Result
{
get { return result; }
set
{
result = value;
this.RaisePropertyChanged("Result");
}
} public DelegateCommand ConcatCommand { get; set; }
public void Concat(object parameter)
{
Result = Txt1 + " and " + Txt2;
} public MainWindowViewModel()
{
ConcatCommand = new DelegateCommand();
ConcatCommand.ExecuteAction = new Action<object>(Concat);
} }
}
3.4.将ViewModel作为数据源赋值给View的DataContext
using MVVMTest.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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 MVVMTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new MainWindowViewModel();
}
}
}
3.5.在View中绑定数据:
<Window x:Class="MVVMTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="" Width="">
<Grid>
<TextBox Margin="40,51,311,216" Text="{Binding Txt1}"/>
<TextBox Margin="230,51,114,216" Text="{Binding Txt2}"/>
<TextBox Margin="128,152,176,139" Text="{Binding Result}"/>
<Button Margin="313,241,64,23" Command="{Binding ConcatCommand}"/>
</Grid>
</Window>
源代码:http://yunpan.cn/c3c7AAXm4U2dP 访问密码 8788
WPF简单MVVM实现的更多相关文章
- 从0到1:使用Caliburn.Micro(WPF和MVVM)开发简单的计算器
从0到1:使用Caliburn.Micro(WPF和MVVM)开发简单的计算器 之前时间一直在使用Caliburn.Micro这种应用了MVVM模式的WPF框架做开发,是时候总结一下了. Calibu ...
- .NET CORE(C#) WPF简单菜单MVVM绑定
微信公众号:Dotnet9,网站:Dotnet9,问题或建议:请网站留言, 如果对您有所帮助:欢迎赞赏. .NET CORE(C#) WPF简单菜单MVVM绑定 阅读导航 本文背景 代码实现 本文参考 ...
- WPF 微信 MVVM 【续】发送部分QQ表情
今天主要记录的就是发送QQ表情, WPF 微信 MVVM里写了,后期为了发送QQ表情,需要把TextBox替换为RichTextBox,接下来就说说替换的过程. 一.支持Binding的RichTex ...
- CleanAOP实战系列--WPF中MVVM自动更新
CleanAOP实战系列--WPF中MVVM自动更新 作者: 立地 邮箱: jarvin_g@126.com QQ: 511363759 CleanAOP介绍:https://github.com/J ...
- WPF Prism MVVM 中 弹出新窗体. 放入用户控件
原文:WPF Prism MVVM 中 弹出新窗体. 放入用户控件 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/qq_37214567/artic ...
- WPF之MVVM模式(3)
有种想写一个MVVM框架的冲动!!! 1.Model中的属性应不应该支持OnPropertyChanged事件? 不应该.应该有ViewModel对该属性进行封装,由ViewModel提供OnProp ...
- 【WPF】MVVM模式的3种command
原文:[WPF]MVVM模式的3种command 1.DelegateCommand 2.RelayCommand 3.AttachbehaviorCommand 因为MVVM模式适合于WPF和SL, ...
- WPF和MVVM的结合使用方法,不可错过
Model:存储数据模型(类) 也在此业务逻辑,主要负责类文件的存储. ViewModel:连接View和Model,借助Command来负责界面的跳转和调用Model中方法来操作Model的数据. ...
- WPF使用MVVM(一)-属性绑定
WPF使用MVVM(一)-属性绑定 简单介绍MVVM MVVM是Model(数据类型),View(界面),ViewModel(数据与界面之间的桥梁)的缩写,是一种编程模式,优点一劳永逸,初步增加一些逻 ...
随机推荐
- Delphi获取文件名、文件名不带扩展名、文件名的方法;delphi 获取文件所在路径
取文件名 ExtractFileName(FileName); 取文件扩展名: ExtractFileExt(filename); 取文件名,不带扩展名: 方法一: Function Extrac ...
- Github 的注册教程和初步使用体验
我叫许晴,是网工143的学生,学号是1413042064,兴趣包括手绘,看书和手游.学习过c++和汇编语言课程,但在编程方面没什么独立实践经验. 我的Githup用户名是 XQ123 .下面是我在gi ...
- [LeetCode 题解]: Rotate List
Given a list, rotate the list to the right by k places, where k is non-negative. For example:Given 1 ...
- [Elixir005] 查看指定数据的详细信息 i helper
elixir在1.2后增加了一个新的特性i helper. 在iex shell中使用i可以查看任意数据的数据类型和详细描述 #查看变量描述 iex(1)> i {:test, "Th ...
- merge sort 的javascript实现
递归 上一篇blog里,用js实现了quicksort算法,quicksort算法是一个递归调用过程. 递归是一种非常强大的编程思想,它广泛的的存在于各种语言当中,尤其lisp的各种方言中,大量的使用 ...
- Selenium窗口切换-----Selenium快速入门(六)
有时候,我们打开多个窗口,进行多窗口操作,那么窗口间该如何切换呢? 切换的方法有两个,一个是通过窗口标题来验证,另一个是通过窗口特定的内容来验证,这两个方法都要求得到的标题或内容是唯一的. 用到的相关 ...
- sqlite 插入数据 too many variables
相关文档:http://www.sqlite.org/limits.html#max_variable_number 一次插入条数限制500,参数最多999个.
- 【OCP-12c】CUUG 071题库考试原题及答案解析(19)
1.choose the best answerWhat is the primary difference between the relational database (RDB) andobje ...
- Mybatis 类的转换器
想一个事情 ,例: 我数据库的表 定义了一个表student 里面有一个字段 stu_sex int类型 可是我对应的实体类是 String 类型或者其他类型 这个时候 实体类与数据库表肯定对应不 ...
- jzoj3511
设f[i][j][k] 表示第i行状态为j i+1行将要被放为状态k的最优解 每次枚举这行和上一行的状态来dfs,注意细节 不合法的状态会直接被赋值成为inf