通过Demo学WPF—数据绑定(二)

准备

今天学习的Demo是Data Binding中的Linq:

image-20240131155033495

创建一个空白解决方案,然后添加现有项目,选择Linq,解决方案如下所示:

image-20240131155225236

查看这个Demo的效果:

这个Demo的效果

开始学习这个Demo

xaml部分

查看MainWindow.xaml

<Window x:Class="Linq.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:Linq"mc:Ignorable="d"Title="MainWindow" SizeToContent="WidthAndHeight" Height="600"><Window.Resources><local:Tasks x:Key="MyTodoList"/><DataTemplate x:Key="MyTaskTemplate"><Border Name="border" BorderBrush="Aqua" BorderThickness="1"Padding="5" Margin="5"><Grid><Grid.RowDefinitions><RowDefinition/><RowDefinition/><RowDefinition/></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition /><ColumnDefinition /></Grid.ColumnDefinitions><TextBlock Grid.Row="0" Grid.Column="0" Text="Task Name:"/><TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Path=TaskName}" /><TextBlock Grid.Row="1" Grid.Column="0" Text="Description:"/><TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Path=Description}"/><TextBlock Grid.Row="2" Grid.Column="0" Text="Priority:"/><TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Path=Priority}"/></Grid></Border></DataTemplate></Window.Resources><StackPanel><TextBlock Margin="10,0,0,0">Choose a Priority:</TextBlock><ListBox SelectionChanged="ListBox_SelectionChanged"SelectedIndex="0" Margin="10,0,10,0" ><ListBoxItem>1</ListBoxItem><ListBoxItem>2</ListBoxItem><ListBoxItem>3</ListBoxItem></ListBox><ListBox Width="400" Margin="10" Name="myListBox"HorizontalContentAlignment="Stretch"ItemsSource="{Binding}"ItemTemplate="{StaticResource MyTaskTemplate}"/></StackPanel>
</Window>

先来看看资源包含什么内容(省略子项):

<Window.Resources><local:Tasks x:Key="MyTodoList"/><DataTemplate x:Key="MyTaskTemplate">      </DataTemplate>
</Window.Resources>

<Window.Resources> 是 XAML 中的一个元素,它定义了一个资源字典,你可以在其中声明和存储可在整个窗口中重用的资源。

我们发现包含两个资源:一个 Tasks 对象和一个 DataTemplate。

通过上一篇文章的学习,我们明白

<local:Tasks x:Key="MyTodoList"/>

的意思就是创建了一个 Tasks 对象,并给它分配了一个键(key)MyTodoList。这样你就可以在其他地方通过这个键引用这个 Tasks 对象了。

DataTemplate又是什么呢?

image-20240131161807052

<DataTemplate x:Key="MyTaskTemplate"><Border Name="border" BorderBrush="Aqua" BorderThickness="1"Padding="5" Margin="5"><Grid><Grid.RowDefinitions><RowDefinition/><RowDefinition/><RowDefinition/></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition /><ColumnDefinition /></Grid.ColumnDefinitions><TextBlock Grid.Row="0" Grid.Column="0" Text="Task Name:"/><TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Path=TaskName}" /><TextBlock Grid.Row="1" Grid.Column="0" Text="Description:"/><TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Path=Description}"/><TextBlock Grid.Row="2" Grid.Column="0" Text="Priority:"/><TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Path=Priority}"/></Grid></Border></DataTemplate>

其中<DataTemplate x:Key="MyTaskTemplate"> 是 XAML 中的一个元素,它定义了如何将数据对象呈现为 UI 元素。
在这个例子中,DataTemplate 定义了一个模板,该模板描述了如何将数据呈现在 UI 中。这个模板被赋予了一个键(key),即 MyTaskTemplate,这样你就可以在其他地方引用这个模板了。

 <Grid><Grid.RowDefinitions><RowDefinition/><RowDefinition/><RowDefinition/></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition /><ColumnDefinition /></Grid.ColumnDefinitions><Grid>    

