WPF中MVVM架构学习笔记

MVVM架构是一种基于数据驱动的软件开发架构,它将数据模型(Model)、视图(View)和视图模型(ViewModel)三者进行分离,使得开发者可以更加专注于各自领域的开发。其中,Model负责存储和管理数据,View负责数据的展示,而ViewModel则作为Model和View之间的桥梁,负责数据的双向绑定和业务逻辑的处理。

MVVM架构的特点

  1. 数据驱动:MVVM架构的核心是数据驱动,当数据发生变化时,视图会自动更新,反之亦然。这种双向数据绑定的机制大大减少了开发者在视图和数据之间手动同步的工作量。
  2. 分离关注点:通过将Model、View和ViewModel三者进行分离,开发者可以更加专注于各自领域的开发,提高了代码的可维护性和可重用性。
  3. 视图与业务逻辑解耦:ViewModel负责处理业务逻辑,而View只负责展示数据,这种设计使得视图和业务逻辑之间的耦合度大大降低,提高了代码的可读性和可测试性。

 实现效果 :

阶段一:代码创建文件放置,搭建出INotifyPropertyChanged进行前后台数据更新

<Grid><Grid.RowDefinitions><RowDefinition Height="100"/><RowDefinition Height="150"/><RowDefinition/><RowDefinition/></Grid.RowDefinitions><Border BorderThickness="1" BorderBrush="Black" Grid.Row="1" Height="30" Width="200" VerticalAlignment="Top" ><TextBox  Text="{Binding UserName}"/></Border><Border BorderThickness="1" BorderBrush="Black" Grid.Row="1" Height="30" Width="200" VerticalAlignment="Top" Margin="0,40,0,0"  ><TextBox Text="{Binding PassWord}" /></Border><Button Grid.Row="1" Height="30" Width="200" VerticalAlignment="Bottom" Content="按钮" Click="Button_Click"/></Grid>
namespace WpfApp_libarymassage
{/// <summary>/// MainWindow.xaml 的交互逻辑/// </summary>public partial class MainWindow : Window, INotifyPropertyChanged{public MainWindow(){this.DataContext = this;InitializeComponent();}private string _UserName;public string UserName{get { return _UserName; }set { _UserName = value;OnPropertyChanged("UserName");}}private string _PassWord;public string PassWord{get { return _PassWord; }set { _PassWord = value;OnPropertyChanged(PassWord);}}public event PropertyChangedEventHandler PropertyChanged;protected void OnPropertyChanged(string propertyName){PropertyChangedEventHandler handler = PropertyChanged;if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));}private void Button_Click(object sender, RoutedEventArgs e){//string useName = textUserName.Text;//string passWord = textPassWord.Text;if (UserName == "AA" && PassWord == "123456" ){MessageBox.Show("Loding Successful");}else{MessageBox.Show("Load Fail");UserName = "";PassWord = "";}}}}

阶段二:创建Model和ViewModel文件,降低数据的关联

LoginModel.cs文件

public class LoginModel : INotifyPropertyChanged
{public event PropertyChangedEventHandler PropertyChanged;protected void OnPropertyChanged(string propertyName){PropertyChangedEventHandler handler = PropertyChanged;if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));}private string _UserName;public string UserName{get { return _UserName; }set{_UserName = value;OnPropertyChanged("UserName");}}private string _PassWord;public string PassWord{get { return _PassWord; }set{_PassWord = value;OnPropertyChanged(PassWord);}}
}

