MVVM框架从WPF移植到UWP遇到的问题和解决方法

0x00 起因

这几天开始学习UWP了,之前有WPF经验,所以总体感觉还可以,看了一些基础概念和主题,写了几个测试程序,突然想起来了前一段时间在WPF下写的简易的MVVM框架(MVVM模式和在WPF中的实现),都是.NET平台的,移到通用类库里只要复制粘贴就可以了吧。抱着这个心态试了下,结果代码一片红,折腾了一下午总算搞得差不多了,第二天写了个测试试了下感觉基本问题应该是解决了。现在总结一下自己踩到的坑。

0x01 命令绑定

之前在WPF中实现ICommand接口时,将检查Command是否可以执行的_canExecute添加到CommandManager的RequerySuggested事件中(详细见MVVM模式解析和在WPF中的实现(三)命令绑定),这样在出现可能会影响命令执行状态的事件时,CommandManager会触发事件对命令的可执行状态进行检查,并将检查方法的返回值赋给命令绑定控件的IsEnable属性上。这样我们只要指定检查命令执行状态的方法即可,系统会自动检查。不过在UWP中这个CommandManager没有了,因此将无法再执行自动的命令可执行状态的检查。刚开始遇到这个问题时,按下Ctrl+.的组合键提示我引用WPF中的dll可以解决问题,按照提示操作了之后红色下划线果然没了,可是编译时提示我有冲突还是什么,后来去网上查如何解决这个冲突,自然没搞定。不过找到了MVVMLight的作者写的一篇文章http://blog.galasoft.ch/posts/2015/01/re-enabling-the-commandmanager-feature-with-relaycommand-in-mvvm-light-v5/,看来CommandManager是真没了。

为什么要在UWP中移除CommandManager呢,我也没找到答案,个人猜测应该是这个操作浪费了太多的资源吧,特别在手机终端资源(包括电量)是很有限的。这个事件在MSDN中的描述意思也很模糊

也就是说CommandManager认为某个行为会影响到命令执行状态就会触发事件执行检查。我在WPF中一直使用这个功能从未遇到过问题,由此可见能触发这个检查的事件或其它状态改变还是很多的,也就是说对命令执行状态的检查是很频繁的,而且当触发检查时会对所有注册了状态检查的命令检查一遍。可能检查100次才会有一次状态改变,也可能程序运行整个过程中状态检查结果都没有变化,所以这个冗余操作太多了。

那么在UWP中我们应该怎么检查命令的执行状态呢,刚开始我打算自己写个事件,绑定命令时把检查执行状态的方法订阅那个事件,然后设置个Timer来定时触发事件检查执行状态,这绝对是个馊主意,马上就否决了。后来考虑在ViewModel中的属性发生改变时进行检查,也是很多冗余操作,而且这种检查也很不完善。后来想想算了,干脆手动检查吧,这样检查的针对性强。具体做法就是在命令的类型中添加触发检查的方法RaiseCanExecuteChanged()方法。

0x02 事件绑定到命令

其实这个问题非常好解决的,结果我却踩到坑里一个多小时才爬出来。先说下事件绑定,再说下坑的事情。之前在WPF中将事件绑定到命令靠的是Interactivity.dll,在UWP中换了另外两个dll:Microsoft.Xaml.Interactivity.dll和Microsoft.Xaml.Interactions.dll,过方法类似。我的VS采用的是默认安装,这两个dll在C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1\ExtensionSDKs\BehaviorsXamlSDKManaged\12.0\References\CommonConfiguration\Neutral这个位置。添加这两个dll的引用后就可以在XAML中实现事件绑定到命令了。下图代码绑定了主页面的PointerMoved事件至ViewModel中的CmdMouseMove命令。