定义了一个3行2列的Grid布局:

image-20240131162453337

 <TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Path=TaskName}" />

Grid.Row="0"表示第1行,Grid.Column="1"表示第2列,Text="{Binding Path=TaskName}" 表示Text属性的值为绑定源的TaskName属性的值。

   <TextBlock Margin="10,0,0,0">Choose a Priority:</TextBlock><ListBox SelectionChanged="ListBox_SelectionChanged"SelectedIndex="0" Margin="10,0,10,0" ><ListBoxItem>1</ListBoxItem><ListBoxItem>2</ListBoxItem><ListBoxItem>3</ListBoxItem></ListBox>

表示以下这部分:

image-20240131163013465

<ListBox Width="400" Margin="10" Name="myListBox"HorizontalContentAlignment="Stretch"ItemsSource="{Binding}"ItemTemplate="{StaticResource MyTaskTemplate}"/>

表示以下这部分:

image-20240131163113558

image-20240131163134246

我们会发现它没有显式的写 <ListBoxItem>,而且它的ListBoxItem数量不是固定的。

它使用了ItemsSource="{Binding}"ItemsSource 是 ListBox 的一个属性,它决定了 ListBox 中显示的项的数据源。

{Binding} 是一个标记扩展,它创建一个数据绑定。在这个例子中,由于没有指定路径(Path),所以它会绑定到当前的数据上下文(DataContext)。数据上下文通常在父元素中设置,并且所有的子元素都可以访问。

ItemTemplate="{StaticResource MyTaskTemplate}"表示每个<ListBoxItem>对象将按照这个模板进行显示。

cs部分

首先定义了TaskType枚举类型:

namespace Linq
{public enum TaskType{Home,Work}
}

定义了Task类:

// // Copyright (c) Microsoft. All rights reserved.
// // Licensed under the MIT license. See LICENSE file in the project root for full license information.using System.ComponentModel;namespace Linq
{public class Task : INotifyPropertyChanged{private string _description;private string _name;private int _priority;private TaskType _type;public Task(){}public Task(string name, string description, int priority, TaskType type){_name = name;_description = description;_priority = priority;_type = type;}public string TaskName{get { return _name; }set{_name = value;OnPropertyChanged("TaskName");}}public string Description{get { return _description; }set{_description = value;OnPropertyChanged("Description");}}public int Priority{get { return _priority; }set{_priority = value;OnPropertyChanged("Priority");}}public TaskType TaskType{get { return _type; }set{_type = value;OnPropertyChanged("TaskType");}}public event PropertyChangedEventHandler PropertyChanged;public override string ToString() => _name;protected void OnPropertyChanged(string info){var handler = PropertyChanged;handler?.Invoke(this, new PropertyChangedEventArgs(info));}}
}

实现了INotifyPropertyChanged接口。

实现INotifyPropertyChanged接口的主要目的是为了提供一个通知机制,当对象的一个属性更改时,可以通知到所有绑定到该属性的元素。

INotifyPropertyChanged 接口只有一个事件 PropertyChanged。当你的类实现了这个接口,你需要在每个属性的 setter 中触发这个事件。这样,当属性的值更改时,所有绑定到这个属性的 UI 元素都会收到通知,并自动更新其显示的值。

再查看Tasks类:

// // Copyright (c) Microsoft. All rights reserved.
// // Licensed under the MIT license. See LICENSE file in the project root for full license information.using System.Collections.ObjectModel;namespace Linq
{public class Tasks : ObservableCollection<Task>{public Tasks(){Add(new Task("Groceries", "Pick up Groceries and Detergent", 2, TaskType.Home));Add(new Task("Laundry", "Do my Laundry", 2, TaskType.Home));Add(new Task("Email", "Email clients", 1, TaskType.Work));Add(new Task("Clean", "Clean my office", 3, TaskType.Work));Add(new Task("Dinner", "Get ready for family reunion", 1, TaskType.Home));Add(new Task("Proposals", "Review new budget proposals", 2, TaskType.Work));}}
}

