《深入浅出WPF》学习笔记六.手动实现Mvvm

news2024/11/15 6:56:15

《深入浅出WPF》学习笔记六.手动实现Mvvm

demo的层级结构,Mvvm常用项目结构

依赖属性基类实现

具体底层原理后续学习中再探讨,可以粗浅理解为,有一个全局对象使用list或者dic监听所有依赖属性,当一个依赖属性变化引发通知时,就会遍历查询对应的字典,通知View层进行处理。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace WpfApp11.ViewModels
{
    /// <summary>
    /// viewmodel的基类
    /// </summary>
    public class NotificationObject : INotifyPropertyChanged
    {
        /// <summary>
        /// 通知属性变化
        /// </summary>
        public event PropertyChangedEventHandler? PropertyChanged;

        public void RaisePropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                //实际方法,内部可以理解为一个字典对象
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

    }
}

命令属性基类实现

这个底层原理没了解过,后续学到了再说。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace WpfApp11.Commands
{
    public class DelegateCommand : ICommand
    {
        public event EventHandler? CanExecuteChanged;

        //是否可以执行
        public bool CanExecute(object? parameter)
        {
            if (this.CanExecuteFunc == null)
            {
                return true;
            }
            else
            {
                this.CanExecuteFunc(parameter);
                return true;
            }
        }

        //具体执行
        public void Execute(object? parameter)
        {
            if (this.ExecuteAction == null)
            {
                return;
            }
            this.ExecuteAction(parameter);
        }

        public Action<object> ExecuteAction { get; set; }

        public Func<object, bool> CanExecuteFunc { get; set; }
    }
}

View

<Window x:Class="WpfApp11.Views.CalculateView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp11.Views"
        mc:Ignorable="d"
        Title="CalculateView" Height="300" Width="300">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto"></RowDefinition>
            <RowDefinition Height="auto"></RowDefinition>
            <RowDefinition Height="auto"></RowDefinition>
            <RowDefinition Height="auto"></RowDefinition>
        </Grid.RowDefinitions>
        <StackPanel Grid.Row="0" Orientation="Horizontal" Margin="10">
            <Label>参数1:</Label>
            <TextBox Height="30" Width="100"  x:Name="tb1"  Text="{Binding Param1}"></TextBox>
        </StackPanel>
        <StackPanel Grid.Row="1" Orientation="Horizontal" Margin="10">
            <Label>参数2:</Label>
            <TextBox Height="30" Width="100"  x:Name="tb2" Text="{Binding Param2}"></TextBox>
        </StackPanel>
        <StackPanel Grid.Row="2" Orientation="Horizontal" Margin="10">
            <Label>结果:</Label>
            <TextBox Height="30" Width="100"  x:Name="tb3" Text="{Binding Result}"></TextBox>
        </StackPanel>
        <StackPanel Grid.Row="3" Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="10">
            <Button x:Name="btn1" Content="Calculate" Height="30" Width="100" Command="{Binding AddCommand}"></Button>
        </StackPanel>
    </Grid>
</Window>
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.Shapes;
using WpfApp11.ViewModels;

namespace WpfApp11.Views
{
    /// <summary>
    /// CalculateView.xaml 的交互逻辑
    /// </summary>
    public partial class CalculateView : Window
    {
        public CalculateView()
        {
            InitializeComponent();
            this.DataContext = new CalculateViewModel();
        }
    }
}

ViewModel

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WpfApp11.Commands;

namespace WpfApp11.ViewModels
{
    public class CalculateViewModel : NotificationObject
    {
        #region 依赖属性
        private string param1;

        public string Param1
        {
            get { return param1; }
            set
            {
                param1 = value;
                this.RaisePropertyChanged("Param1");
            }
        }

        private string param2;

        public string Param2
        {
            get { return param2; }
            set
            {
                param2 = value;
                this.RaisePropertyChanged("Param2");
            }
        }

        private string result;

        public string Result
        {
            get { return result; }
            set
            {
                result = value;
                this.RaisePropertyChanged("Result");
            }
        }
        #endregion

        /// <summary>
        /// 命令属性
        /// </summary>
        public DelegateCommand AddCommand {  get; set; }

        public void Add(object param)
        {
            this.Result = (Convert.ToInt32(this.Param1) + Convert.ToInt32(this.Param2)).ToString();
        }

        public CalculateViewModel()
        {
            Param1 = "0";
            Param2 = "0";
            Result = "0";
            this.AddCommand = new DelegateCommand();
            this.AddCommand.ExecuteAction = new Action<object>(this.Add);
        }


    }
}

