WPF入门第二篇 MVVM与Binding

news2024/11/25 20:25:35

MVVM与Binding

MVVM,即Model-View-ViewModel的首字母缩写,在这种开发模式下常用binding来对View和ViewModel进行绑定。
添加三个文件夹,分别命名为Models、Views、ViewModels。
在这里插入图片描述

在Model文件夹中,添加Student类,并将Student.cs代码替换为如下代码:

//Student.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WpfTest2.Models
{
    public class Student
    {
        //以下两个都是属性,不是字段;因为教程的不规范没有首字母大写
        public string id { get; set; }
        public string name { get; set; }
    }
}

在Models文件夹中,添加Score类,并将Score.cs代码替换为如下代码:

//Score.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WpfTest2.Models
{
    public class Score
    {
        public string stuId { get; set; }
        public string subject { get; set; }
        public int score { get; set; }
    }
}

在ViewModels文件夹中添加CardViewModel类,并将代码替换为如下代码:

//CardViewModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WpfTest2.Models; //注意这里

namespace WpfTest2.ViewModels
{
    public class CardViewModel
    {
        public Student student { get; set; }
        public Score score { get; set; }
    }
}

从上面的步骤可以看出,我们有了两个Model,一个ViewModel。实际开发中,Model一般是数据库表映射的实体,而ViewModel是我们自定义的与一个View完全绑定的数据模型。下面我们在Views文件夹中,添加一个用户控件,命名为Card。并将Card.xaml代码替换为:

<!--Card.xaml-->
<UserControl x:Class="WpfTest2.Views.Card"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WpfTest2.Views"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
  <UserControl.Resources>
    <Style TargetType="TextBlock">
      <Setter Property="FontSize" Value="20"></Setter>
      <Setter Property="Margin" Value="10"></Setter>
      <Setter Property="Foreground" Value="White"></Setter>
      <Setter Property="Width" Value="100"></Setter>
      <Setter Property="Height" Value="35"></Setter>
    </Style>
    <Style TargetType="StackPanel" x:Key="sp-h">
      <Setter Property="Background" Value="Black"></Setter>
      <Setter Property="Margin" Value="5"></Setter>
    </Style>
  </UserControl.Resources>
  <Grid Margin="10">
    <Grid.RowDefinitions>
      <RowDefinition Height="50"></RowDefinition>
      <RowDefinition></RowDefinition>
    </Grid.RowDefinitions>
    <Border Grid.RowSpan="2" BorderThickness="0" Background="Black" CornerRadius="20">
    </Border>
    <StackPanel Orientation="Horizontal" Grid.Row="0" Style="{StaticResource sp-h}" Margin="10,5,10,5">
      <TextBlock Text="{Binding student.name}"></TextBlock>
    </StackPanel>
    <StackPanel Orientation="Vertical" Grid.Row="1" Margin="5,10,5,10">
      <StackPanel Orientation="Horizontal" Style="{StaticResource sp-h}">
        <TextBlock Text="id:"></TextBlock>
        <TextBlock Text="{Binding score.stuId}"></TextBlock>
      </StackPanel>
      <StackPanel Orientation="Horizontal" Style="{StaticResource sp-h}">
        <TextBlock Text="subject:"></TextBlock>
        <TextBlock Text="{Binding score.subject}"></TextBlock>
      </StackPanel>
      <StackPanel Orientation="Horizontal" Style="{StaticResource sp-h}">
        <TextBlock Text="score:"></TextBlock>
        <TextBlock Text="{Binding score.score}"></TextBlock>
      </StackPanel>
    </StackPanel>
  </Grid>
</UserControl>

将Card.xaml.cs代码替换为以下代码:

//Card.xaml.cs
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;
using WpfTest2.ViewModels; //注意这里

namespace WpfTest2.Views
{
    /// <summary>
    /// Card.xaml 的交互逻辑
    /// </summary>
    public partial class Card : UserControl
    {
        public Card()
        {
            InitializeComponent();
        }
        
        //这里是构造函数的重载,有参数的构造函数需要执行无参构造器中的代码,为了省去重复代码的编写,这里就继承了。
        public Card(CardViewModel vm) : this()
        {
            //DataContext属性是绑定的默认源。它允许指定一个绑定的基。
            //详细的在这里:https://blog.csdn.net/seanbei/article/details/53207620
            this.DataContext = vm;
        }
    }
}

此时,我们的解决方案视图如下:
在这里插入图片描述

下面我们将在MainWindow中使用我们的Card。
打开MainWindow.xaml,将代码替换为:

<!--MainWindow.xaml-->
<Window x:Class="WpfTest2.MainWindow"
        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:WpfTest2"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
  <Grid>
    <WrapPanel Name="wpCardList">
    </WrapPanel>
  </Grid>
</Window>

