最新.net6 wpf MVVMToolkit 8.0 工程搭建。

MVVMToolkit是一个轻量级MVVM框架,在框架下我们第一个要做的就是搞清在此框架下的一些常规操作:属性绑定和通知,命令绑定,消息传递。搞懂这些处理流程,然后就可以写自己业务的逻辑。

1.安装mvvmtoolkit

1.1Nuget下载CommunityToolkit.Mvvm

1.2调整目录结构

添加3个文件夹:Views Models ViewModels。

Views下放界面的xmal文件

Models下放数据模型

ViewModels下放逻辑代码

并把MainWindow.xaml移动到Views文件夹下,需要修改3个地方:

App.xaml.cs:

Mainwindow.xaml:

MainWindow.xaml.cs

创建一个类处理逻辑,命名MainViewModel,放在ViewModels下

创建一个类描述数据模型,命名CalculateModel,放在Models下

UI界面设计:

CalculateModel类:

界面上的textbox分别绑定CalculateModel中的a b c

 public class CalculateModel
{
//计算a+b=c
public int a { get; set; }
public int b { get; set; }
public int c { get; set; } }
}

布局代码:

<Grid>
<StackPanel >
<StackPanel Orientation="Horizontal">
<TextBlock Text=" a" Width="50"/>
<TextBox Width="100" Text="{Binding calculateModel.a}"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text=" b" Width="50"/>
<TextBox Width="100" Text="{Binding calculateModel.b}"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text=" c" Width="50"/>
<TextBox Width="100" Text="{Binding calculateModel.c}"/>
</StackPanel> <Button Content="计算" Height="30" Width="50" HorizontalAlignment="Left" />
</StackPanel>
</Grid>

MainViewModel代码:

public class MainViewModel
{
    //在MianViewModel中写处理逻辑,这个类 类似于在不分mvvm模式下的后台的代码
public CalculateModel? calculateModel { get; set; }
public MainViewModel()
{
calculateModel = new CalculateModel();
calculateModel.a = 1;
calculateModel.b = 1;
calculateModel.c = calculateModel.a + calculateModel.b;
}
}

在MainWindow.xaml.cs中添加DataContext

public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new MainViewModel();
}
}

运行结果:可以看到能绑定成功了,然后就是介绍 属性绑定通知,命令绑定,消息传递的功能了。

需要注意的:

1.一个View对应一个ViewModel,usercontrol也算一种view

2.新建的MainViewModel是一个独立的类,和界面没有关联,为了能够让UI界面找到MainViewModel类中的属性,则需要设置DataContext

this.DataContext = new MainViewModel();这里的this就是指MainWindow。

2.属性的绑定和通知

属性想要实现通知功能,属性所在的类需要继承ObservableObject,并在属性的set访问器中添加SetProperty

把上面的CalculateModel修改为可通知的:

public class CalculateModel: ObservableObject
{
//计算a+b=c
private int _a;
private int _b;
private int _c; public int a
{
get { return _a; }
set {
SetProperty(ref _a, value);
}
}
public int b
{
get { return _b; }
set
{
SetProperty(ref _b, value);
}
}
public int c
{
get { return _c; }
set
{
SetProperty(ref _c, value);
}
}
}

通过调用add方法,修改a b c的值,界面也会自动通知

public void add()
{
calculateModel.a = 11;
calculateModel.b = 11;
calculateModel.c = calculateModel.a + calculateModel.b; }

默认:

调用add方法后:

可以看到实现了数据通知的功能,命令的使用方法在后面。

几个需要注意的地方:

1.可通知的属性必须是属性,不能是字段,由get set访问器的是属性,并且访问权限是public。

     //定义属性
public int MyProperty { get; set; }
//定义字段
public int MyProperty1;

2.被绑定的属性在哪个类中,该类就得继承ObservableObject

这个例子中a b c这3个属性在CalculateModel类中,所以是CalculateModel类继承ObservableObject

如果a b c这3个属性直接定义在MainViewModel中,则MainViewModel类需要继承ObservableObject

一个datacontext的问题:

目前这个例子的逻辑是这样:

假如现在MainViewModel中也有abc3个属性了,UI界面想绑定MainViewModel中的abc,而不是去绑定CalculateModel中的abc,则需要这样绑定

 <TextBox Width="100" Text="{Binding b}"/>

3.命令的绑定

不使用mvvm模式时,都是直接处理各种事件,Click DoubleClick等等,在使用mvvm模式下,使用Command代替事件处理。

第2部分介绍了属性的绑定。命令的绑定也和属性的绑定一样简单,把命令当成属性来处理就行了,属性和命令都属于某个类。结合属性的绑定,命令也需要是public的,必须带get set访问器。

看一个简单的例子:

 <Button Content="计算" Command="{Binding addCommand}" Height="30" Width="50" HorizontalAlignment="Left" />

当点击Button时执行 Command,Command绑定了一个addCommand(这个是我们自己写的),

