C# WPF MVVM模式[经典]案例

01

前言

        Caliburn.Micro(简称CM)一经推出便备受推崇,作为一款MVVM开发模式的经典框架,越来越多的受到wpf开发者的青睐.我们看一下官方的描述:Caliburn是一个为Xaml平台设计的小型但功能强大的框架。Micro实现了各种UI模式,用于解决实际问题。突出显示的模式包括MVVM(表示模型)、MVP和MVC。目前CM框架还不不停的开发和迭代中,目前最新版本4.0.212,推出于2022年8月27日,已经可以支持.NET7。

02


项目介绍

解决方案由四个项目组成:见下图

12f290f5563a78d49790a7d72b5f8c1c.png

HelloWorld:框架的搭建、容器注入相关;

HelloWorld.Core;放置数据模型,即mvvm中的M;

HelloWorld.ViewModels:模型视图,即VM;

HelloWorld.Views:V,即视图.

项目基于.NET5开发:

fec91cd0db9e38dea82c179b36bdc5ee.png

CM框架版本:4.0.212;

运行结果显示:

a8473961e6e6f7af630a19eaa80b61db.png

03


代码展示和讲解

① 首先是HelloWorld讲解,这里启动代码:Startup.CS

public class Startup : BootstrapperBase{SimpleContainer _container;public Startup(){Initialize();}protected override void Configure(){_container = new SimpleContainer().Singleton<IWindowManager, WindowManager>().Singleton<IEventAggregator, EventAggregator>();foreach (var asm in SelectAssemblies()){foreach (var vm in asm.GetTypes()){if (vm.Name.EndsWith("VM")){_container.RegisterPerRequest(vm, null, vm);}}}var myRule = new TypeMappingConfiguration{ViewModelSuffix = "VM",ViewSuffixList = new() { "" }};ViewLocator.ConfigureTypeMappings(myRule);ViewModelLocator.ConfigureTypeMappings(myRule);}protected override void OnStartup(object sender, StartupEventArgs e){base.OnStartup(sender, e);DisplayRootViewForAsync<IndexVM>();}protected override IEnumerable<Assembly> SelectAssemblies(){return new List<Assembly>{Assembly.Load("HelloWorld"),Assembly.Load("HelloWorld.Views"),Assembly.Load("HelloWorld.ViewModels"),};}protected override object GetInstance(Type service, string key){return _container.GetInstance(service, key);}}

这里容器采用了CM自带的SimpleContainer:

开始先把窗口管理器和事件聚合器注册到了容器中:

_container = new SimpleContainer().Singleton<IWindowManager, WindowManager>().Singleton<IEventAggregator, EventAggregator>();

然后通过反射把下面三个程序集:

Assembly.Load("HelloWorld"),Assembly.Load("HelloWorld.Views"),Assembly.Load("HelloWorld.ViewModels"),

中vm结尾的视图模型文件注册到容器:

foreach (var asm in SelectAssemblies()){foreach (var vm in asm.GetTypes()){if (vm.Name.EndsWith("VM")){_container.RegisterPerRequest(vm, null, vm);}}}

接下来是自定义了一套CM的VM和V的匹配规则,默认情况,CM的匹配规则是视图以View结尾,视图模型以ViewModel结尾,这里的规则是VM以VM结尾,View只要前缀和Viewmodel的一致就可以:

var myRule = new TypeMappingConfiguration{ViewModelSuffix = "VM",ViewSuffixList = new() { "" }};ViewLocator.ConfigureTypeMappings(myRule);ViewModelLocator.ConfigureTypeMappings(myRule);

②HelloWorld.Views,这里放的是视图,代码很简单,不展开了,比较新颖的用法是它通过load函数接在view的:

cal:Message.Attach="[Event Loaded]=[Loaded($view,$eventArgs)]"
public void Loaded(UserControl control, RoutedEventArgs @event){Debug.WriteLine(control);Debug.WriteLine(@event);}

③ HelloWorld.ViewModels,视图模型:

LoginVM.cs这是登录窗体的后台逻辑:点击登录后发送背景线程异步事件更新进度条:

public async Task DoLogin(){await _eventAggregator.PublishOnBackgroundThreadAsync(new BusyMessage(true));await Task.Delay(1000);MessageBox.Show("Test Login Success");await _eventAggregator.PublishOnBackgroundThreadAsync(new BusyMessage(false));}

IndexVM.cs:继承IHandle<BusyMessage>,

接收事件更新进度条:

public Task HandleAsync(BusyMessage message, CancellationToken cancellationToken){if (message.IsBusy){BarValue = 50;}else{BarValue = 0;}return Task.CompletedTask;}