App

<Application x:Class="WpfApp11.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfApp11"
             StartupUri="Views/CalculateView.xaml">
    <Application.Resources>
         
    </Application.Resources>
</Application>

结语

实际项目中基本都是使用成熟框架Prism或者MvvmLight,不需要手动造轮子,但学习要知所以然。

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

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

相关文章

目标检测之选择性搜索:Selective Search

文章目录 一.选择性搜索的具体算法二.保持多样性的策略三.给区域打分四.选择性搜索性能评估五.代码实现 论文地址&#xff1a; https://www.koen.me/research/selectivesearch/ 代码地址&#xff1a; https://github.com/AlpacaDB/selectivesearch 参考&#xff1a; https:/…

SpringBootWeb AOP

事务&AOP 1. 事务管理 1.1 事务回顾 在数据库阶段我们已学习过事务了&#xff0c;我们讲到&#xff1a; 事务是一组操作的集合&#xff0c;它是一个不可分割的工作单位。事务会把所有的操作作为一个整体&#xff0c;一起向数据库提交或者是撤销操作请求。所以这组操作要…

kickstart自动安装脚本,pxe网络安装

目录 1 kickstart图形化生成脚本工具 1.1 安装apache 1.2 创建挂载镜像软链接 1.3 图形生成自动化脚本选项 1.4 修改生成的自动化脚本 1.5 将脚本放至网站根目录 2 安装系统 2.1 关闭DHCP自动分配 2.2 下载配置DHCP服务 2.3 重启DHCP服务 2.4 使用pxe方法安装系统&#xff08;网…

YOLOv5与YOLOv8 训练准备工作(不包含环境搭建)

前言&#xff1a;我发现除了安装环境需要耗费大量时间以外&#xff0c;对于训练前的准备工作也要琢磨一段时间&#xff0c;所以本篇主要讲一下训练前需要准备的工作&#xff08;主要是XML格式换为txt&#xff0c;以及划分数据集验证集&#xff0c;和训练参数的设置&#xff09;…

8–9月,​Sui Move智能合约工作坊将在台北+线上举行

你对区块链和去中心化应用感兴趣吗&#xff1f;想深入学习Sui Move编程语言吗&#xff1f; 从8月10日到9月28日&#xff0c;Sui Mover社区将在每周六下午13:00–17:00举办精彩的工作坊&#xff0c;为期两个月&#xff0c;带你从零基础入门到高级进阶&#xff0c;全面掌握Sui M…

Django配置模板引擎

【图书介绍】《Django 5企业级Web应用开发实战&#xff08;视频教学版&#xff09;》_django 5企业级web应用开发实战(视频教学版)-CSDN博客 《Django 5企业级Web应用开发实战&#xff08;视频教学版&#xff09;》(王金柱)【摘要 书评 试读】- 京东图书 (jd.com) 本节主要介…

Linux之进程间通信(上)

目录 进程间通信的目的 进程通信的分类 进程通信之匿名管道 创建匿名管道 匿名管道的特点 匿名管道四种通信类型 在现实生活中&#xff0c;人们要进行合作&#xff0c;就必须进行交流&#xff0c;那么在进程之间&#xff0c;会存在交流的情景吗&#xff1f;答案是肯定的…

音频转换器在线哪个好?提升音频质量的转换工具

你是否曾梦想过将手机里的铃声变成自己的原创作品&#xff1f;或者&#xff0c;有没有想过将一段演讲录音转化为易于分享的MP3格式&#xff1f; 如果答案是肯定的&#xff0c;那么这款音频转换器mp3就是你寻找的答案。现在&#xff0c;让我们一起探索它的魅力吧&#xff01; 一…

基于MATLAB机器学习、深度学习实践技术

近年来&#xff0c;MATLAB在机器学习和深度学习领域的发展取得了显著成就。其强大的计算能力和灵活的编程环境使其成为科研人员和工程师的首选工具。在无人驾驶汽车、医学影像智能诊疗、ImageNet竞赛等热门领域&#xff0c;MATLAB提供了丰富的算法库和工具箱&#xff0c;极大地…

浏览器用户文件夹详解 - Preferences(十)

1.Preferences简介 1.1 什么是Preferences文件&#xff1f; Preferences文件是Chromium浏览器中用于存储用户个性化设置和配置的一个重要文件。每当用户在浏览器中更改设置或安装扩展程序时&#xff0c;这些信息都会被记录在Preferences文件中。通过这些记录&#xff0c;浏览…

