【WPF】桌面程序开发之xaml页面绑定数据模型详解

使用Visual Studio开发工具,我们可以编写在Windows系统上运行的桌面应用程序。其中,WPF(Windows Presentation Foundation)项目是一种常见的选择。然而,对于初学者来说,WPF项目中xaml页面的布局设计可能是一个难点。下面,将简要介绍WPF项目中xaml页面的数据绑定基础知识。

文章目录

  • 页面布局
  • 控件属性
    • 更新内容
    • 显示隐藏
    • 更新样式
    • 其它属性
  • 绑定数据模型
    • 数据绑定
    • 结构体对象
    • 绑定对象属性
      • 内容显示
      • 未初始化显示
    • 设置对象属性
      • 更新处理
    • 绑定其它属性
      • 数据列表
  • 绑定数据调试

如果还不知道怎么创建WPF项目, 可以看以下文章,回顾一下再来

  • Windows系统桌面应用程序编程开发新手入门-打造自己的小工具
  • 桌面程序开发之xaml页面基础布局方式详解
  • 桌面程序开发之xaml页面主题和样式详解

页面布局

带后缀名xaml的是页面的布局文件,打开内容大致如下

<Window x:Class="WpfApp4.MainWindow"...xmlns:local="clr-namespace:WpfApp4"mc:Ignorable="d"Title="MainWindow" Height="450" Width="800"><Window.Resources><!-- 这里设置统一控件的样式和加载资源 --></Window.Resources>    <Grid><!-- 这里开始添加控件布局 --><StackPanel><TextBlock x:Name="textBlock1" Text="Hello World" FontSize="24" /><Button Click="Button_Click">点击按钮</Button></StackPanel></Grid>
</Window>

其中xmlns:local="clr-namespace:WpfApp4"是指定可用控件local的命令空间

设计器下显示, 如下图
在这里插入图片描述

控件属性

在绑定控件的属性数据之前,需要了解如何改变控件的一些属性,

这些属性除了绑定,都是可通过写代码来改变的,以更新控件的显示内容和状态

更新内容

例如更新控件的文本内容,用一个文本控件TextBlock

这个控件里有个显示内容的属性Text,在布局中内容修改如下

<TextBlock x:Name="textBlock1" Text="zs1028" FontSize="24" />

通过点击按钮控件来执行,在按钮事件Button_Click中的代码添加内容,代码如下

textBlock1.Text = "Hello, zs1028";

点击运行后,效果如下图
在这里插入图片描述

显示隐藏

所有会显示的控件都有个可隐藏的属性,通过代码设置其属性Visibility来改变即可,

通常用如下三个值:

  • Visible 显示
  • Hidden 隐藏,仍占用空间
  • Collapsed 隐藏,不占空间

在布局中添加一个图像控件,内容如下

<Image x:Name="image1" Source="/zs1028的头像.jpg" Width="130" Stretch="Uniform" />

看设计器是否显示图片,如果填入的图片地址不对,就不会显示,
图片文件应放在项目根目录下资源文件夹Resources

要想把一个图片控件隐藏起来,

就在该控件标签里添加一个属性Visibility,内容如下

<Image x:Name="image1" ... Visibility="Hidden" />

看设计器显示结果,就会发现图片不显示

或者,通过写代码,点击按钮隐藏该控件,代码如下

image1.Visibility = Visibility.Hidden;

上面的操作代码来看,虽然是把隐藏了,但是会占空间

点击运行后,效果如下图
在这里插入图片描述

如果要改变图片显示,修改代码如下

image1.Source = new BitmapImage(new Uri("pack://application:,,,/Resources/520.jpg"));

文件地址对象类Uri传入的参数如果是项目根目录下需要带上前缀pack://application:,,,/

点击运行后,效果如下图
在这里插入图片描述

从上面看出,一些控件的属性数据类型不全是字符串String类型,在代码中改变控件属性时要注意区别处理,

更新样式

例如,想要改变一个容器控件的背景,

就在布局中给其属性Background设置为深蓝色背景,内容如下

 <StackPanel x:Name="stackPanel1" Background="DarkBlue" />...
</StackPanel>

其属性值是颜色名称,也可以改成 #1028CA 之类的十六进制颜色

可以通过写代码来改变,C#代码如下

stackPanel1.Background = Brushes.DarkBlue;

该属性的值在代码中不是字符串类型,而是在Brushes中预定义的SolidColorBrush对象,它继承与Brush

如果在代码中要使用字符串类型的颜色值,需要转换处理,C#代码如下

string bgColorHtml = "#1028CA";
stackPanel1.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString(bgColorHtml));

点击运行后,效果如下图
在这里插入图片描述

其它属性

控件还有一些其它属性,用法同上面类似,在这里就不多讲,用到时候,自己研究。