定义命令:

public class MainViewModel
{
public CalculateModel? calculateModel { get; set; } public MainViewModel()
{
calculateModel = new CalculateModel();
calculateModel.a = 1;
calculateModel.b = 1;
calculateModel.c = calculateModel.a + calculateModel.b;
       //第三步:给命令赋值一个方法,当命令被触发时会自动调用赋值的方法
addCommand = new RelayCommand(add);
}
    //第一步:定义一个命令
public RelayCommand addCommand { get; set; }
    //顶二步:定义一个普通的方法
public void add()
{
calculateModel.a = 11;
calculateModel.b = 11;
calculateModel.c = calculateModel.a + calculateModel.b;
}
}

总结就3点:定义一个方法,定义一个命令,把方法和命令关联起来。

当点击button时会调用add方法。

疑惑的点:命令要定义在哪里?

解释:可以定义在Model中,也可以定义在ViewModel中,都可以。

4.MvvmToolkit框架下任意命令的绑定

只有Button由Command,其他控件没有怎么处理?

参考这篇文章,多种方法

WPF 任意事件绑定 - 薛定谔的小灯泡 - 博客园 (cnblogs.com)

5.消息传递

在mvvm模式下,项目的组成可能是这样的:

一般是这样:

一个View对应一个ViewModel,操作View的数据的逻辑,写在对应的ViewModle中,操作View界面的和业务无关的逻辑写在View.xaml.cs中

ViewModel中定义Model,然后处理

View和ViewModel之间可以互相传递消息。在mvvmtoolkit框架下,提供了传递消息的机制

5.1 WeakReferenceMessenger基本理解

既然是传递消息,就会有2方:收消息的一方和发消息的一方

收消息:WeakReferenceMessenger.Default.Register

发消息:WeakReferenceMessenger.Default.Send

a给b发送消息,b必须提前注册好这个消息,也就是说b是提前知道a会给它发消息的。

假如上面的例子实现这样一个功能,

点击“计算”按钮后,计算出a+b的结果,并使用MessageBox弹出这个结果。

其中的逻辑:“计算”按钮的点击绑定了ViewModel中的命令,在ViewModel中计算结果,弹窗需要在View.xmal.cs中处理,所以在ViewModel中给View.xaml.cs发送结果,在View.xmal.cs中接收到消息后,弹出结果

ViewModel代码:

发消息:

MainWindow.xaml.cs代码:

收消息:

运行结果:

这里传递的消息类型必须是引用,int double之类的非引用类型无法传递

发消息和收消息的2方靠什么识别是否接收呢?

如果没有写Token,则以消息的类型判断,双方消息的类型一致则能成功发送消息

如果写了Token,则判断Token和消息类型

Token的写法:

6.MvvmToolkit框架下IOC的处理

mvvmtoolkit框架没有提供IOC容器,需要额外处理,这里使用微软的 SeverCollection (ServiceProvider)仿照mvvmlight的Locator写一个,引用Nuget包microsoft.extensions.dependencyinjection

第1步:添加microsoft.extensions.dependencyinjection,在ViewModels文件夹下创建一个Locator类

Locator代码:

public class Locator
{
public static IServiceProvider? ServiceProvide { get; set; }
public Locator()
{
ServiceProvide = GetService();
} private IServiceProvider GetService()
{
var service = new ServiceCollection();
service.AddSingleton<MainViewModel>();
return service.BuildServiceProvider();
}
public MainViewModel MainViewModel
{
get
{
return ServiceProvide.GetService<MainViewModel>();
}
}
}

第2步:修改dataContext

第3步:修改UI界面绑定时的层级关系

修改前:

修改后:

WPF MvvmToolkit入门的更多相关文章

  1. WPF快速入门系列(1)——WPF布局概览

    一.引言 关于WPF早在一年前就已经看过<深入浅出WPF>这本书,当时看完之后由于没有做笔记,以至于我现在又重新捡起来并记录下学习的过程,本系列将是一个WPF快速入门系列,主要介绍WPF中 ...

  2. WPF从入门到放弃系列第二章 XAML

    本文是作者学习WPF从入门到放弃过程中的一些总结,主要内容都是对学习过程中拜读的文章的整理归纳. 参考资料 XAML 概述 (WPF):https://msdn.microsoft.com/zh-cn ...

  3. WPF自学入门(三)WPF路由事件之内置路由事件

    有没有想过在.NET中已经有了事件机制,为什么在WPF中不直接使用.NET事件要加入路由事件来取代事件呢?最直观的原因就是典型的WPF应用程序使用很多元素关联和组合起来,是否还记得在WPF自学入门(一 ...

  4. WPF自学入门(六)WPF带标题的内容控件简单介绍

    在WPF自学入门(二)WPF-XAML布局控件的文章中分别介绍StackPanel,WarpPanel,DockPanel,Grid,Canvas五种布局容器的使用,可以让我们大致了解容器可以使用在什 ...

  5. WPF自学入门(十一)WPF MVVM模式Command命令

    在WPF自学入门(十)WPF MVVM简单介绍中的示例似乎运行起来没有什么问题,也可以进行更新.但是这并不是我们使用MVVM的正确方式.正如上一篇文章中在开始说的,MVVM的目的是为了最大限度地降低了 ...

  6. WPF自学入门(十二)WPF MVVM模式提取函数

    我们平时在写代码时为了不重复写代码,会进行复制代码或者写通用方法.今天我们就来把上传做的函数提取成为通用的方法调用.把上次写的函数提取为两个主要的文件:ObserableObject和RelayCom ...

  7. WPF自学入门(十一)WPF MVVM模式Command命令 WPF自学入门(十)WPF MVVM简单介绍

    WPF自学入门(十一)WPF MVVM模式Command命令   在WPF自学入门(十)WPF MVVM简单介绍中的示例似乎运行起来没有什么问题,也可以进行更新.但是这并不是我们使用MVVM的正确方式 ...

  8. WPF快速入门系列(8)——MVVM快速入门

    一.引言 在前面介绍了WPF一些核心的内容,其中包括WPF布局.依赖属性.路由事件.绑定.命令.资源样式和模板.然而,在WPF还衍生出了一种很好的编程框架,即WVVM,在Web端开发有MVC,在WPF ...

  9. WPF快速入门系列(4)——深入解析WPF绑定

    一.引言 WPF绑定使得原本需要多行代码实现的功能,现在只需要简单的XAML代码就可以完成之前多行后台代码实现的功能.WPF绑定可以理解为一种关系,该关系告诉WPF从一个源对象提取一些信息,并将这些信 ...

  10. WPF简单入门总结

    WPF简单总结 最近看了点关于WPF的东西,总结了点点入门的东西. XAML语法基础 1.  定义样式 <Window.Resources><!--窗体资源的定义--> < ...

随机推荐

  1. 提升SEO与网站可爬性 :动态生成sitemaps和robots.txt文件

    本文由 ChatMoney团队出品 在现代Web开发中,搜索引擎优化(SEO)是网站成功的关键因素之一.搜索引擎通过网络爬虫来索引网页,而sitemaps和robots.txt文件则是帮助这些爬虫更好 ...

  2. 关于PHP 函数性能优化的技巧

    本文由 ChatMoney团队出品 本文将详细介绍 PHP 函数性能优化的技巧.通过分析 PHP 函数的执行过程和性能瓶颈,提供一系列实用的优化方法,并结合代码示例,帮助读者提升 PHP 代码的执行效 ...

  3. c++ 预处理 编译 链接 文件组织形式

    -- 整体流程 C++ 源文件 (.cpp) ↓ 预处理(展开头文件.宏替换等) 预处理后的代码 (.i) ↓ 编译(编译器) 汇编代码 (.s) ↓ 汇编(汇编器) 目标文件 (.o / .obj) ...

  4. 开源交流丨批流一体数据集成框架ChunJun数据传输模块详解分享

    课件获取:关注公众号"ChunJun",后台私信 "课件" 获得直播课件 视频回放:点击这里 ChengYing开源项目地址:github 丨 gitee 喜欢 ...

  5. 首个离散元仿真软件EDEM好学吗?有什么学习技巧?

    EDEM是一款首个离散元仿真软件,它被广泛应用于工程领域,特别是在颗粒材料的模拟和分析方面.对于初学者来说,EDEM可能会有一定的学习曲线,但是只要掌握了一些学习技巧,就能够很快上手并熟练运用这款软件 ...

  6. Go协程简单学习

    什么是协程? 协程类似于线程,但是比线程更加轻量.一个程序启动会占用一个进程 而一个进程可以拥有多个线程 ,一个线程可以拥有多个协程. 一个进程至少包含一个主线程,一个主线程可以有更多的子线程. 线程 ...

  7. [Ynoi2016] 炸脖龙 I

    题目传送门 已经能过 hack,原因:做快速幂的时候需要微判一下边界.很好奇 lxl 为什么不卡 显然区间加可用线段树做. 然后操作二用扩展欧拉定理,每个 \(p\) 最多递归 \(\log\) 层, ...

  8. 前端开发系列044-基础篇之TypeScript语言特性(四)

    本文主要对TypeScript中的函数进行展开介绍.主要包括以下内容 ❏ 函数的创建和类型 ❏ 函数参数情况说明 ❏ 泛型函数简单介绍 一.函数的创建和类型 函数的创建 函数的创建主要有两种方式:通过 ...

  9. 华为机试题 求最大连续bit数

    简介 c = c++ ? c = ++c ? code #include <iostream> #include <string> using namespace std; i ...

  10. Delaunay 三角化 学习3

    简介 还是太菜从解析官方代码开始. 官方代码共有三个核心函数. 参考链接 http://blog.sina.com.cn/s/blog_6029f0330101irlh.html http://pau ...