海思ISP记录七:低照度图像调整

Hi3519av100imx585 记录下低照度图像调整的流程和思路 一、环境与配置 环境&#xff1a;暗房不开灯&#xff0c;只有零散漏光和电脑光亮gain与帧率&#xff1a;根据手册我设置的是Again&#xff1a;31282&#xff1b;Dgain&#xff1a;8192&#xff1b;ISP Dgain&#xff1a;…

B1.1 关于应用程序员模型-概述

快速链接: . 👉👉👉 ARMv8/ARMv9架构入门到精通-[目录] 👈👈👈 付费专栏-付费课程 【购买须知】个人博客笔记导读目录(全部) B1.1 关于应用程序员模型–概述 本章节包含了应用程序开发所需的程序员模型信息。 本章节中的信息不同于支持和服务于操作系统下应用程…

1.MySQL面试题之innodb如何解决幻读

1. 写在前面 在数据库系统中&#xff0c;幻读&#xff08;Phantom Read&#xff09;是指在一个事务中&#xff0c;两次读取同一范围的数据集时&#xff0c;由于其他事务的插入操作&#xff0c;导致第二次读取结果集发生变化的问题。InnoDB 作为 MySQL 的一个存储引擎&#xff…

PyTorch深度学习实战(2)——PyTorch快速入门

PyTorch的简洁设计使得它易于入门&#xff0c;在深入介绍PyTorch之前&#xff0c;本文先介绍一些PyTorch的基础知识&#xff0c;以便读者能够对PyTorch有一个大致的了解&#xff0c;并能够用PyTorch搭建一个简单的神经网络。 1 Tensor Tensor是PyTorch中最重要的数据结构&#…

docker、k8s部署 mysql group replication 和 ProxySQL 读写分离

MySQL Group Replication&#xff08;简称MGR&#xff09;是MySQL官方推出的一个高可用与高扩展的解决方案。MySQL组复制它提供了高可用、高扩展、高可靠的MySQL集群服务&#xff0c;这里部署的 mysql 版本 5.7.33&#xff0c;架构是一读一写。特别要注意一个关键点: 必须保证各…

sqli-labs-php7-master第11-16关

猜注入点 先来猜数字型 单引号字符型&#xff1a; 发现注入点找到了 猜测数据库有多少个字段&#xff1a; 1’ order by 4 # 密码随便输的。 这里没有使用--注释&#xff0c;因为没作用&#xff0c;可能是过滤掉了 继续猜。刚才没猜对 1 order by 2 # 没报错&#xff0c;猜…

如何将neo4j,4.x版本部署到服务器上

一. 简介 当我们使用neo4j构建知识图谱时&#xff0c;我们希望让别人能和我们共用neo4j进行知识图谱的构建&#xff0c;我们的方法之一就是将neo4j部署到我们的服务器上&#xff0c;然后将7474,7687端口暴露出来&#xff0c;这样就可以通过访问服务器公网IP的7474端口来操作我…

电脑硬盘坏了数据可以恢复吗?如何恢复硬盘数据?

电脑硬盘坏了数据可以恢复吗&#xff1f;对于这种问题&#xff0c;还需要具体问题具体分析的&#xff0c;一般是可以恢复。 硬盘损坏可以分为物理损坏和逻辑损坏两种情况&#xff1a; 1.逻辑损坏 这通常是由于软件问题&#xff0c;如文件系统错误、病毒攻击、误删除、格式化等…

CentOS Linux release 7.9.2009 中sudo命令未找到

先在 Windows 环境中下载 sudo 的安装包 选择适合自己 Centos 版本的安装包下载到本地&#xff1a;https://www.sudo.ws/releases/stable/ 然后把安装包拷贝的 Centos &#xff08;Linux系统&#xff09;中&#xff0c;cd 进入安装包所在的目录执行下面的命令&#xff1a; 格…

【Unity】线性代数基础:矩阵、矩阵乘法、转置矩阵、逆矩阵、正交矩阵等

文章目录 矩阵&#xff08;Matrix&#xff09;矩阵能干啥&#xff1f;矩阵基本运算矩阵加减法矩阵和标量的乘法矩阵和矩阵的乘法矩阵的转置矩阵相等 特殊的矩阵方块矩阵对称矩阵对角元素&#xff08;Diagonal Elements&#xff09;对角矩阵&#xff08;Diagonal Matrix&#xf…