慢慢就会发现,通过一行一行代码来改很多控件的属性,是很低效的,

想要提升工作效率,试试用控件的绑定数据

绑定数据模型

前端请求后台服务返回的数据,叫作数据模型,按实际需求来处理展示,

把这个数据处理为对象,与在后端写得数据库表存取的一条条数据都对应,

学过web前端页面数据绑定的同学应该很熟悉,

数据绑定

绑定的数据,就是当修改控件属性绑定的数据,控件会自动更新显示内容和状态,

与之前通过代码改变控件属性相比,这处理操作起来更容易一些

结构体对象

页面上有很多控件,控件的属性都能用一个结构体对象的属性来绑定,

先写一个自定义结构体对象类来当作数据模型,代码如下

public class DataModel
{public string key1 { get; set; }public DataModel(){}
}

写得不多的话,就写在页面的代码里,这样方便点

页面代码里有一个构造方法MainWindow()

在这里面写,将DataContext初始化,代码如下,

public partial class MainWindow : Window
{        public MainWindow(){InitializeComponent();// 用自定义对象的属性数据this.DataContext = new DataModel();}
}

这窗体对象有个属性DataContext,是页面的数据上下文,

为其赋值为DataModel类的实例,使用控件就可以绑定实例的属性

绑定对象属性

实例对象类DataModel中有定义了一个属性key1,可以从页面数据上下文中获取,

在页面布局中,绑定这个属性,改后内容如下

<TextBlock Text="{Binding key1}" FontSize="14" Foreground="Blue" />

其文本控件的属性值Text使用花括号将内容包括起来,
其开头写了Binding,表示绑定一个变量,指向属性名key1

在设计器上,这个文本控件默认是不显示内容的,

内容显示

要想显示内容,需要在绑定的属性Text中添加一段FallbackValue,改后内容如下

<TextBlock Text="{Binding key1, FallbackValue='zs1028'}" ... />

点击运行后,会发现文件控件显示了内容,如下图
在这里插入图片描述

这是因为变量属性key1没有初始化赋值,

未初始化显示

要在绑定的属性未初始化时提示的话,可以再添加一段TargetNullValue,改后内容如下

<TextBlock Text="{Binding key1, FallbackValue='zs1028', TargetNullValue='未初始化赋值'}" .../>

点击运行后,会发现文件控件显示未初始化赋值内容,

设置对象属性

接下来,通过按钮点击给其key1赋值,代码如下

DataModel data = (DataModel)this.DataContext;
data.key1 = "hello zs1028";

那页面就会自动更新相关的控件显示状态,对吗,

点击运行后发现,和预期的不一致,点击按钮后文本控件没有自动更新,

更新处理

问题出在这里,自定义对象DataModel类没有继承INotifyPropertyChanged接口,

继承这个接口,实现通知更新的处理,

修改后,代码如下

public class DataModel : INotifyPropertyChanged
{public event PropertyChangedEventHandler PropertyChanged;protected virtual void OnPropertyChanged(string propertyName){PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));}public string key1 {get { return _key1; }set{_key1 = value;OnPropertyChanged(nameof(key1));}}private string _key1 { get; set; }public DataModel(){}
}

当运行时,修改其中的属性key1后,它会调用一个方法OnPropertyChanged()通知属性改变,

那页面上就会自动更新相关的控件显示状态,

点击运行后,效果如下图
在这里插入图片描述

绑定其它属性

除了绑定数据类型有字符串的属性,还有其它属性,

用法参考之前代码设置控件属性一样,中间需要转换,

在这里就不多讲,用到时候,自己研究。

数据列表

如果用到展示列表之类的控件,这些列表控件有ItemsControlListBox

这些列表控件使用的数据属性是ItemsSource,是一个列表或数组,数据集合类型,

想到列表List类,用它来代替使用就会有问题,因为这个类没有继承类似更新项属性的接口和实现

这里使用数据集合ObservableCollection对象,作为列表,

这个对象类继承了Collection, INotifyCollectionChanged, INotifyPropertyChanged,所以在修改数据项时会自动更新,

使用前需要添加来自System.Collections.ObjectModel的引用,

在之前的自定义对象中添加一个属性keys1,为数据列表, 代码如下

public class DataModel : INotifyPropertyChanged
{/.../public ObservableCollection<KeyValuePair<string, string>> keys1{get { return _keys1; }set{_keys1 = value;OnPropertyChanged(nameof(keys1));}}private ObservableCollection<KeyValuePair<string, string>> _keys1 { set; get; }public DataModel(){}
}

在页面布局中,应改成这样,

设置列表控件的属性ItemsSource指向数据集合变量,内容如下