特别值得一提的是之前在WPF中为了在事件绑定到命令后能够把时间的EventArgs传给命令,我们自己写了一个MyEventCommand类(MVVM设计模式和WPF中的实现(四)事件绑定),在UWP中就不需要了,InvokeCommandAction在不绑定CommandParameter的情况下默认就传递EventArgs参数,但当绑定了CommandParameter后传给Command的则为CommandParameter绑定的对象而不是事件的EventArgs参数。

这个应该是很简单的,结果我在测试的时候在类库的项目中引用了那两个dll,没有在测试项目中引入,所以在测试项目MainPage的XAML中进行引用命名空间时总是提示我不存在。记得以前刚换Windows8.1的时候遇到过类似问题,原因是系统会把来自网络的dll加锁,只要手动解锁就可以用了,翻了下之前那篇文章,也没在win10中看到有dll加锁啊。又开始怀疑dll版本不对,搜了好半天,最后发现是测试项目中没有引入那两个dll,反倒类库中没有必要引入。

0x03 其他一些问题

由于刚开始学习UWP开发,缺乏相关经验,因此在WPF中的View和ViewModel的通信和依赖注入不知道是不是适合于UWP,所以只是暂时把功能移过去,有待后面边学习边测试边修改。好吧,其实后面学习过程中写测试程序的话应该也不会用MVVM的。

另外移植过程中还发现从Type创建实例的方法变了,以前是这么写的:

type.Assembly.CreateInstance(type.FullName);

在UWP中需要这么写:

type.GetConstructor(Type.EmptyTypes).Invoke(parameters);

还有Dispatcher变成了CoreDispatcher等其他一些问题都与MVVM无关了,而且处理起来也都很容易,就不再讨论了。

0x04 示例

之前WPF版的MVVM框架还没来得及写示例,UWP版的反倒写了。示例很简单,界面如下图所示:

说明一下:

1.上边的TextBox显示的是当前鼠标相对于窗体的位置,随着鼠标移动显示数值会变化,方法是绑定了MainPage的PointerMoved事件,这说明了命令绑定运行正常,事件绑定命令并传递事件的参数也运行正常。

2.鼠标位置信息正确显示说明ViewModel中属性的数据绑定正常。

3.下面ListView数据正确显示说明绑定ViewModel中的集合属性正常。

4.按下Add会插入一条数据,按下Delete会删除选中数据,按下Clear会清空列表,说明命令绑定正常。

5.当无选中项时Delete按钮禁用,说明命令执行状态检查正常。

0x05 相关下载

https://github.com/durow/AyxMVVM


更多内容欢迎访问我的博客:http://www.durow.vip