WrapPanel用法:https://blog.csdn.net/seanbei/article/details/52893767
打开MainWindow.xaml.cs,将代码替换为:

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 WpfTest2
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            Models.Student stu = new Models.Student() { id = "111", name = "吴凡" };
            Models.Score sc = new Models.Score() { stuId = "111", subject = "语文", score = 100 };
            ViewModels.CardViewModel cardVm = new ViewModels.CardViewModel() { student = stu, score = sc };
            Views.Card card = new Views.Card(cardVm);
            wpCardList.Children.Add(card);

            Models.Score sc1 = new Models.Score() { stuId = "111", subject = "数学", score = 99 };
            ViewModels.CardViewModel cardVm1 = new ViewModels.CardViewModel() { student = stu, score = sc1 };
            Views.Card card1 = new Views.Card(cardVm1);
            wpCardList.Children.Add(card1);
        }
    }
}

运行效果:
在这里插入图片描述

分析以上代码,不难发现,通过MVVM的开发模式,使用数据库表映射实体作为Models,使用UserControl作为Views,使用自定义类作为ViewModel,可以让代码整体结构非常清晰,而且通过UserControl的动态创建、删除等操作,可以很容易的实现子页面的跳转、复杂的自定义列表等操作

关于Binding的使用,在上面的代码中也有体现。对于用户控件Card,首先在后台代码中设置this.DataContext = vm,然后在xaml页面中使用{Binding 属性值}进行数据绑定。这其实是简写方式,写全后为{Binding Path=属性值}。除了使用这种方法绑定后台设置的DataContext的值外,还可以通过{Binding ElementName=name Path=prop}来绑定页面内的其他控件的指定属性值。如:

<TextBlock Text={Binding ElementName="btn1" Path="Content"}></TextBlock>

比如,使MainWindow的title显示为wpCardList的Children的数量,则可以将MainWindow.xaml替换为如下代码:

<Window x:Class="WpfTest2.MainWindow"
        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:WpfTest2"
        mc:Ignorable="d"
        Title="{Binding ElementName=wpCardList, Path=Children.Count}" Height="800" Width="1000">//这里是新增的
  <Grid>
    <WrapPanel Name="wpCardList">
    </WrapPanel>
  </Grid>
</Window>

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

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

相关文章

Java学到什么程度可以找工作?这10点赶紧自查!

最近收到了不少私信&#xff0c;询问Java学到什么程度可以找工作。 我也去问了几个同组大佬的想法&#xff0c;总结了10点&#xff0c;大家可以对照自查一下&#xff0c;看看你都做到了吗&#xff1f; 基本技能自查 1、Java SE基础 推荐学习Java8&#xff0c;这依旧是个有代表…

【2023最新】腾讯云注册域名及服务器使用宝塔绑定域名教程

1 在腾讯云注册域名 在官网&#xff1a;https://buy.cloud.tencent.com/domain&#xff0c;注册想要的域名&#xff0c;需要认证信息模板 注册好以后&#xff0c;在右上角输入框&#xff0c;输入域名&#xff0c;查找并进入到域名控制台 在域名控制台&#xff0c;添加记录&…

基础算法系列之排序算法(一)[快速排序,归并排序,二分查找]

文章目录前言快速排序关键点实现选角排序重复实现稳定性分析记忆模板归并排序关键点实现二分查找总结前言 先来一波预热&#xff0c;本次寒假将要更新的博文系列为&#xff1a;基础算法部分&#xff0c;最新前言论文研读&#xff08;不包含论文复现-耗时太长&#xff09;&…

day21【代码随想录】二叉树的层序遍历、二叉树的层序遍历|| 、二叉树的层平均值 、二叉树的锯齿形层序遍历 、二叉树的右视图 、N叉树的层序遍历

文章目录前言一、二叉树的层序遍历&#xff08;力扣102&#xff09;二、二叉树的层序遍历||&#xff08;力扣107&#xff09;三、二叉树的层平均值&#xff08;力扣637&#xff09;四、二叉树的锯齿形层序遍历&#xff08;力扣103&#xff09;五、二叉树的右视图&#xff08;力…

吃透Chisel语言.39.Chisel实战之单周期RISC-V处理器实现(一)——需求分析和初步设计

Chisel实战之单周期RISC-V处理器实现&#xff08;一&#xff09;——需求分析和初步设计 需求分析 首先明确我们要做的是什么&#xff0c;这个在标题里面已经说明了&#xff0c;我们要做的是一个单周期RISC-V处理器。 但光是个短语不足以支撑我们开展项目&#xff0c;我们需…

大数据学习:shell基础(3)

文章目录history命令参数说明任务一&#xff1a;查看历史操作记录任务二&#xff1a;查看最近10条历史命令任务三&#xff1a;查看最开始10条历史命令任务四&#xff1a;曾多少次使用vim编辑文本文件&#xff1f;任务五&#xff1a;执行历史第5条命令任务六&#xff1a;执行上一…

【深度学习】李宏毅2021/2022春深度学习课程笔记 - Recurrent Neural NetWork(RNN)

