有种想写一个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. js 科学计数转数字或字符串

  2. laravel 配置文件的使用

    在开发的时候有许多数据是固定的 或者是多处使用的, 那么我们可以把它保存到配置文件中, 这样将来我们可以直接从配置文件中读取这个数据,如果有特殊的数据需要改变的时候,我们也可以在单独特定的环境中,不使 ...

  3. PHP 实现了一种代码复用的方法,称为 trait

    自 PHP 5.4.0 起,PHP 实现了一种代码复用的方法,称为 trait. Trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制.Trait 为了减少单继承语言的限制,使开发人员能 ...

  4. HTML 和 CSS

    HTML html是英文hyper text mark-up language(超文本标记语言)的缩写,它是一种制作万维网页面标准语言.   内容摘要   Doctype 告诉浏览器使用什么样的htm ...

  5. Fork/Join框架介绍

    转http://www.infoq.com/cn/articles/fork-join-introduction/ 1. 什么是Fork/Join框架 Fork/Join框架是Java7提供了的一个用 ...

  6. net.sf.json.JSONObject 和org.json.JSONObject

    参考 net.sf.json.JSONObject 和org.json.JSONObject 的差别

  7. 关于无法解析的外部符号 _main

    今天在写一段代码的时候,遇到了这个问题,一般遇到这种问题,都是找不到主函数,就是main函数,可是我写的代码是有入口地址main函数的呀.最后发现是自己源文件里,main函数是.c文件,.h文件对应的 ...

  8. java 多线程系列---JUC原子类(四)之AtomicReference原子类

    AtomicReference介绍和函数列表 AtomicReference是作用是对"对象"进行原子操作. AtomicReference函数列表   // 使用 null 初始 ...

  9. jquery ajax中error返回错误解决办法

    转自:https://www.jb51.net/article/72198.htm 进入百度搜索此问题,发现有人这么说了一句 Jquery中的Ajax的async默认是true(异步请求),如果想一个 ...

  10. Android webRTC 代码下载编译

    1.安装depot tools git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git 然后把把depot ...