首页 > 其他分享 >WPF MvvmToolkit入门

WPF MvvmToolkit入门

时间:2023-12-23 22:33:44浏览次数:32  
标签:set 入门 MvvmToolkit 绑定 MainViewModel get WPF public calculateModel

最新.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界面绑定时的层级关系

修改前:

 修改后:

标签:set,入门,MvvmToolkit,绑定,MainViewModel,get,WPF,public,calculateModel
From: https://www.cnblogs.com/chinasoft/p/17923758.html

相关文章

  • Swagger(一) Swagger/Springfox 入门简介
    转载自:https://blog.csdn.net/donglinjob/article/details/108550636 Swagger/Springfox入门简介一、Swagger 简介1前言接口文档对于前后端开发人员都十分重要。尤其近几年流行前后端分离后接口文档又变成重中之重。接口文档固然重要,但是由于项目周期等原因后端人员经......
  • [WPF] 使用 MVVM Toolkit 构建 MVVM 程序(CommunityToolkit.Mvvm)
    1.什么是MVVMToolkit模型-视图-视图模型(MVVM)是用于解耦UI代码和非UI代码的UI体系结构设计模式。借助MVVM,可以在XAML中以声明方式定义UI,并使用数据绑定标记将UI链接到包含数据和命令的其他层。微软虽然提出了MVVM,但又没有提供一个官方的MVVM库(多年前有过......
  • Stable_diffusion入门学习
    前言最近升级了一下电脑的显卡,搞了个4060ti16g的,于是乎终于可以玩玩一直想玩的AI绘画了。简单学习了一下入门教程,了解了一下基本的情况,于是选择秋葉大佬的启动器学习。但是要画出好看的绘画,还是需要借助于许多其他工具来优化和修复绘画的图形。接下来我将一一记录我在学习过程......
  • WPF+SqlSugar+MVVM实现增删改查
    1、新建一个WPF应用(NETFramework)2、安装SqlSugarNuGet包3、在SqlSugar4.x下载代码生成器https://www.donet5.com/Doc/8/11374、在WPF中新建三个文件夹Models主要放实体类、Views主要放窗体、ViewModels主要是View逻辑的实现5、把生成的实体类放到Models文件夹内,在V......
  • golang快速入门:并发编程(一)
    进程、线程和协程进程:是操作系统中的一个执行实体,它拥有独立的内存空间和系统资源。每个进程都是独立运行的,它们之间相互隔离,通过进程间通信(IPC)来进行数据交换。每个进程都有自己的地址空间、堆栈和文件描述符等。进程之间的切换开销较大,因为需要保存和恢复整个进程的状态。线程:是......
  • 浅谈WPF之DataGrid过滤,分组,排序
    使用过Excel的用户都知道,Excel可以方便的对数据进行分组,过滤,排序等操作,而在WPF中,默认提供的DataGrid只有很简单的功能,那么如何才能让我们开发的DataGrid,也像Excel一样具备丰富的客户端操作呢?今天就以一个简单的小例子,简述如何在WPF中实现DataGrid的过滤,筛选,排序等功能。仅供学习分......
  • [C++从入门到精通] 2.inline内联函数、const的相关用法
    作者:丶布布文章预览:一、返回类型二、内联函数inline三、函数杂合用法总结四、constchar*、charconst*、char*const三者的区别五、函数形参中带const一、返回类型前置类型:在函数声明和定义的时候,把函数返回类型写到函数名字之前的形式,叫前置返回类型voidfunc(inta);//函数......
  • [C++从入门到精通] 3.string类型的相关用法
    作者:丶布布文章预览:一.C++基本变量类型二.String对象的定义和初始化三.String对象的操作一.C++基本变量类型基本类型:int、double等。复合类型:引用、指针、const等。标准库类型:string(可变长字符串的处理)、vector(一种集合或容器的概念)、迭代器。对于字符串,在现实生活中,string......
  • [C++ 从入门到精通] 5.迭代器精彩演绎、失效分析及弥补、实战
    作者:丶布布文章预览:一.迭代器简介二.容器的迭代器类型三.迭代器begin()/end()操作,反向迭代器rbegin()/rend()操作四.迭代器相关操作五.constiterator迭代器5.1.cbegin()和cend()操作六.迭代器失效及弥补6.1.灾难程序演示七.范例演示7.1用迭代器遍历string数据7.2vect......
  • [C++从入门到精通] 10.回顾类内初始化、默认构造函数、=default
    ......