有种想写一个MVVM框架的冲动!!!

1、Model中的属性应不应该支持OnPropertyChanged事件?


不应该。应该有ViewModel对该属性进行封装,由ViewModel提供OnPropertyChanged事件。WPF之MVVM(1)中有实例

2、如何将控件事件转换为命令?


  • 在“扩展”中添加“System.Windows.Interractivity”引用
  • xaml中添加xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity命名空间
  • 使用

    <ListBox Name="LbBox" ItemsSource="{Binding Path=SourceCount}">
    <i:Interaction.Triggers>
    <i:EventTrigger EventName="SelectionChanged">
    <common:ExInvokeCommandAction Command="{Binding Path=SelectionChangedCmd}" CommandParameter="{Binding ElementName=LbBox, Path=SelectedItem}"/>
    </i:EventTrigger>
    </i:Interaction.Triggers>
    </ListBox>

3、View中如何访问ViewModel


WPF之MVVM(2)中介绍了

4、ViewModel中如何访问View


WPF之MVVM(2)中介绍了

5、ViewModel之间通信


  • 聚合关系

    public class VM01
    {
    public string Name{get;set;}
    } public class VM02
    {
    public list<VM01> Property
    {
    get;
    set;
    }
    }
  • 组合关系

    public class VM01
    {
    public string Name{get;set;}
    } public class VM02
    {
    public string Name{get;set;}
    } public class VM03
    {
    private VM01 _vm01;
    private VM02 _vm02;
    ...
    public VM03(VM01 vm01, VM02 vm02){}
    }
  • 依赖关系

这里主要介绍下依赖关系的ViewModel如何通信

通过一个非常简单的程序来演示这种实现:点击左边的数字,右边的数字加1。

左边为LeftViewModel右边为RightViewModel,两个VM是相互独立的,通过事件进行通信。

1、定义类型来容纳所有需要发送给事件通知接收者的附件信息

public class NumberChangedEventArgs : EventArgs
{
public int Number { get; set; } public NumberChangedEventArgs(int num)
{
Number = num;
}
}

2、在LeftViewModel中定义事件成员

public event EventHandler<NumberChangedEventArgs> NumberChanged;

protected virtual void OnNumberChanged(NumberChangedEventArgs e)
{
var handler = NumberChanged;
if (handler != null) handler(this, e);
}

3、定义负责引发事件的方法来通知事件的登记对象

/// <summary>
/// 选择命令
/// </summary>
private DelegateCommand<ExCommandParameter> _selectionChangedCmd; public DelegateCommand<ExCommandParameter> SelectionChangedCmd
{
get
{
if (_selectionChangedCmd == null)
{
_selectionChangedCmd = new DelegateCommand<ExCommandParameter>(InvokeMouseDown);
} return _selectionChangedCmd;
}
} private void InvokeMouseDown(ExCommandParameter param)
{
var number = param.Parameter is int ? (int) param.Parameter : ;
//触发事件
OnNumberChanged(new NumberChangedEventArgs(number));
}

4、定义方法将输入转化为期望事件

public class RightViewModel : ViewModelBase
{
public RightViewModel()
{
//订阅事件
var vm = ViewModelManager.GetByKey("left") as LeftViewModel;
if (vm != null) vm.NumberChanged += VmOnNumberChanged;
} private int _number; public int Number
{
get { return _number; }
set
{
_number = value;
OnPropertyChanged("Number");
}
} /// <summary>
/// 事件处理
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void VmOnNumberChanged(object sender, NumberChangedEventArgs e)
{
Number = e.Number + ;
}
}

问题RightViewModel中如何获取LeftViewModel呢?

定义一个容器

public static class ViewModelManager
{
private static readonly Dictionary<string, ViewModelBase> Dic = new Dictionary<string, ViewModelBase>(); public static void Add(string key, ViewModelBase value)
{
if (Dic.ContainsKey(key)) return; Dic.Add(key, value);
} public static ViewModelBase GetByKey(string key)
{
if (!Dic.ContainsKey(key)) return null; ViewModelBase value;
Dic.TryGetValue(key, out value); return value;
}
}

在设置View的DataContext时将ViewModel添加到ViewModelManager

public LeftView()
{
InitializeComponent(); var vm = new LeftViewModel();
ViewModelManager.Add("left", vm);
this.DataContext = vm;
}

总结


回顾上面3篇博文中解决的问题,我们再来看下MvvmLight ToolKit是如何实现MVVM的,这里引用下园友的总结MvvmLight ToolKit 教程

我们可以猜测MvvmLight作者使用这些组件是为了解决什么问题?

  • ViewModelBase && ObservableObject(INotifyPropertyChanged接口的实现,解决属性改变通知的问题)
  • ViewModelLocator && SimpleIoc(IOC容器,我们的ViewModelManager高级版)
  • RelayCommand(ICommand接口的实现,解决View和ViewModel通信问题)
  • EventToCommand && IEventArgsConverter(Interaction的封装,解决将事件转换为命令的问题)
  • Messenger(解决View和ViewModel以及ViewModel和ViewModel之间通信的问题)
  • DispatcherHelper(博客中未提到)