MVVM框架从WPF移植到UWP遇到的问题和解决方法的更多相关文章

  1. winform,wpf全屏 还显示任务栏的解决方法

    原文:winform,wpf全屏 还显示任务栏的解决方法 以wpf为例: 全屏代码: this.Topmost = true; this.WindowStyle = System.Windows.Wi ...

  2. WPF拖动DataGrid滚动条时内容混乱的解决方法

    WPF拖动DataGrid滚动条时内容混乱的解决方法 在WPF中,如果DataGrid里使用了模板列,当拖动滚动条时,往往会出现列表内容显示混乱的情况.解决方法就是在Binding的时候给Update ...

  3. MVVM框架下 WPF隐藏DataGrid一列

    最近的一个项目,需要在部分用户登录的时候,隐藏DataGrid中的一列,但是常规的绑定不好使,在下面举个例子. XAML部分代码 <Window x:Class="DataGridCo ...

  4. WPF ComboBox SelectionChanged事件里赋值Text的解决方法

    string sCountry ; private void cbCountry_SelectionChanged(object sender, SelectionChangedEventArgs e ...

  5. 简单的介绍下WPF中的MVVM框架

    最近在研究学习Swift,苹果希望它迅速取代复杂的Objective-C开发,引发了一大堆热潮去学它,放眼望去各个培训机构都已打着Swift开发0基础快速上手的招牌了.不过我觉得,等同于无C++基础上 ...

  6. ViewModel从未如此清爽 - 轻量级WPF MVVM框架Stylet

    Stylet是我最近发现的一个WPF MVVM框架, 在博客园上搜了一下, 相关的文章基本没有, 所以写了这个入门的文章推荐给大家. Stylet是受Caliburn Micro项目的启发, 所以借鉴 ...

  7. 浅谈WPF中的MVVM框架--MVVMFoundation

    先科普一下:什么是WPF,请看下图 微软对于WPF技术的构想是很宏大的,可惜普及率不高,不过如果你要做Windows客户端开发的话WPF技术还是值得一学的. 什么是MVVM模式 简单来说它是一种高级的 ...

  8. 基于WPF系统框架设计(6)-整合MVVM框架(Prism)

    应用场景 我们基础的框架已经搭建起来了,现在整合MVVM框架Prism,在ViewModel做一些逻辑处理,真正把界面设计分离出来. 这样方便我们系统开发分工合作,同时提高系统可维护性和灵活性. 具体 ...

  9. 在WPF的MVVM框架中获取下拉选择列表中的选中项

    文章概述: 本演示介绍怎样在WPF的MVVM框架中.通过数据绑定的方式获取下拉列表中的选中项.程序执行后的效果例如以下图所看到的: 相关下载(代码.屏幕录像):http://pan.baidu.com ...

随机推荐

  1. Python高手之路【五】python基础之正则表达式

    下图列出了Python支持的正则表达式元字符和语法: 字符点:匹配任意一个字符 import re st = 'python' result = re.findall('p.t',st) print( ...

  2. 【WCF】错误协定声明

    在上一篇烂文中,老周给大伙伴们介绍了 IErrorHandler 接口的使用,今天,老周补充一个错误处理的知识点——错误协定. 错误协定与IErrorHandler接口不同,大伙伴们应该记得,上回我们 ...

  3. react-redux

    1. 首先redux,与react是两个独立的个体,项目中可以只用react,也可以只用redux 1.1 react-redux: 是一个redux作者专门为react制作的 redux, 增加了新 ...

  4. 和 Thrift 的一场美丽邂逅

    一. 与 Thrift 的初识 也许大多数人接触 Thrift 是从序列化开始的.每次搜索 “java序列化” + “方式”.“对比” 或 “性能” 等关键字时,搜索引擎总是会返回一大堆有关各种序列化 ...

  5. Node.js:进程、子进程与cluster多核处理模块

    1.process对象 process对象就是处理与进程相关信息的全局对象,不需要require引用,且是EventEmitter的实例. 获取进程信息 process对象提供了很多的API来获取当前 ...

  6. 如何安全的将VMware vCenter Server使用的SQL Server Express数据库平滑升级到完整版

    背景: 由于建设初期使用的vSphere vCenter for Windows版,其中安装自动化过程中会使用SQL Server Express的免费版数据库进行基础环境构建.而此时随着业务量的增加 ...

  7. python 数据类型 ---文件一

    1.文件的操作流程: 打开(open), 操作(read,write), 关闭(close) 下面分别用三种方式打开文件,r,w,a 模式 . "a"模式将不会覆盖原来的文件内容, ...

  8. Block解析(iOS)

    1. 操作系统中的栈和堆 我们先来看看一个由C/C++/OBJC编译的程序占用内存分布的结构: 栈区(stack):由系统自动分配,一般存放函数参数值.局部变量的值等.由编译器自动创建与释放.其操作方 ...

  9. Linux环境下常见漏洞利用技术(培训ppt+实例+exp)

    记得以前在drops写过一篇文章叫 linux常见漏洞利用技术实践 ,现在还可以找得到(https://woo.49.gs/static/drops/binary-6521.html), 不过当时开始 ...

  10. Unit Of Work的设计

    在DDD开发过程中,一个良好的Uow设计必不可少,我心目中的Uow设计应该具备以下几点: 1.有着良好的抽象,有着恰如其分的命名: 2.能够应付不同的组件,比如你的系统中可能会存在EfUnitOfWo ...