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…

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;接受的客户端连…

在OpenCloudOS 上安装.NET 6

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

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

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

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…

捕获 BackgroundService 中的异常 | 学学官方是如何实现的

前言上次&#xff0c;我们实现了《使用“装饰者模式”捕获 BackgroundService 中的异常》。结果发现&#xff0c;微软已经发现了这个问题&#xff0c;并在 .NET 6 中解决了。&#xff08;囧&#xff09;让我们验证一下&#xff1a;using IHost host Host.CreateDefaultBuilder…

使用badboy录制脚本 结合Jmeter一起测试。

1.badboy介绍 Badboy是一款不错的Web自动化测试工具&#xff0c;如果你将它用于非商业用途&#xff0c;或者用于商业用途安装Badboy 的机器数量不超过5台&#xff0c;你是不需要为它支付任何费用的。Badboy提供了将Web测试脚本直接导出生成JMeter 脚本的功能&#xff0c;并且这…

centOS下安装jdk1.8

2019独角兽企业重金招聘Python工程师标准>>> 本文记录了在vm下安装的centOS7下安装jdk1.8的过程 需要的工具及jdk&#xff1a; jdk-8u171-linux-x64.tar.gz 可以到官网去下 cecureFX 用于文件的传输 过程&#xff1a; 本次centOS7使用VMware Workstation 14 P…

盘点大厂的那些开源项目 - 滴滴出行

滴滴出行是涵盖出租车、 专车、滴滴快车、 顺风车、代驾及大巴、货运等多项业务在内的一站式出行平台。Nightingale 夜莺分类&#xff1a;监控系统夜莺是一套分布式高可用的运维监控系统&#xff0c;最大的特点是混合云支持&#xff0c;既可以支持传统物理机虚拟机的场景&#…

阿里巴巴发布智能运维故障管理AI+生态计划

摘要&#xff1a; 为响应马老师“家国情怀&#xff0c;世界担当”的号召&#xff0c;开放“AI”生态计划&#xff0c;将让集团内部服务过程中积累下的技术与经验更好地回馈社会&#xff0c;任何企业或合作伙伴均可以简单方便的接入阿里巴巴智能故障管理平台&#xff0c;通过对接…

k8s 读书笔记 - Pod 的升级和回滚

Pod 升级可能面临的问题当集群中的某个服务需要升级时&#xff0c;我们需要停止目前与该服务相关的所有 Pod&#xff0c;然后下载新版本镜像并创建新的 Pod。但是当集群规模比较庞大时&#xff0c;那么这个工作就会变成一个挑战&#xff0c;而且先全部停止然后再逐步升级的方式…

《ASP.NET Core 6框架揭秘》实例演示[21]:如何承载你的后台服务

借助 .NET提供的服务承载&#xff08;Hosting&#xff09;系统&#xff0c;我们可以将一个或者多个长时间运行的后台服务寄宿或者承载我们创建的应用中。任何需要在后台长时间运行的操作都可以定义成标准化的服务并利用该系统来承载&#xff0c;ASP.NET Core应用最终也体现为这…