通过ioc容器获取VM:

 public LoginVM LoginVM { get; set; } = IoC.Get<LoginVM>();

public LoginVM LoginVM { get; set; } = IoC.Get<LoginVM>();public TableVM TableVM { get; set; } = IoC.Get<TableVM>();

TableVM.cs:

数据集合定义:  public ObservableCollection<Foo> Data { get; set; }

开线程更新集合数据:用 await Task.Delay(1000);演示一秒

Task.Run(async () =>{while (true){if (IsShow){_data.Add(new Foo{Id = Guid.NewGuid(),Name = "John" + new Random().Next(1, 100),School = "上海大学"});Data = new ObservableCollection<Foo>(_data);}await Task.Delay(1000);}});

 [AddINotifyPropertyChangedInterface]:来源于,可以自动通知界面数据更新。

049ca8ee3eb9606d15dfe5c80e3a374f.png

04


源码下载及声明

声明:首先感谢群友提供源码,需要和源码提供者本人直面交流的可以通过邮箱:xingrui_zhuang@asiasymbol.com 联系.

源码百度网盘链接链接:https://pan.baidu.com/s/1BHkVEFWHwGQf6EwHpWCBKw
提取码:6666
技术群:添加小编微信并备注进群小编微信:mm1552923   
公众号:dotNet编程大全

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

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

相关文章

shell数组

定义数组[rootwy shell]# a(1 2 3 4)显示数组[rootwy shell]# echo ${a[]}1 2 3 4[rootwy shell]# echo ${a[*]}1 2 3 4显示数组中的某个元素[rootwy shell]# echo ${a[0]}1增加元素[rootwy shell]# a[4]9[rootwy shell]# echo ${a[*]}1 2 3 4 9修改元素值 [rootwy shell]# a[2…

java二级程序题两个角度_两个角度图_【SCME大一】使用JAVA语言深入理解程序逻辑答案_学小易找答案...

【填空题】《蝶恋花 伫倚危楼风细细 》的作者( )。【简答题】简要概述问卷调查的整体设计?【填空题】父母在,( ),游必有方。【填空题】白居易与刘禹锡并称“( )”。【填空题】白居易,字( )。【填空题】白居易,是唐代伟大的( )主义诗人。【单选题】《红楼梦》最成功处在于塑造了…

LINUX中常用操作命令

LINUX中常用操作命令 引用&#xff1a;http://www.daniubiji.cn/archives/25 Linux简介及Ubuntu安装 常见指令系统管理命令打包压缩相关命令关机/重启机器Linux管道Linux软件包管理vim使用用户及用户组管理文件权限管理Linux简介及Ubuntu安装 Linux&#xff0c;免费开源&#x…

Log4j编写

来自: http://www.blogjava.net/zJun/archive/2006/06/28/55511.html Log4J的配置文件(Configuration File)就是用来设置记录器的级别、存放器和布局的&#xff0c;它可接keyvalue格式的设置或xml格式的设置信息。通过配置&#xff0c;可以创建出Log4J的运行环境。1. 配置文件L…

C# 为什么高手喜欢用StartsWith而不是Substring进行字符串匹配?

字符串的截取匹配操作在开发中非常常见&#xff0c;比如下面这个示例&#xff1a;我要匹配查找出来字符串数组中以“abc”开头的字符串并打印&#xff0c;我下面分别用了两种方式实现&#xff0c;代码如下&#xff1a;using System;namespace ConsoleApp23 {class Program{stat…

Nginx 服务器开启status页面检测服务状态

原文&#xff1a;http://www.cnblogs.com/hanyifeng/p/5830013.html 一、Nginx status monitor 和apache 中服务器状态一样。输出的内容如&#xff1a; 第1列&#xff1a; 当前与http建立的连接数&#xff0c;包括等待的客户端连接&#xff1a;2第2列&#xff1a;接受的客户端连…

elif是不是java关键字_C# 中的#if、#elif、#else、#endif等条件编译符号 (转载)

这些是C#中的条件编译符号。这些指令我在项目中遇到过&#xff0c;查过网络&#xff0c;问过人(当然&#xff0c;既不认识大牛&#xff0c;也不认识小牛&#xff0c;所以没什么收获)。今天翻看一本资料&#xff0c;有提到这个方面的东西&#xff0c;所以写下来和能看到这篇文章…

从零开始React项目架构(四)

前言 使用当前的webpack配置能不能打包构建项目呢&#xff1f;当然可以&#xff0c;但这不是我们想要的&#xff0c;所以&#xff0c;让我们来看一看生产环境需要怎么配置webpack吧 开发 生产环境配置 在根目录创建webpack.pro.config.jsconst path require(path) const webpa…