LoginViewModel.cs

 public class LoginViewModel{private LoginModel _loginM; //创建LoginModel类型的变量_loginMpublic LoginModel LoginM   {get { if (_loginM == null)   //如果没有实列化LoginModel,实列化LoginModel_loginM = new LoginModel();return _loginM; }set { _loginM = value; }}}

XAM文件 

 public partial class MainWindow : Window{LoginViewModel loginViewModel; //创建变量LoginViewModel类型的变量loginViewModelpublic MainWindow(){         loginViewModel = new LoginViewModel(); //loginViewModel进行实列化this.DataContext = loginViewModel;    //绑定上下文InitializeComponent();}private void Button_Click(object sender, RoutedEventArgs e){//因为我们实列话了LoginViewModel(),绑定的的变量是在LoginViewModel中的LoginM中//所以变量连接为loginViewModel.LoginM.UserNameif (loginViewModel.LoginM.UserName == "AA" && loginViewModel.LoginM.PassWord == "123456" ){MessageBox.Show("Loding Successful");}else{MessageBox.Show("Load Fail");loginViewModel.LoginM.UserName = "";loginViewModel.LoginM.PassWord = "";}}}
  <Border BorderThickness="1" BorderBrush="Black" Grid.Row="1" Height="30" Width="200" VerticalAlignment="Top" ><TextBox  Text="{Binding LoginM.UserName}"/></Border><Border BorderThickness="1" BorderBrush="Black" Grid.Row="1" Height="30" Width="200" VerticalAlignment="Top" Margin="0,40,0,0"  ><TextBox Text="{Binding LoginM.PassWo

阶段三:将按钮放入ViewModel中

ICommand接口调用

RelayCommander.cs

internal class RelayCommander:ICommand
{readonly Func<bool> _canExecute; //命令是否能够执行readonly Action _execute; //命令需要执行的方法public RelayCommander(Action action, Func<bool> canExecute){_execute =action;_canExecute =canExecute;}public bool CanExecute(object parameter){if (_canExecute != null){return true;}return _canExecute();}public void Execute(object parameter){_execute();}public event EventHandler CanExecuteChanged{add{if (_canExecute != null){CommandManager.RequerySuggested += value;}}remove{if ( _canExecute != null){CommandManager.RequerySuggested -= value;}}}
}

在ViewModel中调用接口

public class LoginViewModel
{private LoginModel _loginM; //创建LoginModel类型的变量_loginMpublic LoginModel LoginM   {get { if (_loginM == null)   //如果没有实列化LoginModel,实列化LoginModel_loginM = new LoginModel();return _loginM; }set { _loginM = value; }}//登录按钮方法void LoginFunc(){if (LoginM.UserName == "AA" && LoginM.PassWord == "123456"){MessageBox.Show("Loding Successful");}else{MessageBox.Show("Load Fail");LoginM.UserName = "";LoginM.PassWord = "";}}bool CanLoginExcute() { return true; }//命令绑定至按钮public ICommand LoginButton   //LoginButton参数为按钮Command绑定的参数{ get{return new RelayCommander(LoginFunc, CanLoginExcute);}}}

xaml

public partial class MainWindow : Window
{LoginViewModel loginViewModel; //创建变量LoginViewModel类型的变量loginViewModelpublic MainWindow(){         loginViewModel = new LoginViewModel(); //loginViewModel进行实列化this.DataContext = loginViewModel;    //绑定上下文InitializeComponent();}}
<Button Grid.Row="1" Height="30" Width="200" VerticalAlignment="Bottom" Content="按钮" Command="{Binding LoginButton}"/>

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Add object from object library 从对象库中添加内置器件

Add object from object library 从对象库中添加内置器件 正文正文 对于 Lumerical,有些时候我们在使用中,可能需要从 Object library 中添加器件,通常我们的做法是手动添加。如下图所示,我们添加一个 Directional Coupler 到我们的工程文件中: 但是这种操作方式不够智能…

封装了一个iOS中间放大的collectionView layout

效果图如下所示 原理&#xff1a;就是首先确定一个放大和缩小系数和原大小对应的基准位置&#xff0c;然后根据距离每个布局属性到视图中心的距离和基准点到中心的距离的差距/基准点到中心的距离&#xff0c; 计算出每个布局属性的缩放系数 下面是代码 // // LBHorizontalCe…

基于AT89C52单片机的智能窗帘系统

点击链接获取Keil源码与Project Backups仿真图&#xff1a; https://download.csdn.net/download/qq_64505944/89276984?spm1001.2014.3001.5503 C 源码仿真图毕业设计实物制作步骤07 智能窗户控制系统学院&#xff08;部&#xff09;&#xff1a; 专 业&#xff1a; 班 级&…

springboot vue 开源 会员收银系统 (4) 门店模块开发

前言 完整版演示 前面我们对会员系统 springboot vue 开源 会员收银系统 (3) 会员管理的开发 实现了简单的会员添加 下面我们将从会员模块进行延伸 门店模块的开发 首先我们先分析一下常见门店的管理模式 常见的管理形式为总公司 - 区域管理&#xff08;若干个门店&#xff…

论文精读-SwinIR Image Restoration Using Swin Transformer

论文精读-SwinIR: Image Restoration Using Swin Transformer SwinIR:使用 Swin Transformer进行图像恢复 参数量&#xff1a;SR 11.8M、JPEG压缩伪影 11.5M、去噪 12.0M 优点&#xff1a;1、提出了新的网络结构。它采用分块设计。包括浅层特征提取&#xff1a;cnn提取&#…

【C++】C++11(一)

C11是一次里程碑式的更新&#xff0c;我们一起来看一看~ 目录 列表初始化&#xff1a;{ }初始化&#xff1a;std::initializer_list&#xff1a; 声明&#xff1a;auto&#xff1a;decltype&#xff1a; STL的一些变化&#xff1a; 列表初始化&#xff1a; { }初始化&#xf…

JavaSE——类和对象(二)~~封装

目录 一.封装 二.封装扩展之包 三.static成员 四. 代码块 五. 内部类&#xff08;重要&#xff09; 大家好呀&#xff0c;我是北纬&#xff0c;接着上节我们继续讲解Java中关于类和对象的相关知识&#xff0c;今天着重给大家介绍一下关于面向对象程序的特性之一——封装。…

最新php项目加密源码

压缩包里有多少个php就会被加密多少个PHP、php无需安装任何插件。源码全开源 如果上传的压缩包里有子文件夹&#xff08;子文件夹里的php文件也会被加密&#xff09;&#xff0c;加密后的压缩包需要先修复一下&#xff0c;步骤&#xff1a;打开压缩包 》 工具 》 修复压缩文件…

STM32——IIC篇

技术笔记&#xff01; 一、IIC总线协议介绍&#xff08;掌握&#xff09; 1.1 IIC总线结构图 1.2 IIC协议时序 1.3 硬件和软件IIC对比 二、AT24C02介绍&#xff08;了解&#xff09; 2.1 AT24C02通讯地址 三、AT24C02读写时序&#xff08;掌握&#xff09; 3.1 写时序 3.…

有趣的css - 移形换位加载动画

大家好&#xff0c;我是 Just&#xff0c;这里是「设计师工作日常」&#xff0c;今天分享的是一个移形换位动态加载小动效&#xff0c;适用于 app 列表加载&#xff0c;页面加载或者图片懒加载等场景。 最新文章通过公众号「设计师工作日常」发布。 目录 整体效果核心代码html…

Ubuntu22.04本地部署qwen模型、jupyterlab开发环境、LoRA微调全流程

前言 这段时间在自己的Win11系统上部署了chatGLM以及Qwen模型&#xff0c;进行对话、推理以及工具调用都没有问题&#xff0c;但是在尝试进行微调的时候发现好像并不能成功&#xff0c;因此花费了很大的力气&#xff0c;又分别在ubuntu桌面版、windows子系统WSL2 Ubuntu上部署…

数据可视化第9天(利用wordcloud和jieba分析蝙蝠侠评论的关键字)

数据可以在这里下载 https://github.com/harkbox/DataAnalyseStudy WordCloud wordcloud可以很方便的生成词云图&#xff0c;方便的提供可视化可以直接使用pip install wordcloud进行安装如果使用的是Anaconda,可以使用conda install进行安装 下面看一个简单的例子 txt &qu…

JVM学习-堆空间(三)

JVM在进行GC时&#xff0c;并非每次都对新生代、老年代、方法区(元空间)三个区域一起回收&#xff0c;大部分时间回收的都是新生代 针对Hotspot VM的实现&#xff0c;它里面的GC按照回收区域分两大类型&#xff1a;一种是部分收集(Partial GC)&#xff0c;一种是整堆收集(Full …

amtlib.dll打不开怎么办?一键修复丢失amtlib.dll方法

电脑丢失amtlib.dll文件是什么情况&#xff1f;出现amtlib.dll打不开怎么办&#xff1f;这样的情况有什么解决方法呢&#xff1f;今天就和大家聊聊amtlib.dll文件同时教大家一键修复丢失amtlib.dll方法&#xff1f;一起来看看amtlib.dll文件丢失会有哪些方法修复&#xff1f; a…

Docker配置国内镜像源

添加Docker国内镜像源 在/etc/docker/daemon.json文件中添加以下内容&#xff1a; {"registry-mirrors": ["http://hub-mirror.c.163.com","https://docker.mirrors.ustc.edu.cn","https://registry.docker-cn.com"] }重启docker s…

【Python】—— lambda表达式

目录 &#xff08;一&#xff09;应用场景 &#xff08;二&#xff09;lambda 语法 &#xff08;三&#xff09;示例分析 &#xff08;四&#xff09;lambda参数形式 4.1 无参数 4.2 一个参数 4.3 默认参数 4.4 可变参数 &#xff1a;*args 4.5 可变参数 &#xff1a;…

第四十一天 | 62.不同路径 63.不同路径|| 343.整数拆分 96.不同的二叉搜索树

题目&#xff1a;62.不同路径 1.二维dp数组dp[i][j]含义&#xff1a;到达&#xff08;i&#xff0c;j&#xff09;位置有dp[i][j]种方法。 2.动态转移方程&#xff1a;dp[i][j] dp[i - 1][j] dp[i][j - 1] 3.初始化&#xff1a;dp[0][j] 1, dp[i][0] 1 &#xff08;第一…

Spring Cloud 之 Gateway

本篇主要介绍有关Gateway网关的相关内容。 目录 一、什么是网关 二、Gateway的使用 Gateway服务的搭建 Route Predicate Factories Gateway Filter Factories Filter GlobalFilter Filter的执行顺序 一、什么是网关 经常面试的人肯定知道&#xff0c;在去公司面试时…

CAN笔记第二篇,车载测试继续学起来!

在CAN协议中&#xff0c;“帧”是一个包含完整信息的独立单元&#xff0c;它具有特定的格式和结构&#xff0c;以确保数据在CAN总线上的可靠传输。这里的“帧”字可以理解为&#xff1a; 完整性&#xff1a;一个帧包含了所有必要的信息&#xff0c;从起始到结束&#xff0c;都遵…

【LeetCode】【1】两数之和(1141字)

文章目录 [toc]题目描述样例输入输出与解释样例1样例2样例3 提示进阶Python实现哈希表 个人主页&#xff1a;丷从心 系列专栏&#xff1a;LeetCode 刷题指南&#xff1a;LeetCode刷题指南 题目描述 给定一个整数数组nums和一个整数目标值target&#xff0c;请在该数组中找出…