继承自ObservableCollection<Task>类。

ObservableCollection<T> 是 .NET 框架中的一个类,它表示一个动态数据集合,当添加、删除项或者整个列表刷新时,它会提供通知。这对于绑定到 UI 元素(例如 WPF 或 UWP 应用程序中的数据绑定)非常有用,因为当集合更改时,UI 元素可以自动更新。

image-20240131164317743

再看下这个Demo中最为重要的部分:

// // Copyright (c) Microsoft. All rights reserved.
// // Licensed under the MIT license. See LICENSE file in the project root for full license information.using System.Linq;
using System.Windows;
using System.Windows.Controls;namespace Linq
{/// <summary>///     Interaction logic for MainWindow.xaml/// </summary>public partial class MainWindow : Window{private readonly Tasks tasks = new Tasks();public MainWindow(){InitializeComponent();}private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e){var pri = int.Parse(((sender as ListBox).SelectedItem as ListBoxItem).Content.ToString());DataContext = from task in taskswhere task.Priority == priselect task;     }}
}
 private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e){var pri = int.Parse(((sender as ListBox).SelectedItem as ListBoxItem).Content.ToString());DataContext = from task in taskswhere task.Priority == priselect task;     }

表示ListBox选项改变事件处理函数。

 var pri = int.Parse(((sender as ListBox).SelectedItem as ListBoxItem).Content.ToString());

获取选中项的值。

   DataContext = from task in taskswhere task.Priority == priselect task; 

中的DataContext获取或设置元素参与数据绑定时的数据上下文。

image-20240131165019921

from task in tasks
where task.Priority == pri
select task; 

使用C#中的Linq获得tasks中Priority属性等于pri的所有task对象,也可以这样写:

  DataContext = tasks.Where(x => x.Priority == pri);

效果是一样的。

过程

首先实例化了一个Tasks类如下:

image-20240131165631201

包含这些Task类。

以选择“2”为例,进行说明:

image-20240131165511996

打个断点:

image-20240131165821240

DataContext的结果如下:

image-20240131165934477

<ListBox Width="400" Margin="10" Name="myListBox"HorizontalContentAlignment="Stretch"ItemsSource="{Binding}"ItemTemplate="{StaticResource MyTaskTemplate}"/>

中的ItemsSource="{Binding}"表示ListBox的数据源就是DataContext,也就是有3个Task对象,也就是有3个ListItem,每个ListItem都按照{StaticResource MyTaskTemplate}这个模板进行显示。

结果就如上图所示。

测试

最后为了测试自己是否真的理解,可以按照自己的意图进行更改,比如我想根据工作类型进行数据的显示。

<TextBlock Grid.Row="2" Grid.Column="0" Text="TaskType:"/>
<TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Path=TaskType}"/>

修改数据模板。

<ListBox SelectionChanged="ListBox_SelectionChanged"SelectedIndex="0" Margin="10,0,10,0" ><ListBoxItem>Home</ListBoxItem><ListBoxItem>Work</ListBoxItem>
</ListBox>

修改第一个ListBox。

private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{var pri = ((sender as ListBox).SelectedItem as ListBoxItem).Content.ToString();TaskType type = new TaskType();switch (pri){case "Home":type = TaskType.Home;break;case "Work":type = TaskType.Work;break;default:break;}DataContext = tasks.Where(x => x.TaskType == type);
}

修改ListBox选项改变事件处理函数。

效果如下所示:

效果2

总结

本文主要介绍了数据绑定配合Linq的使用,希望对你有所帮助。

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

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

相关文章

【Java八股面试系列】JVM-常见参数设置