在OpenCloudOS 上安装.NET 6

开源操作系统社区 OpenCloudOS 由腾讯与合作伙伴共同倡议发起&#xff0c;是完全中立、全面开放、安全稳定、高性能的操作系统及生态。OpenCloudOS 沉淀了多家厂商在软件和开源生态的优势&#xff0c;继承了腾讯在操作系统和内核层面超过10年的技术积累&#xff0c;在云原生、稳…

Linux 命令详解(二)awk 命令

AWK是一种处理文本文件的语言&#xff0c;是一个强大的文本分析工具。之所以叫AWK是因为其取了三位创始人 Alfred Aho&#xff0c;Peter Weinberger, 和 Brian Kernighan 的Family Name的首字符。 语法&#xff1a; awk [选项参数] script varvalue file(s) 或 awk [选项参数] …

linux下vtune使用

安装&#xff1a;http://www.cnblogs.com/jiu0821/p/5943533.html 终端输入amplxe-gui,打开vtune界面。 点击new project&#xff0c;进入project properties界面。进行配置&#xff1a; target&#xff1a;target type选择launch application&#xff0c;application选择程序可…

java产生的数字发送到页面_JAVA中数字证书的维护及生成方法

Java中的keytool.exe可以用来创建数字证书&#xff0c;所有的数字证书是以一条一条(采用别名区别)的形式存入证书库的中&#xff0c;证书库中的一条证书包含该条证书的私钥&#xff0c;公钥和对应的数字证书的信息。证书库中的一条证书可以导出数字证书文件&#xff0c;数字证书…

数据库 创建 / 查看/ 删除

创建数据库 语法&#xff1a;CREATE DATABASE [IF NOT EXISTS] db_name; 重复创建会报错&#xff0c;所以可以加上if not exists 注意&#xff1a;SQL语句必须以分号结尾 查看有哪些数据库&#xff1a;SHOW DATABASES; 删除数据库 语法:DROP DATABASE [IF EXISTS] dbname;如果…

IDEA破解 2017 IDEA license server 激活(可用)

进入ide主页面&#xff0c;help-register-license server,然后输入 http://idea.iteblog.com/key.PHP&#xff08;注意&#xff1a;php要小写&#xff09;即可~ 转载于:https://www.cnblogs.com/austinspark-jessylu/p/7232982.html

《ASP.NET Core 6框架揭秘》实例演示[20]:“数据保护”框架基于文件的密钥存储...

《数据加解密与哈希》演示了“数据保护”框架如何用来对数据进行加解密&#xff0c;而“数据保护”框架的核心是“密钥管理”。数据保护框架以XML的形式来存储密钥&#xff0c;默认的IKeyManager实现类型为XmlKeyManager。接下来我们通过模拟代码和实例演示的形式来介绍一下Xml…

使用msui的回到顶部的一个小问题

2019独角兽企业重金招聘Python工程师标准>>> 回到顶部&#xff0c;一直没反应。 zepto加了动画后&#xff0c;依然如此。原生写法&#xff0c;jquery写法&#xff0c;仍然没有反应。 排查了后&#xff0c;发现获取的对象错误。手机端上&#xff0c;滚动到顶部&#…

口袋精灵加速版java_口袋妖怪TCG!口袋对决加速版教程(免ROOT)

原标题&#xff1a;口袋妖怪TCG&#xff01;口袋对决加速版教程(免ROOT)《口袋对决》是一款以口袋精灵对战为核心玩法的集换式卡牌游戏&#xff0c;原汁原味的口袋画风&#xff0c;丰富多彩的各系精灵&#xff0c;策略竞技的属性相克。在5分钟一局的卡牌对战中&#xff0c;你将…

C#发布程序添加其他程序文件

注&#xff1a;程序发布文件&#xff0c;默认只发布自身程序直接引用的相关文件(A程序)。 如果需要添加其他程序(不同的应用程序B)文件&#xff0c;操作方法如下&#xff1a; 第一步&#xff1a;将B程序文件复制到A程序 第二步&#xff1a;将B程序文件右键--》属性做如下更改&a…

k8s 读书笔记 - 初始化容器 Init Container

Init Container 概述Init Container&#xff08;Init 容器&#xff09; 是一种特殊容器&#xff0c;在 Pod 内的应用容器启动之前运行&#xff0c;执行相关的初始化操作。Init 容器可以包括一些应用镜像中不存在的 实用工具 和 安装脚本 。每个 Pod 中可以包含一个或多个容器&a…

jsp 连接access数据库

参考笔记&#xff1a;https://www.cnblogs.com/mthoutai/p/7278995.html