<ItemsControl  ItemsSource="{Binding}"><ItemsControl.ItemTemplate><DataTemplate><DockPanel><Label DockPanel.Dock="Left" FontWeight="Bold" Content="{Binding YourName}" /><TextBlock Padding="0,5" Text="{Binding YourCode}" /></DockPanel></DataTemplate></ItemsControl.ItemTemplate>
</ItemsControl>

在标签DataTemplate对内填入的内容是列表项的布局,其绑定的数据上下文是指向该列表控件本身的当时列表项数据ListItem对象

列表项数据ListItem是一个自定义对象类,写出来,代码如下

public class ListItem
{public string YourName { get; set; }public string YourCode { get; set; }public ListItem(string name, string code){YourName = name;YourCode = code;}
}

现在点击运行是看不到列表的,还没有列表数据,

直接在自定义对象的构造方法中添加列表数据,代码如下

public DataModel()
{_keys1 = new ObservableCollection<ListItem>{new ListItem("你的名字","你的代号"),new ListItem("zs1028","1028"),};
}

点击运行后,效果如下图
在这里插入图片描述

在点击按钮事件中,实现添加新项,代码如下

DataModel data = (DataModel)this.DataContext;
//...
data.keys1.Add(new ListItem(DateTime.Now.ToString("孙悟空 HHmmss"), data.keys1.Count.ToString("D4")));

点击运行后,效果如下图
在这里插入图片描述

绑定数据调试

点击运行时,程序窗口标题栏上会出现一个开发者工具悬浮窗,

如下图,标为橙色的图标按钮就是调试查看绑定情况的,
在这里插入图片描述

上面都是基本上能用到的,对需要学习的新手来说很有帮助,就讲到这里,
先溜了

更多绑定数据详情,参考微软官方的文档

将 WPF 控件绑定到 .NET Framework 应用程序中的数据

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

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

相关文章

java项目之在线考试与学习交流网页平台源码(springboot)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的在线考试与学习交流网页平台。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 基于JAVA语言…

C++数据结构-树的概念及分类介绍(基础篇)

1.什么是树 树是数据结构中的一种&#xff0c;其属于非线性数据结构结构的一种&#xff0c;我们前文所提到的数据结构多数都是线性的&#xff0c;这也是较为简单的数据结构&#xff0c;而接下来的树与图均属于非线性数据结构&#xff0c;也是概念极多的一类。 树是由结点或顶…

OSS对象资源管理

1、登录aliyun 1.1、什么是OSS&#xff1f;有什么用&#xff1f; OSS 是“Object Storage Service”的缩写&#xff0c;中文常称为“对象存储服务”。OSS 是一种互联网云存储服务&#xff0c;主要用于海量数据的存储与管理。 相较于nginx&#xff0c;OSS更灵活&#xff0c;不…

yolov8 pose姿态关键点识别动物姿态识别

导言 介绍了 Tiger数据集&#xff0c;这是一个专为姿势估计任务设计的多功能数据集。该数据集由来自YouTube 视频的 263 张图片组成&#xff0c;其中 210 张用于训练&#xff0c;53 张用于验证。它是测试姿势估计算法和排除故障的绝佳资源。 尽管虎姿态数据集只有 210 张图像…

AT89C51 Intel HEX手工结构分析 反汇编工具

在不查询格式情况下分析确定 Intel HEX 格式 Hex文件内容 :0300000002090BE7 :0C090B00787FE4F6D8FD7581080208F63C :01091700419E :1008F60078087C007D007BFF7A0979177E007F01EE :050906001208D080FE84 :10080000E709F608DFFA8046E709F208DFFA803EDA :1008100088828C83E709F0…

9.15 BFS中等 133 Clone Graph review 138 随机链表的复制

133 Clone Graph //错误代码class Solution { public:Node* cloneGraph(Node* node) {//邻接表、BFS---》类似于二叉树的层次遍历if(!node || !node->val) return node;//构造队列queue<Node*> prev;prev.push(node);//构造新的图结点列表vector<Node*> adjList…

用Spring Boot搭建的读书笔记分享平台

第1章 绪论 1.1课题背景 计算机的普及和互联网时代的到来使信息的发布和传播更加方便快捷。用户可以通过计算机上的浏览器访问多个应用系统&#xff0c;从中获取一些可以满足用户需求的管理系统。网站系统有时更像是一个大型“展示平台”&#xff0c;用户可以选择所需的信息进入…

framework解决权限不足无法安装apk

文件浏览器中安装apk权限不足 源码位置 base/services/core/java/com/android/server/uri/UriGrantsManagerService.java

java数据结构----图

