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

news2024/11/15 19:57:17

使用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.coloradmin.cn/o/2138766.html

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

相关文章

unity3d入门教程七

unity3d入门教程七 17.1物理系统17.2静态刚体17.3刚体的碰撞17.4刚体的反弹18.1运动学刚体18.2碰撞检测18.3碰撞事件回调18.4目标的识别18.5碰撞的规避 17.1物理系统 在物理系统中的物体具有质量和速度的是刚体 不用写代码就会自由落体运动了 17.2静态刚体 给 ‘地面’ 添…

conda安装qgis(亲测没问题)

conda安装qgis&#xff08;亲测没问题&#xff0c;目前测试win10&#xff0c;linux其实也是可以的&#xff09; 目录 1.前提 2.准备条件 3.实战 4.扩展 1.前提 意外发现conda可以安装qgis&#xff0c;即使不是完全版&#xff0c;但是矢量空间分析都可以用&#xff0c;那么…

影刀RPA实战:网页爬虫之CSDN博文作品数据

今天我们使用影刀来采集网页数据&#xff0c;影刀RPA是一款功能强大的自动化办公软件&#xff0c;它可以模拟人工的各种操作&#xff0c;帮助企业自动处理大量重复性、有逻辑规则的工作。影刀RPA在网页数据采集方面表现出色&#xff0c;能够实现对任何桌面软件、Web程序的自动化…

危机中的机遇:客户服务在品牌危机管理中的角色与价值

在瞬息万变的商业环境中&#xff0c;品牌危机如同暗流涌动的漩涡&#xff0c;随时可能将企业卷入深渊。然而&#xff0c;正如古语所云&#xff1a;“祸兮福之所倚”&#xff0c;危机之中往往也蕴藏着转机与机遇。在这一过程中&#xff0c;客户服务作为企业与消费者之间的桥梁&a…

物品识别——基于python语言

目录 1.物品识别 2.模型介绍 3.文件框架 4.代码示例 4.1 camera.py 4.2 interaction.py 4.3 object_detection.py 4.4 main.py 4.5 运行结果 5.总结 1.物品识别 该项目使用Python&#xff0c;OpenCV进行图像捕捉&#xff0c;进行物品识别。我们将使用YOLO&#xff08…

Dating App约会软件都有哪些商业化策略

在设计一个成功的Dating App时&#xff0c;吸引并留住用户&#xff08;特别是女用户&#xff09;和实现商业化是两个核心任务。比如探探、陌陌等&#xff0c;以下是可行的产品流程思路&#xff0c;以及商业化的功能设计策略&#xff0c;借鉴了成熟的约会平台的经验。 吸引并留住…

2000-2021年3月海关数据库

2000-2021年3月海关数据库 1、时间&#xff1a;2000-2021年3月 2、指标&#xff1a;2000-2015数据变量包括&#xff1a;年份、截止日期、进出口分类代码、进出口分类名称、HS商品编码、HS商品名称、金额_美元、数量、价格、经营单位代码、经营单位名称、经营单位地址、电话、…

AI论文写作测评!类似茅茅虫论文写作助手网站

在当前的学术研究和写作环境中&#xff0c;AI论文写作助手成为了许多学者和学生的重要工具。其中&#xff0c;千笔-AIPassPaper和茅茅虫论文写作助手是两款备受关注的平台。本文将对这两款工具进行详细测评&#xff0c;并推荐适合不同需求的用户使用。 千笔-AIPassPaper AI论文…

linux安全软件Hydra使用教程

Hydra 是一个强大的网络登录工具&#xff0c;常用于渗透测试&#xff0c;支持对多种服务和协议&#xff08;如 SSH、FTP、HTTP 等&#xff09;进行暴力crack攻击。它可以通过字典攻击来测试用户名和密码的有效性。以下是关于如何使用 Hydra 的基本步骤和示例&#xff1a; 1. 安…

【mechine learning-九-梯度下降】

梯度下降 更加通用的梯度下降算法算法步骤 上一节讲过&#xff0c;随机的寻找w和b使损失最小不是一种合适的方法&#xff0c;梯度下降算法就是解决解决这个问题的&#xff0c;它不仅可以用于线性回归&#xff0c;还可以用于神经网络等深度学习算法&#xff0c;是目前的通用性算…