这样分析后,我们就知道MvvmLight是如何产生的,以及它能为我们做什么。

吹牛吹到现在,我都有种自己想写一个MVVM框架的冲动了。你们有没有?

WPF之MVVM模式(3)的更多相关文章

  1. 【WPF】MVVM模式的3种command

    原文:[WPF]MVVM模式的3种command 1.DelegateCommand 2.RelayCommand 3.AttachbehaviorCommand 因为MVVM模式适合于WPF和SL, ...

  2. WPF之MVVM模式讲解

    WPF技术的主要特点是数据驱动UI,所以在使用WPF技术开发的过程中是以数据为核心的,WPF提供了数据绑定机制,当数据发生变化时,WPF会自动发出通知去更新UI. 恰当的模式可以让我们轻松达到“高内聚 ...

  3. 【转】【WPF】MVVM模式的3种command

    1.DelegateCommand 2.RelayCommand 3.AttachbehaviorCommand 因为MVVM模式适合于WPF和SL,所以这3种模式中也有一些小差异,比如RelayCo ...

  4. WPF之MVVM模式(2)

    我们都想追求完美 Every view in the app has an empty codebehind file, except for the standard boilerplate cod ...

  5. WPF之MVVM模式(1)

    MVVM模式 一.MVVM模式概述 MVVM Pattern : Model\View\ViewModel View:视图.UI界面 ViewModel:ViewModel是对Model的封装,通过一 ...

  6. WPF中MVVM模式的 Event 处理

    WPF的有些UI元素有Command属性可以直接实现绑定,如Button 但是很多Event的触发如何绑定到ViewModel中的Command呢? 答案就是使用EventTrigger可以实现. 继 ...

  7. WPF中 MVVM模式的Slider Binding.

    对于Button的Command的绑定可以通过实现ICommand接口来进行,但是Slider并没有Command属性. 另外如果要实现MVVM模式的话,需要将一些Method和Slider的Even ...

  8. WPF采用MVVM模式(绑定:纯前台、命令:触发器绑定命令)

    MVVM绑定 view-viewModel-model,模型介绍省略,就是创建类,添加字段封装属性.注:控件的绑定只能绑定到属性上,不能绑定到字段上: 接下来就是代码 (view): <Wind ...

  9. WPF中MVVM模式下控件自有的事件绑定

    1.原因 在WPF中单纯的命令绑定往往不能满足覆盖所有的事件,例如ComboBox的SelectionChanged事件,DataGrid的SelectionChanged事件等等,这时就可以用事件绑 ...

随机推荐

  1. shell for的用法

    #!/bin/sh for1(){ for i in 1 2 3 4 5 6do echo "$i"done } for1#!/bin/shfor2(){for i in {1.. ...

  2. TexStudio 非常好用的Latex软件

    先大概写一下,免得忘了,等有时间详细补充. 跨平台.免费. 语法高亮 方便的公式.符号选择界面 可以配置Latex,pdflatex,xelatex等默认编译命令 集成了pdf阅读器,可在阅读器中浏览 ...

  3. HIVE-利用ow_number() OVER(PARTITION BY)函数介绍求TOP-K

    http://blog.csdn.net/631799/article/details/7419797 第一句话: select row_number() over (partition by mon ...

  4. PHP怎么把经过UTF-8编码的中文字符转换成正常的中文

    问题的场景: html 为utf-8编码<meta http-equiv="Content-Type" content="text/html; charset=UT ...

  5. BZOJ1293:[SCOI2009]生日礼物

    浅谈队列:https://www.cnblogs.com/AKMer/p/10314965.html 题目传送门:https://lydsy.com/JudgeOnline/problem.php?i ...

  6. Linux应用程序调用其他程序执行

    一.system 1.作用 在Linux应用程序中调用另一个程序: 2.用法 system("/sbin/ifconfig"): 二.popen 1.作用 调用另一个程序执行,同时 ...

  7. 【转】S1 Setup

    概念 S1是eNB和MME之间交换应用层配置数据的接口的名称.它是在建立TNL完成后的第一个S1AP的操作,S1的建立意味着eNB和MME之间之前已经存在的所有应用层数据将被全部清空,所有的数据将被重 ...

  8. HashSet中是如何判断元素是否重复的

    HashSet不能添加重复的元素,当调用add(Object)方法时候, 首先会调用Object的hashCode方法判hashCode是否已经存在,如不存在则直接插入元素: 如果已存在则调用Obje ...

  9. CRC 简介

    CRC wiki,历史发展,各个版本的用途 等 https://en.wikipedia.org/wiki/Cyclic_redundancy_check (apple)crc32.c /* * Th ...

  10. C语言学习笔记--递归函数

    1. 递归函数的思想 (1)递归是一种数学上分而自治的思想,是将大型复杂问题转化为与原问题相同但规模较小的问题进行处理的一种方法 (2)递归需要有边界条件 ①当边界条件不满足时,递归继续进行 ②当边界 ...