文章目录一、Slot Filling二、Recurrent Neural NetWork&#xff08;RNN&#xff09;三、Bidirectional RNN&#xff08;双向RNN&#xff09;四、Long Short Term Memory&#xff08;LSTM&#xff09;五、Learning Target六、RNN 很难 Train七、Helpful Techniques7.1 LSTM7.2 …

CSDN竞赛14期·12月11日考试

CSDN竞赛14期12月11日考试 1、题目名称&#xff1a;字符串全排列 // 请关闭中文输入法&#xff0c;用英文的字母和标点符号。 // 如果你想运行系统测试用例&#xff0c;请点击【执行代码】按钮&#xff0c;如果你想提交作答结果&#xff0c;请点击【提交】按钮&#xff0c; //…

半入耳式蓝牙耳机哪款音质好?音质好的半入耳式蓝牙耳机推荐

对于喜欢听歌的朋友来讲&#xff0c;你只佛会关注到蓝牙耳机的佩戴舒适度&#xff0c;音质清晰这种情况&#xff0c;入耳式的带有耳塞&#xff0c;往往更加佩戴有更好的密闭性&#xff0c;半入耳的不完全进入耳道&#xff0c;佩戴更加舒适&#xff0c;下面整理了几款音质不错的…

[附源码]Python计算机毕业设计非处方药的查询与推荐系统Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

Prometheus+Grafana监控一网打尽

PrometheusGrafana监控一、Prometheus介绍二、监控组件node-exportermysqld-exportercadvisorprometheus三、Grafana 展示平台docker启动配置Data sources导入Dashboard模板Linux主机监控Mysql监控Nginx监控Redis监控PostgreSQL监控Kafka监控ElasticSearch监控一、Prometheus介…

这四类项目经理一定带不好项目

项目经理就一定可以带好项目嘛&#xff1f;&#xff0c;当然不一定 失败的项目不少&#xff0c;除去一些本身就很坑的项目&#xff0c;大多项目失败&#xff0c;都和项目经理的个性有关。 也总结了2组极端特质&#xff1a; 第一&#xff0c;烂好人VS劳模型 第二&#xff0c;马…

[ vulhub漏洞复现篇 ] struts2远程代码执行漏洞s2-059(CVE-2019-0230)

&#x1f36c; 博主介绍 &#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 _PowerShell &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 &#x1f389;点赞➕评论➕收藏 养成习…

JavaEE-多线程初阶3

✏️作者&#xff1a;银河罐头 &#x1f4cb;系列专栏&#xff1a;JavaEE &#x1f332;“种一棵树最好的时间是十年前&#xff0c;其次是现在” 目录volatile关键字wait 和 notify多线程案例单例模式饿汉模式懒汉模式volatile关键字 volatile : 易变的&#xff0c;易失的 vo…

关于实体类中VO、DTO、Entity的区别

关于实体类中VO、DTO、Entity的区别 1、entity 里的每一个字段&#xff0c;与数据库相对应&#xff0c; 2、vo 里的每一个字段&#xff0c;是和你前台 html 页面相对应&#xff0c; 3、dto 这是用来转换从 entity 到 vo&#xff0c;或者从 vo 到 entity 的中间的东西 。(DTO中拥…

leetcode: 1091. 二进制矩阵中的最短路径

1091. 二进制矩阵中的最短路径 来源:力扣(LeetCode) 链接: https://leetcode.cn/problems/shortest-path-in-binary-matrix/description/ 给你一个 n x n 的二进制矩阵 grid 中,返回矩阵中最短 畅通路径 的长度。如果不存在这样的路径,返回 -1 。 二进制矩阵中的 畅通…

刚刚接触编程,纠结应该先学Python还是Java?看完心里就有数了。

准备学习编程前&#xff0c;你一定会打开电脑搜索一下“先学Python还是先学Java&#xff1f;”扑面而来的是海量回答。 如果你问一名Java程序员&#xff0c;肯定会建议你先学Java&#xff0c;因为他们认为Python像个乳臭未干的黄毛小子。但如果你问Python程序员&#xff0c;可…

MacOS Ventura 13.1 (22C65) 正式版带 OC 0.8.7 and winPE 双分区原版黑苹果镜像

12 月 14 日&#xff0c;苹果向 Mac 电脑用户推送了 macOS 13.1 更新&#xff08;内部版本号&#xff1a;22C65&#xff09;&#xff0c;本次更新距离上次发布隔了 34 天。本次更新引入了无边记应用&#xff0c;旨在让用户在空白的白板式画布上进行素描、绘画和写作&#xff0c…

[附源码]Nodejs计算机毕业设计基于Web的在线音乐网站Express(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置&#xff1a; Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分…

能力评估网站

开发工具(eclipse/idea/vscode等)&#xff1a; 数据库(sqlite/mysql/sqlserver等)&#xff1a; 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a; (1)高校学生评估系统用户页面设计 前台页面主要是为用户设计&#xff0c;经过对用户和评估系统分析&#xff0c;目前主要…