图的存储结构: 代码实现 public class Graph {// 标记顶点数目private int V;// 标记边数目private int E;// 邻接表private Queue<Integer>[] adj;public Graph(int v) {V v;this.E 0;this.adj new Queue[v];for (int i 0; i < adj.length; i) {adj[i] new Queu…

初中(7-9年级)数学-人教版视频全套

文章目录 一、紧贴教材&#xff0c;内容全面二、生动讲解&#xff0c;易于理解三、灵活学习&#xff0c;随时随地四、获取方式 初中数学人教版视频全套&#xff0c;专为使用人教版教材的学生打造。通过高清视频、生动讲解和精准辅导&#xff0c;帮助学生轻松掌握数学知识点&…

系统架构设计师教程 第5章 5.2 需求工程 笔记

5.2 需求工程 ★★★★★ 软件需求是指用户对系统在功能、行为、性能、设计约束等方面的期望。 软件需求包括3个不同的层次&#xff1a;业务需求、用户需求和功能需求(也包括非功能需求)。 (1)业务需求 (business requirement) 反映了组织机构或客户对系统、产品高层次的目标…

电信网络携手大模型:AI赋能网络运维的新范式

当电信网络用上大模型&#xff0c;会带来怎样的体验&#xff1f; 过去&#xff0c;网络出现问题时&#xff0c;运维人员需要依赖经验反复排查&#xff0c;找到“病根”后再“对症下药”。但在大模型的加持下&#xff0c;问题的解决方式发生了颠覆性的改变。 如今&#xff0c;…

java项目之基于工程教育认证的计算机课程管理平台(源码+论文)

项目简介 基于工程教育认证的计算机课程管理平台的主要管理员可以管理教师&#xff0c;可以对教师信息修改删除以及查询操作&#xff1b;可以对通知公告信息进行添加&#xff0c;修改&#xff0c;删除以及查询操作&#xff1b;可以对学生信息进行添加&#xff0c;修改&#xf…

算法刷题:300. 最长递增子序列、674. 最长连续递增序列、718. 最长重复子数组、1143. 最长公共子序列

300. 最长递增子序列 1.dp定义&#xff1a;dp[i]表示i之前包括i的以nums[i]结尾的最长递增子序列的长度 2.递推公式&#xff1a;if (nums[i] > nums[j]) dp[i] max(dp[i], dp[j] 1); 注意这里不是要dp[i] 与 dp[j] 1进行比较&#xff0c;而是我们要取dp[j] 1的最大值…

Linux操作系统入门(一)

Linux操作系统是开源的类Unix操作系统内核&#xff0c;由林纳斯托瓦兹在1991年创建。 Linux操作系统以其强大的性能、稳定性和开放性&#xff0c;赢得了全球用户的广泛认可&#xff0c;从服务器到个人电脑&#xff0c;从超级计算机到嵌入式设备&#xff0c;都有它的身影。作为…

进阶岛 任务3: LMDeploy 量化部署进阶实践

进阶岛 任务3&#xff1a; LMDeploy 量化部署进阶实践 任务&#xff1a;https://github.com/InternLM/Tutorial/blob/camp3/docs/L2/LMDeploy/task.md 使用结合W4A16量化与kv cache量化的internlm2_5-1_8b-chat模型封装本地API并与大模型进行一次对话&#xff0c;作业截图需包…

URP 线性空间 ui资源制作规范

前言&#xff1a; 关于颜色空间的介绍&#xff0c;可参阅 unity 文档 Color space URP实现了基于物理的渲染&#xff0c;为了保证光照计算的准确&#xff0c;需要使用线性空间&#xff1b; 使用线性空间会带来一个问题&#xff0c;ui资源在unity中进行透明度混合时&#xff…

Python版《天天酷跑+源码》,详细讲解,手把手教学-python游戏开发

天天酷跑游戏 游戏效果: 游戏主要是躲避障碍物&#xff0c;这里也添加了金币&#xff0c;增加一点积分的娱乐性&#xff0c;人物设置是三条命&#xff0c;障碍物有6种&#xff0c;包括金币&#xff0c;障碍物随机生成&#xff0c;碰到障碍物掉一滴血&#xff0c;没血了结束游戏…

STL之stack

stack容器 - 先进后出” - stack是堆栈容器&#xff0c;是一种的容器。 - 头文件&#xff1a;#include <stack> stack的push()与pop()方法 stack.push(elem);//往栈头添加元素 stack.pop();//从栈头移除第一个元素 stack<int> stkInt; stkInt.push(1);stkInt…

react hooks--概述

前言 ◼ Hook 是 React 16.8 的新增特性&#xff0c;它可以让我们在不编写class的情况下使用state以及其他的React特性&#xff08;比如生命周期&#xff09;。 ◼ 我们先来思考一下class组件相对于函数式组件有什么优势&#xff1f;比较常见的是下面的优势&#xff1a; ◼ …