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类型的变量_loginM
     public 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类型的变量loginViewModel
     public MainWindow()
     {         
         loginViewModel = new LoginViewModel(); //loginViewModel进行实列化
         this.DataContext = loginViewModel;    //绑定上下文
         InitializeComponent();

     }



     private void Button_Click(object sender, RoutedEventArgs e)
     {
         //因为我们实列话了LoginViewModel(),绑定的的变量是在LoginViewModel中的LoginM中
         //所以变量连接为loginViewModel.LoginM.UserName
         if (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类型的变量_loginM
    public 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类型的变量loginViewModel
    public MainWindow()
    {         
        loginViewModel = new LoginViewModel(); //loginViewModel进行实列化
        this.DataContext = loginViewModel;    //绑定上下文
        InitializeComponent();

    }

}
<Button Grid.Row="1" Height="30" Width="200" VerticalAlignment="Bottom" Content="按钮" Command="{Binding LoginButton}"/>

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

系统架构师考试(十)

SaaS为在线客服 PaaS为二次开发&#xff0c;比如低代码平台 IaaS 硬件开发 B 是基础设施作为服务 软件架构的概念 架构风格 数据流风格 网络报文是在计算机网络中通过网络传输的数据单元&#xff0c;它是网络通信的基本单位。网络报文包含了发送方和接收方之间传输的数据&…

蛮力法0/1背包问题实验

实验项目1 蛮力法 实验题目 使用蛮力法解决0/1背包问题。 ​ 问题描述&#xff1a;给定n个重量(weight)为{w1, w2, … ,wn}、价值(key)为{v1, v2, … ,vn}的物品和一个**容量为C(contain)**的背包&#xff0c;求这些物品中的一个最有价值的子集&#xff0c;且要能够装到背包中…

第十三期Big Demo Day亮点项目:CCarbon重塑碳交易生态,助力全球绿色发展

第十三期Big Demo Day活动即将于2024年5月28日在香港数码港的CyberArena隆重举行。我们荣幸地宣布&#xff0c;利用区块链技术优化全球碳交易CCarbon项目将亮相&#xff0c;参与精彩的项目路演。本次活动由ZeeprLabs、BiKing Exchange、Gather冠名赞助&#xff0c;Central Rese…

【教学类-56-03】数感训练——数字03(寻找自己的学号数字,1号-31号,出现15-20次)

背景需求&#xff1a; 在实际操作中&#xff0c;孩子们把数字当做了自己的学好&#xff0c;这个提示老师可以给每位孩子做一份“学号数感训练 【教学类-56-02】数感训练——数字02&#xff08;控制指定数字出现的数量&#xff09;-CSDN博客文章浏览阅读341次&#xff0c;点赞…

【Linux学习】深入探索进程等待与进程退出码和退出信号

文章目录 退出码return退出 进程的等待进程等待的方法 退出码 main函数的返回值&#xff1a;进程的退出码。 一般为0表示成功&#xff0c;非0表示失败。 每一个非0退出码都表示一个失败的原因&#xff1b; echo $&#xff1f;命令 作用&#xff1a;查看进程退出码。&#xf…

学AI绘图【300集SD新课】--Stable Diffusion教程

学AI绘图需要以下步骤&#xff1a; 明确目标和需求&#xff1a;首先明确设计图的目的&#xff0c;是用于展示算法流程、模型结构还是其他目的。选择合适的工具&#xff1a;根据需求选择合适的绘图工具&#xff0c;如Visio、PowerPoint、Adobe Illustrator等。绘制草图&#xf…

jmeter之HTTP请求和查看结果树

一、HTTP请求作用&#xff1a; 可以发送post或get请求等请求可以向服务器发送参数或消息体数据可以进行文件上传 HTTP请求&#xff1a;是线程组内的取样器最常用的的一个原件 二、查看界面 添加一个HTTP请求&#xff1a;选择线程组–添加–取样器–HTTP请求 默认界面 名称和…

Steam游戏被攻击怎么办,如何针对性的做好防护措施

在现代网络环境中&#xff0c;在线游戏经常成为各种网络攻击的目标&#xff0c;尤其是DDoS攻击。这类攻击不仅会导致游戏服务器瘫痪&#xff0c;还会影响玩家的游戏体验&#xff0c;损害游戏开发商的声誉和经济利益。为了应对这些威胁&#xff0c;使用专门的防护措施是必要的。…

Scrapy框架简单介绍及Scrapy项目编写详细步骤

引言 Scrapy是一个用Python编写的开源、功能强大的网络爬虫框架&#xff0c;专为网页抓取和数据提取设计。它允许开发者高效地从网站上抓取所需的数据&#xff0c;并通过一系列可扩展和可配置的组件来处理这些数据。Scrapy框架的核心组成部分包括&#xff1a; Scrapy Engine&…

rclone迁移对象存储之间的数据

1 概述 rclone是一款文件复制工具&#xff0c;既可以用于在linux主机之间复制文件&#xff0c;也可以在对象存储之间复制文件。 rclone的官网为&#xff1a; https://rclone.orgrlcone关于对象存储的官方文档为&#xff1a; https://rclone.org/s32 安装 2.1 yum安装 yum …

centos7.9用docker运行一个nginx容器

首先你的linux 系统里面已经安装好了docker&#xff0c;docker的安装教程看这个 1&#xff0c;下载nginx镜像 有很多文章会把镜像下载说成是拉取镜像&#xff0c; 我觉得就是下载的意思啊&#xff0c;搞不懂为什么要说拉取&#xff1f; docker pull nginx 下载最新版 Nginx …

深度学习之基于Unet的新冠肺炎等级分割分类系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景与意义 近年来&#xff0c;新冠肺炎&#xff08;COVID-19&#xff09;疫情给全球公共卫生安全带来了极…

操作系统基本原理

一、基本概念 二、进程管理 三、存储管理 四、文件管理 五、设备管理 六、微内核操作系统 操作系统的概念&#xff08;定义) 操作系统(Operating System,OS)是指控制和管理整个计算机系统的硬件和软件资源&#xff0c;并合理地组织调度计算机的工作和资源的分&#xff0c;以…

光耦合器的特性和应用概述

光耦合器又称光电耦合器&#xff0c;是现代电子学中必不可少的元件&#xff0c;确保隔离电路之间安全有效的信号传输。本文探讨了光耦合器的特性及其多样化应用&#xff0c;强调了它们在各种电子系统中的关键作用。 什么是光耦合器&#xff1f; 光耦合器是一种设计用于利用光传…

第十六节:带你梳理Vue2: 生命周期与钩子函数

前沿: 通过前面几节的学习&#xff0c;我们已经对vue有了初步的了解&#xff0c;大致了解了vue可以帮我们干什么&#xff0c; 那么接下来我们就来看看vue的生命周期和它常用的钩子函数, 1. 理解生命周期的含义 生命周期&#xff1a;就是一个组件从实例化创建并添加到DOM树开…

【全开源】招聘求职小程序系统源码(ThinkPHP+原生微信小程序)

基于ThinkPHP和原生微信小程序开发的招聘平台系统&#xff0c;包含微信小程序求职者端、微信小程序企业招聘端、PC企业招聘端、PC管理平台端 构建高效人才交流平台 一、引言&#xff1a;招聘求职市场的数字化趋势 在数字化时代&#xff0c;招聘求职市场也迎来了巨大的变革。…

Edge浏览器:重新定义现代网页浏览

引言 - Edge的起源与重生 Edge浏览器&#xff0c;作为Microsoft Windows标志性的互联网窗口&#xff0c;源起于1995年的Internet Explorer。在网络发展的浪潮中&#xff0c;IE曾是无可争议的霸主&#xff0c;但随着技术革新与用户需求的演变&#xff0c;它面临的竞争日益激烈。…

Linux学习笔记:线程

Linux中的线程 什么是线程线程的使用原生线程库创建线程线程的id线程退出等待线程join分离线程取消一个线程线程的局部存储在c程序中使用线程使用c自己封装一个简易的线程库 线程互斥(多线程)导致共享数据出错的原因互斥锁关键函数pthread_mutex_t :创建一个锁pthread_mutex_in…

租赁系统|北京租赁系统|租赁软件开发流程

在数字化时代的浪潮下&#xff0c;小程序成为了各行各业争相探索的新领域。租赁行业亦不例外&#xff0c;租赁小程序的开发不仅提升了用户体验&#xff0c;更为商家带来了更多商业机会。本文将详细解析租赁小程序的开发流程&#xff0c;为有志于进军小程序领域的租赁行业从业者…

Hadoop+Spark大数据技术 实验8 Spark SQL结构化

9.2 创建DataFrame对象的方式 val dfUsers spark.read.load("/usr/local/spark/examples/src/main/resources/users.parquet") dfUsers: org.apache.spark.sql.DataFrame [name: string, favorite_color: string ... 1 more field] dfUsers.show() -----------…