目录 堆内存相关 显式指定堆内存–Xms和-Xmx 显式新生代内存(Young Generation) 显式指定永久代/元空间的大小 垃圾收集相关 垃圾回收器 GC 日志记录 处理 OOM JDK监控和故障处理工具总结 堆内存相关 Java 虚拟机所管理的内存中最大的一块&#xff0c;Java 堆是所有线…

【嵌入式-传感器】从旋转编码器到学会看懂方波

背景&#xff1a; 在学习STM32F103的中断时&#xff0c;用到旋转编码器&#xff0c;需要通过旋转编码器输出的DO信号&#xff0c;获取旋转的刻度和方向。 前提知识&#xff1a; 使用中断需要RCC使能GPIO外设口及AFIO口、初始化GPIO、中断引脚AFIO选择配置、EXTI外部中断配置…

第62讲商品搜索动态实现以及性能优化

商品搜索后端动态获取数据 后端动态获取数据&#xff1a; /*** 商品搜索* param q* return*/GetMapping("/search")public R search(String q){List<Product> productList productService.list(new QueryWrapper<Product>().like("name", q)…

免费生成ios证书的方法(无需mac电脑)

使用hbuilderx的uniapp框架开发移动端程序很方便&#xff0c;可以很方便地开发出移动端的小程序和app。但是打包ios版本的app的时候却很麻烦&#xff0c;官方提供的教程需要使用mac电脑来生成证书&#xff0c;但是mac电脑却不便宜&#xff0c;一般的型号都差不多上万。 因此&a…

Linux部署Nacos注册中心实现远程访问UI管理界面

Nacos是阿里开放的一款中间件,也是一款服务注册中心&#xff0c;它主要提供三种功能&#xff1a;持久化节点注册&#xff0c;非持久化节点注册和配置管理。 本例通过结合Cpolar内网穿透实现远程访问Nacos 提供的UI (控制台)界面,帮助管理所有的服务和应用的配置 Cpolar内网穿…

idea: 无法创建Java Class文件(SpringBoot)已解决

第一&#xff1a;点击file-->project Sructure... 第二步&#xff1a;点击Moudules 选择自己需要创建java的文件夹&#xff08;我这里选择的是main&#xff09;右键点击Sources&#xff0c;然后点击OK即可 然后就可以创建java类了

第十四篇【传奇开心果系列】Python的OpenCV库技术点案例示例:图像特征提取与描述

传奇开心果短博文系列 系列短博文目录Python的OpenCV库技术点案例示例系列短博文目录前言一、OpenCV图像特征提取与描述介绍二、OpenCV图像特征提取与描述初步示例代码三、扩展思路介绍四、特征点筛选和匹配优化示例代码五、多尺度特征提取示例代码六、非局部特征描述子示例代码…

Quartus工程的qsf配置约束文件介绍

一、qsf文件概述 qsf&#xff1a;Quartus Setting File&#xff0c;是Quartus工程的配置文件&#xff1b; 包含一个Quartus工程的所有约束&#xff0c;包括工程的软件版本信息、FPGA器件信息、引脚约分配、引脚电平分配&#xff0c;编译约束和用于Classic TimingAnalyzer的时…

3分钟部署完成Docker Registry及可视化管理工具Docker-UI

安装docker-registry 由于镜像文件会非常占用空间&#xff0c;因此需要选择一个磁盘充裕的位置来存放镜像数据。 这里设置为&#xff1a;-v /data/registry:/var/lib/registry&#xff0c;其中/data/registry是宿主机存放数据的位置。 docker run -d -p 5000:5000 --restart…

[职场] 智能材料与结构专业的就业前景 #经验分享#学习方法

智能材料与结构专业的就业前景 智能材料与结构专业是面向国家智能制造强国战略&#xff0c;面向地方经济新旧动能转换需求&#xff0c;学习智能材料与结构的基础理论及基本知识&#xff0c;接受智能材料制备、组织分析、性能测试、智能材料系统集成技能的基本训练&#xff0c;…

【QT】day6