【QT】定时器使用

文章目录 关于 Qt 定时器使用的注意细节总结实例-检查工具使用周期时间是否合理UI设计头文件 remind.h源文件 remind.cpp实现效果 关于 Qt 定时器使用的注意细节总结 一、创建与初始化 使用 QTimer 类来创建定时器。可以在构造函数中指定父对象&#xff0c;确保定时器在正确的…

跨境电商代购新纪元:一键解锁全球好物,系统流程全揭秘

添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 在全球化日益加深的今天&#xff0c;跨境电商代购成为了连接消费者与世界各地优质商品的桥梁。本文将在CSDN平台上&#xff0c;深入剖析跨境电商代购系统的功能流程&#xff0c;带您一窥其背后的技术奥秘与…

vue3+ant design vue实现可编辑表格弹出气泡弹出窗~

1、这里主要是介绍下::v-deep伪元素的作用。用于穿透组件作用域&#xff0c;以便在组件内部修改样式。用来覆盖Ant Design Vue组件库中的样式 <a-table:dataSource"dataList":columns"columns":scroll"{ x: 100% }":pagination"false&q…

架构师备考的一些思考(四)

前言 对于数学&#xff0c;我们之前学的是对的&#xff0c;但不是真的&#xff0c;所以我们没有数学思维。 对于计算机&#xff0c;我们学校教的是对的&#xff0c;但不是真的&#xff0c;所以仅仅从学校学习知识的应届毕业生&#xff0c;不论985,211&#xff0c;本科&#xff…

优化深度学习模型训练过程:提升PASCAL VOC 2012数据集上Deeplabv3+模型训练效率的策略

创作不易&#xff0c;您的打赏、关注、点赞、收藏和转发是我坚持下去的动力&#xff01; 优化说明&#xff1a; 避免重复下载和解压数据集&#xff1a;将downloadTrue改为downloadFalse&#xff0c;防止每次运行代码都重新下载和解压数据集&#xff0c;从而节省时间。 使用pin…

8. Transforms的使用(三)-- Resize

Transforms的使用(三) 1. 为什么要使用Resize 在模型的训练过程中往往需要图片数据的维度相同,才能适应深度学习模型中的相关神经网络结构,这时候就需要使用Resize保证所有的图片保持相同的尺寸2. 使用Resize调整图片的尺寸 在pytorch2.3的版本上,Resize()支持对Tensor类…

k8s Service 服务

文章目录 一、为什么需要 Service二、Kubernetes 中的服务发现与负载均衡 -- Service三、用例解读1、Service 语法2、创建和查看 Service 四、Headless Service五、集群内访问 Service六、向集群外暴露 Service七、操作示例1、获取集群状态信息2、创建 Service、Deployment3、创…

分贝转换 1 mVpp = 9.03dBmV

分贝转换 1 mVpp 9.03dBmV 函数发生器调节如下参数在频谱仪器上能看到9.03dBmv的电压值函数发生器产生 30mVpp 频谱仪会显示多少dBmV 函数发生器调节如下参数 输出频率&#xff1a;10 MHz 波形类型&#xff1a;正弦波 阻抗&#xff1a;50 Ω 幅度&#xff1a;1 mVpp …

【笔记】CCF直播:《如何在国际会议上有效交流》(2024-9-15)

目录 一、提问的勇气二、提问什么三、其他主题的报告为什么听四、会议前怎么读大量论文&#xff1f;五、workshop为什么参加&#xff1f;Poster环节&#xff1f;六、提问环节七、其他 今天听了《如何在国际会议上有效交流》的直播讲座&#xff0c;记录一些笔记。 一、提问的勇…

Gitlab及Git使用说明

目 录 1 Gitlab及Git介绍说明 5 1.1 什么是 Gitlab 5 1.2 什么是Git 5 1.3 Git 家族成员 5 1.4 Gitlab版本 5 1.5 Gitlab 优势 5 1.6 Gitlab 主要服务构成 6 1.7 Gitlab 简单工作流程 6 1.8 Gitlab用户角色 6 2 Gitlab安装与使用 7 2.1 Gitlab安装说明&#xff08;管理员&#…