学习MVVM设计模式后第一次用于生产

WPF的MVVM设计模式

winform转变到WPF的过程,难点主要还是在MVVM的设计模式。当然,如果依然采用winform的涉及方式,在每个控件背后绑定事件的方式运用在wpf中,依然可行,但是假如GUI改版,其背后绑定的特别为此界面设计的事件不得不多数弃用。而MVVM最大的好处是将一切业务逻辑放在ViewModel中 ,将GUI的操作放在view中,将数据结构放在Model中,如图摘自MSDN

640?wx_fmt=png

实际使用

使用了Prism框架,省去了去构造实现INotifyPropertyChanged的基类,直接继承BindableBase

namespace Prism.Mvvm{    //    // 摘要:    //     Implementation of System.ComponentModel.INotifyPropertyChanged to simplify models.    public abstract class BindableBase : INotifyPropertyChanged    {        protected BindableBase();        //        // 摘要:        //     Occurs when a property value changes.        public event PropertyChangedEventHandler PropertyChanged;        //        // 摘要:        //     Notifies listeners that a property value has changed.        //        // 参数:        //   propertyName:        //     Name of the property used to notify listeners. This value is optional and can        //     be provided automatically when invoked from compilers that support System.Runtime.CompilerServices.CallerMemberNameAttribute.        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null);        //        // 摘要:        //     Raises this object's PropertyChanged event.        //        // 参数:        //   propertyExpression:        //     A Lambda expression representing the property that has a new value.        //        // 类型参数:        //   T:        //     The type of the property that has a new value        protected virtual void OnPropertyChanged<T>(Expression<Func<T>> propertyExpression);        //        // 摘要:        //     Checks if a property already matches a desired value. Sets the property and notifies        //     listeners only when necessary.        //        // 参数:        //   storage:        //     Reference to a property with both getter and setter.        //        //   value:        //     Desired value for the property.        //        //   propertyName:        //     Name of the property used to notify listeners. This value is optional and can        //     be provided automatically when invoked from compilers that support CallerMemberName.        //        // 类型参数:        //   T:        //     Type of the property.        //        // 返回结果:        //     True if the value was changed, false if the existing value matched the desired        //     value.        protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null);    }

以及用来构造Command的基类DelegateCommand

namespace Prism.Commands{    //    // 摘要:    //     An System.Windows.Input.ICommand whose delegates do not take any parameters for    //     Prism.Commands.DelegateCommand.Execute and Prism.Commands.DelegateCommand.CanExecute.    public class DelegateCommand : DelegateCommandBase    {        //        // 摘要:        //     Creates a new instance of Prism.Commands.DelegateCommand with the System.Action        //     to invoke on execution.        //        // 参数:        //   executeMethod:        //     The System.Action to invoke when System.Windows.Input.ICommand.Execute(System.Object)        //     is called.        public DelegateCommand(Action executeMethod);        //        // 摘要:        //     Creates a new instance of Prism.Commands.DelegateCommand with the System.Action        //     to invoke on execution and a Func to query for determining if the command can        //     execute.        //        // 参数:        //   executeMethod:        //     The System.Action to invoke when System.Windows.Input.ICommand.Execute(System.Object)        //     is called.        //        //   canExecuteMethod:        //     The System.Func`1 to invoke when System.Windows.Input.ICommand.CanExecute(System.Object)        //     is called        public DelegateCommand(Action executeMethod, Func<bool> canExecuteMethod);        protected DelegateCommand(Func<Task> executeMethod);        protected DelegateCommand(Func<Task> executeMethod, Func<bool> canExecuteMethod);        //        // 摘要:        //     Factory method to create a new instance of Prism.Commands.DelegateCommand from        //     an awaitable handler method.        //        // 参数:        //   executeMethod:        //     Delegate to execute when Execute is called on the command.        //        // 返回结果:        //     Constructed instance of Prism.Commands.DelegateCommand        public static DelegateCommand FromAsyncHandler(Func<Task> executeMethod);        //        // 摘要:        //     Factory method to create a new instance of Prism.Commands.DelegateCommand from        //     an awaitable handler method.        //        // 参数:        //   executeMethod:        //     Delegate to execute when Execute is called on the command. This can be null to        //     just hook up a CanExecute delegate.        //        //   canExecuteMethod:        //     Delegate to execute when CanExecute is called on the command. This can be null.        //        // 返回结果:        //     Constructed instance of Prism.Commands.DelegateCommand        public static DelegateCommand FromAsyncHandler(Func<Task> executeMethod, Func<bool> canExecuteMethod);        //        // 摘要:        //     Determines if the command can be executed.        //        // 返回结果:        //     Returns true if the command can execute, otherwise returns false.        public virtual bool CanExecute();        //        // 摘要:        //     Executes the command.        public virtual Task Execute();        //        // 摘要:        //     Observes a property that is used to determine if this command can execute, and        //     if it implements INotifyPropertyChanged it will automatically call DelegateCommandBase.RaiseCanExecuteChanged        //     on property changed notifications.        //        // 参数:        //   canExecuteExpression:        //     The property expression. Example: ObservesCanExecute((o) => PropertyName).        //        // 返回结果:        //     The current instance of DelegateCommand        public DelegateCommand ObservesCanExecute(Expression<Func<object, bool>> canExecuteExpression);        //        // 摘要:        //     Observes a property that implements INotifyPropertyChanged, and automatically        //     calls DelegateCommandBase.RaiseCanExecuteChanged on property changed notifications.        //        // 参数:        //   propertyExpression:        //     The property expression. Example: ObservesProperty(() => PropertyName).        //        // 类型参数:        //   T:        //     The object type containing the property specified in the expression.        //        // 返回结果:        //     The current instance of DelegateCommand        public DelegateCommand ObservesProperty<T>(Expression<Func<T>> propertyExpression);    }}

第一次使用MVVM设计模式,没有理解在多个ViewModel之间通信,所以不得不采用单一ViewModel和多个view,这样导致了一个ViewModel的臃肿和复杂,看似结构简单,但是实际的逻辑越来越混乱。在没有理解Event Aggregator如何使用的情况下,这是可行方案。

MVVM使用感受

最主要的感受是MVVM将UI和业务逻辑分离,UI就只写UI,不用像WinForm一样在每个事件背后,如果要获得UI某个TextBox的数据,得通过如下获取

public void SomeButton_Clicked(object sender, EventArgs e){	string text = textBox1.Text;	DoSomeThings(text);	...}

同样,后台事件要更新前台UI数据时

pubic void SomeButton_Clicked(object sender, EvnetArgs e){	DoOtherThings();	textBox1.Text = "Some Text";}

这种硬编码的形式,遇到UI的重大变化,必须就将背后事件对应UI的控件名称全部更改才能继续运行。当软件达到一定复杂度,这样做就是灾难性的。

MVVM,使用了数据绑定,虽然增加了一点代码,但是带来的好处巨大。在ViewModel中先定义要绑定的数据

private string name;public string Name{	get{return name;}	set{		if (name != value)		{			name = value;			OnPropertyChanged("Name"); // 实现INotifyPropertyChanged接口	}}}

然后在view中将其和TextBox数据绑定

<TextBox Text="{Binding Name, Mode=TwoWay}">

这里的数据绑定方式是双向绑定,后台数据变化会自动通知前台UI线程更新数据,相反,前台UI线程更改了数据,后台的数据也会相应变化。这样,在实际数据更新时,不用去查看绑定的UI控件名称,也不用担心在其他线程更新控件数据时要用oneControl.Invoke(Action action)

总结

第一次使用MVVM感受到的优点:

  • 数据绑定,不用考虑具体UI控件的名称,不用手动更新UI数据。

  • UI可操作性更大,支持template

  • 业务逻辑和UI分离,界面改版方便

但同样带来了缺点:

  • 代码量明显增加

  • 对于小软件来说,开发没有WinFrom来的敏捷


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/315211.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

netcore mvc快速开发系统(菜单,角色,权限[精确到按钮])开源

基于netcore2.0 mvc 开发的 快速搭建具有如下特色的后台管理系统用户管理菜单管理角色管理权限管理[精确到按钮]&#xff09;代码生成器代码克隆到本地 用vs2017或以上版本 打开工程。项目结构如下&#xff1a;找到DbModel下面的初始化db脚本里面包含4张表的schema和初始化数据…

asp.net core 系列之Startup

这篇文章简单记录 ASP.NET Core中 &#xff0c;startup类的一些使用。一.前言在 Startup类中&#xff0c;一般有两个方法&#xff1a;ConfigureServices 方法: 用来配置应用的 service 。 Configure 方法&#xff1a;创建应用的请求处理管道它们都在应用启动时&#xff0c;被AS…

译 | .NET Core 基础架构进化之路(一)

原文&#xff1a;Matt Mitchell翻译&#xff1a;Edi Wang随着 .NET Core 3.0 Preview 6 的推出&#xff0c;我们认为简要了解一下我们基础设施系统的历史以及过去一年左右所做的重大改进会很有用。如果您对构建基础结构感兴趣&#xff0c;或者想要了解我们如何构建与 .NET Core…

剑指 Offer 27. 二叉树的镜像

思路&#xff1a;递归 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/ class Solution { public:TreeNode* mirrorTree(TreeNode*…

Codeforces Round #626 (Div. 2) D. Present 按位贡献 + 快排新姿势

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 给你一个长度为nnn的序列aaa&#xff0c;让你计算 n≤4e5,a≤1e7n\le 4e5,a\le 1e7n≤4e5,a≤1e7 思路&#xff1a; 首先这个式子是n2n^2n2的&#xff0c;显然不能直接算&#xff0c;并且异或没有分配律&…

.NET开发框架(一)-框架介绍与视频演示

本文主要介绍一套基于.NET CORE的SPA高并发、高可用的开发框架.我们暂且称它为&#xff1a;&#xff08;让你懂.NET&#xff09;开发框架。以此为主线&#xff0c;陆续编写教程&#xff0c;讲述如何构建高并发、高可用的框架。&#xff08;欢迎转载与分享&#xff09;它标准化了…

译 | .NET Core 基础架构进化之路(二)

原文&#xff1a;Matt Mitchell翻译&#xff1a;Edi Wang&#xff08;接上篇 译 | .NET Core 基础架构进化之路&#xff08;一&#xff09;&#xff09;Maestro 及依赖流.NET Core 3.0 基础结构难题的最后一部分就是我们所说的依赖项流。这不是 .NET Core 的唯一概念。除非它们…

在.Net Core中实现一个WebSocket路由

Net Core中使用WebSocket默认是没有路由系统的&#xff0c;只能通过Request.Path"/xxx"来判断请求&#xff0c;例如&#xff1a;1 2 3 4 5 6 7 8 91011121314151617181920app.Use(async (context, next) >{ if (context.Request.Path "/ws") { …

Dapper介绍--Micro-ORM

一&#xff0e;概述目前对于.net的数据访问ORM工具很多&#xff0c;EF和EF Core是一个重量级的框架。最近在搭建新的项目架构&#xff0c;来学习一下轻量级的数据访问ORM工具Dapper。Dapper支持SQL Server&#xff0c;MySQL&#xff0c;Sqlite&#xff0c;SqlCE&#xff0c;Fir…

剑指 Offer 31. 栈的压入、弹出序列

思路&#xff1a;模拟就完事 class Solution { public:bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {stack<int> c;int idx0;for(int v:pushed){c.push(v);while(c.size()&&c.top()popped[idx]){c.pop();idx;}…

Educational Codeforces Round 84 (Rated for Div. 2) D. Infinite Path 构建环 + 思维

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 懒得写了&#xff0c;直接贴图了。 思路&#xff1a; 遇事不决画成图&#xff0c;考虑将iii向p[i]p[i]p[i]连一个边&#xff0c;可以发现每个点入度为111&#xff0c;出度为111&#xff0c;所以画出来是若…

WSL+VSCODE体验UBUNTU环境下的开发

首先安装 WSL&#xff0c;我这里选择的是 ubuntu18.04 这个应用。切换 WSL 的默认用户为 root 用户切换成 root 用户主要是避免后续开发中遇到权限问题比较麻烦&#xff0c;直接默认 root 解决问题。找到ubuntu安装目录&#xff0c;一般在C:\Program Files\WindowsApps\Canonic…

程序员修仙之路--优雅快速的统计千万级别uv

菜菜&#xff0c;咱们网站现在有多少PV和UV了&#xff1f;Y总&#xff0c;咱们没有统计pv和uv的系统&#xff0c;预估大约有一千万uv吧写一个统计uv和pv的系统吧网上有现成的&#xff0c;直接接入一个不行吗&#xff1f;别人的不太放心&#xff0c;毕竟自己写的&#xff0c;自己…

P3391 【模板】文艺平衡树 fhq-treap 模板

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 思路&#xff1a; 这是学splaysplaysplay的时候的一个模板题&#xff0c;之前学过fhq−treapfhq-treapfhq−treap&#xff0c;但是没怎么用他做过题&#xff0c;今天一做还发现不少问题&#xff0c;真是眼高…

123. 买卖股票的最3佳时机 III

思路&#xff1a;动态规划&#xff0c; dp1是当前第一次买入的最大值 dp2是当前第一次卖出的最大值 dp3是当前第二次买入的最大值 dp4是当前第二次卖出的最大值 转移看代码&#xff1a; class Solution { public:int maxProfit(vector<int>& prices) {int dp1-…

微软正式开源WSL 2的内核源码

微软在今年5月举办的 Build 2019 上宣布了第二代 Windows 的 Linux 子系统 —— WSL 2。与第一代相比&#xff0c;WSL 2 重新设计了架构&#xff0c;使用真正的 Linux 内核&#xff0c;支持在 Windows 上运行 ELF64 Linux 二进制文件。按照计划&#xff0c;WSL 2 的初始版本已于…

【NOI2016】优秀的拆分【后缀数组】【ST表】【关键点】【调和级数复杂度】【差分】

传送门 题意&#xff1a;如果一个字符串可以拆分为AABB的形式&#xff0c;其中A和B是任意非空字符串&#xff0c;则我们这种拆分是优秀的。求给定串的所有子串的拆分方案数之和。 N≤30000N \leq30000N≤30000 本来是个神仙题 但明明一个O(nlogn)O(nlogn)O(nlogn)的题为啥只…

剑指 Offer 43. 1~n 整数中 1 出现的次数(数位dp)

思路&#xff1a;就是数位dp&#xff0c;dp[idx][sum][limit]代表&#xff0c;到idx位&#xff0c;前面有sum个0&#xff0c;有没有limit限制&#xff1b; class Solution { public:int dp[20][50][2];int len; int pos[20];int countDigitOne(int n) {for(int i0;i<15;i)f…

Windows新终端中玩转ASCII和Emoji游戏的正确姿势

前一段时间&#xff0c;我搬运了几个Windows Terminal中玩游戏的视频.Windows Terminal - 动图GIF作背景图Windows Terminal - 母牛说HiWindows Terminal - 字符水族箱今天我来给大家展示一下具体的玩法~Emoji版双人碰碰球目前有个现成的 .NET core 项目可以直接用&#xff0c;…

剑指 Offer 38. 字符串的排列(有重复元素的排列)

思路&#xff1a;dfs 暴搜 class Solution { public:vector<string> permutation(string s) {vector<string> a;function<bool(char,int,int)> check[&](char x,int st,int idx){if(st>idx) return false;for(int ist;i<idx;i) if(s[i]x) return …