zoukankan      html  css  js  c++  java
  • MVVM框架从WPF移植到UWP遇到的问题和解决方法

    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 SDKsWindowsv8.1ExtensionSDKsBehaviorsXamlSDKManaged12.0ReferencesCommonConfigurationNeutral这个位置。添加这两个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

  • 相关阅读:
    mysql数据库常用指令
    解决windows的mysql无法启动 服务没有报告任何错误的经验。
    “Can't open file for writing”或“operation not permitted”的解决办法
    启动Apache出现错误Port 80 in use by "Unable to open process" with PID 4!
    如何打开windows的服务services.msc
    常见的HTTP状态码 404 500 301 200
    linux系统常用的重启、关机指令
    (wifi)wifi移植之命令行调试driver和supplicant
    linux(debian)安装USB无线网卡(tp-link TL-WN725N rtl8188eu )
    alloc_chrdev_region申请一个动态主设备号,并申请一系列次设备号
  • 原文地址:https://www.cnblogs.com/durow/p/4883556.html
Copyright © 2011-2022 走看看