Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 515|回复: 0

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

[复制链接]
  • TA的每日心情
    奋斗
    2024-4-6 11:05
  • 签到天数: 748 天

    [LV.9]以坛为家II

    2034

    主题

    2092

    帖子

    70万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    705612
    发表于 2021-5-3 09:28:21 | 显示全部楼层 |阅读模式

    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

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-5-19 21:06 , Processed in 0.061333 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表