#include "home.h" #include "ui_home.h"Home::Home(QWidget *parent): QWidget(parent), ui(new Ui::Home) {ui->setupUi(this);// 从配置文件读取用户名QSettings settings("kim", "ad");username settings.value("usernam…

【03】C++ 类和对象 2:默认成员函数

文章目录 &#x1f308; 前言&#x1f308; Ⅰ 构造函数1. 构造函数概念2. 构造函数特性3. 初始化列表 &#x1f308; Ⅱ 析构函数1. 析构函数概念2. 析构函数特性 &#x1f308; Ⅲ 拷贝构造1. 拷贝构造概念2. 拷贝构造特性3. 深度拷贝构造 &#x1f308; Ⅳ 赋值重载1. 运算符…

ruoyi若依框架SpringSecurity实现分析

系列文章 ruoyi若依框架学习笔记-01 ruoyi若依框架分页实现分析 ruoyi若依框架SpringSecurity实现分析 文章目录 系列文章前言具体分析一、项目中的SpringSecurity版本二、登录认证流程分析三、权限鉴定四、退出登录五、SpringSecurity配置类 总结 前言 在ruoyi-vue若依框…

单片机的省电模式及策略

目录 一、单片机省电的核心策略 二、单片机IO口的几种模式 三、单片机的掉电运行模式 &#xff08;1&#xff09; 浅谈cpu运行为什么会需要时钟&#xff1f; &#xff08;2&#xff09;STC15系列单片机内部可以配置时钟 &#xff08;3&#xff09;分频策略&#xff0c;降低…

数据结构与算法之美学习笔记:51 | 并行算法:如何利用并行处理提高算法的执行效率?

目录 前言并行排序并行查找并行字符串匹配并行搜索总结引申 前言 本节课程思维导图&#xff1a; 时间复杂度是衡量算法执行效率的一种标准。但是&#xff0c;时间复杂度并不能跟性能划等号。在真实的软件开发中&#xff0c;即便在不降低时间复杂度的情况下&#xff0c;也可以…

Linux应用开发---网络通信

Linux应用开发—网络通信 1 网络通信概述 Linux下的网络编程&#xff0c;我们一般称为 socket 编程&#xff0c;socket 是内核向应用层提供的一套网络编程接口&#xff0c;我们可以基于socket接口开发自己的网络相关应用程序。 1.1 socket 简介 套接字&#xff08;socket&…

Jenkins升级后,构建任务配置界面重复错位

最近我把公司的Jenkins服务升级到了最新版本&#xff0c;升级完成后&#xff0c;点了一下构建任务&#xff0c;发现能够构建成功&#xff0c;就以为顺利完成升级了&#xff0c;下班走了&#xff0c;结果第二天&#xff0c;进入构建任务配置界面发现&#xff0c;界面一团乱麻&am…

LabVIEW热电偶自动校准系统

设计并实现一套基于LabVIEW平台的工业热电偶自动校准系统&#xff0c;通过自动化技术提高校准效率和精度&#xff0c;降低人力成本&#xff0c;确保温度测量的准确性和可靠性。 工业生产过程中&#xff0c;温度的准确测量对产品质量控制至关重要。传统的热电偶校准方式依赖人工…

[Java][算法 双指针]Day 02---LeetCode 热题 100---04~07

LeetCode 热题 100---04~07 第一题&#xff1a;移动零 思路 找到每一个为0的元素 然后移到数组的最后 但是需要注意的是 要在给定的数组原地进行修改 并且其他非零元素的相对顺序不能改变 我们采用双指针法 定义两个指针i和j i和j一开始分别都在0索引位置 然后判断j所…

tab 切换类交互功能实现

tab切换类交互&#xff1a; 记录激活项&#xff08;整个对象/id/index)动态类型控制 下面以一个地址 tab 切换业务功能为例&#xff1a; <div class"text item" :class"{active : activeAddress.id item.id}" click"switchAddress(item)"…