ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

wpf-mvvm开发学习1

2022-05-25 13:00:53  阅读:221  来源: 互联网

标签:MVVM mvvm ViewModel System 学习 using wpf pidName View


最近在做wpf的程序 写到中期越来越恶心 所以尝试重构为MVVM模式

MVVM相关知识

0x01 什么是MVVM

1.Model

Model就是一个class,是对现实中事物的抽象,开发过程中涉及到的事物都可以抽象为Model,例如客户,客户的姓名、编号、电话、住址等属性也对应了class中的Property,客户的下订单、付款等行为对应了class中的方法。

2. View

View很好理解,就是界面。

3. ViewModel

上面说过Model抽象,那么ViewModel就是对View的抽象。显示的数据对应着ViewMode中的Property,执行的命令对应着ViewModel中的Command。

0x02 WPF中MVVM的解耦方式

在WPF的MVVM模式中,View和ViewModel之间数据和命令的关联都是通过绑定实现的,绑定后View和ViewModel并不产生直接的依赖。具体就是View中出现数据变化时会尝试修改绑定的目标。同样View执行命令时也会去寻找绑定的Command并执行。反过来,ViewModel在Property发生改变时会发个通知说“名字叫XXX的Property改变了,你们这些View中谁绑定了XXX也要跟着变啊!”,至于有没有View收到是不是做出变化也不关心。ViewModel中的Command脱离View就更简单了,因为Command在执行操作过程中操作数据时,根本不需要操作View中的数据,只需要操作ViewModel中的Property就可以了,Property的变化通过绑定就可以反映到View上。这样在测试Command时也不需要View的参与。这也是我在接触WPF初期时根本理解不了的所谓数据驱动。

这样一来ViewMode可以在完全没有View的情况下测试,View也可以在完全没有ViewModel的情况下测试(当然只是测试界面布局和动画等业务无关的内容)。

0x3 MVVM框架需要解决的问题

从图中可以看出如果要实现一套MVVM框架,需要解决的最基本的问题就是数据绑定和命令绑定。此外由于UI中会产生大量的事件,因此还需要将事件绑定到MVVM中的命令上。

实战开始

安装

Microsoft.Toolkit.Mvvm

Microsoft.Xaml.Behaviors.Wpf

PropertyChanged.Fody

image-20220524142927427

构建如图项目结构

一个简单demo

ProcessWindowModel.cs Model层

应该声明所需要的类 数据结构)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Toolkit.Mvvm.ComponentModel;
namespace lltool_MVVM.Model {
    internal class ProcessWindowModel {
    }
    public class myProcess : ObservableObject {

        private int _pid;
        private string _pidName;
        private bool _isChecked;
        private int _processSize;
        public int pid
        {
            get { return _pid; }
            set { _pid = value; }
        }
        public string pidName
        {
            get { return _pidName; }
            set { _pidName = value; }
        }
        public bool isChecked
        {
            get { return _isChecked; }
            set { _isChecked = value; }
        }
        public int processSize
        {
            get { return _processSize; }
            set { _processSize = value; }
        }
        
    }
}

ViewModel层

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using lltool_MVVM.Model;
using Microsoft.Toolkit.Mvvm.ComponentModel;
using Microsoft.Toolkit.Mvvm.DependencyInjection;
using Microsoft.Toolkit.Mvvm.Input;
using Microsoft.Toolkit.Mvvm.Messaging;
using Microsoft.Toolkit.Mvvm.Messaging.Messages;
namespace lltool_MVVM.ViewModel {
    public class myProcessViewModel : ObservableObject {
        public myProcessViewModel() {
            //将命令接口与真正的函数绑定
            UpdatePidNameCommand = new RelayCommand(UpdatePidNameExecute);
        }
        private string _pidName;
        //提供的SetProperty<T>(ref T, T, string)方法检查属性的当前值,如果不同则更新它,然后还会自动引发相关事件。
        //属性名称是通过使用[CallerMemberName]属性自动捕获的,因此无需手动指定要更新的属性。
        //暴露出pidName 便于外部进行绑定
        public string pidName
        {
            get { return _pidName; }
            set
            {
                SetProperty(ref _pidName , value);
            }
        }
        void UpdatePidNameExecute() {
            this.pidName = "new name";
            MessageBox.Show(this.pidName);
        }
        //一个接口 用于外部的button绑定
        public ICommand UpdatePidNameCommand { get; }
    }

}

View层

<metro:MetroWindow
    x:Class="lltool_MVVM.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:Aduskin="clr-namespace:AduSkin;assembly=AduSkin"
    xmlns:ViewModel="using:lltool_MVVM.ViewModel"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:lltool_MVVM"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:metro="clr-namespace:AduSkin.Controls.Metro;assembly=AduSkin"
    Title="MainWindow"
    Width="800"
    Height="450"
    mc:Ignorable="d">
    <Grid>
        <TextBlock Margin="20" Text="{Binding pidName}" />
        <Button Width="100" Height="100" Command="{Binding UpdatePidNameCommand}" Content="点我" />
    </Grid>

</metro:MetroWindow>

MainWindow.xaml.cs

using AduSkin.Controls.Metro;
using lltool_MVVM.ViewModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace lltool_MVVM {
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : MetroWindow {
        public MainWindow() {
            InitializeComponent();
            //绑定数据上下文
            DataContext = new myProcessViewModel
            {
                pidName = "2333"
            };
        }
    }
}

结果

image-20220525123732158

image-20220525123738535

标签:MVVM,mvvm,ViewModel,System,学习,using,wpf,pidName,View
来源: https://www.cnblogs.com/FW-ltlly/p/16308932.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有