WPF中集合ObservableCollection<T>的使用

news2024/12/22 18:41:23

C#集合类ObservableCollection<T>

类似于泛型列表类List<T>,表示一个动态数据收集,该集合在添加或删除项或刷新整个列表时提供通知。

所在命名空间:System.Collections.ObjectModel

继承关系:

public class ObservableCollection<T> : Collection<T>, INotifyCollectionChanged, INotifyPropertyChanged

参考微软官方网站

ObservableCollection

有两个重要的事件

public event NotifyCollectionChangedEventHandler CollectionChanged;
protected event PropertyChangedEventHandler PropertyChanged;

实现

INotifyCollectionChanged  INotifyPropertyChanged

注解

在许多情况下,你使用的数据是 对象的集合。 例如,数据绑定中的常见方案是使用 ItemsControl (如 、 ListView或 TreeView )ListBox来显示记录集合。

你可以枚举实现 IEnumerable 接口的任何集合。 但是,若要设置动态绑定,以便集合中的插入或删除操作可以自动更新 UI,则集合必须实现 INotifyCollectionChanged 接口。 此接口公开 CollectionChanged 事件,只要基础集合发生更改,就会引发该事件。

WPF 提供 ObservableCollection<T> 类,该类是实现 INotifyCollectionChanged 接口的数据收集的内置实现。

在实现自己的集合前,请考虑使用 ObservableCollection<T> 或现有集合类之一,例如 List<T>、Collection<T> 和 BindingList<T> 等。 如果你有一个高级方案并且想要实现自己的集合,请考虑使用 IList,它提供可由索引单独访问的对象的非泛型集合。 实现 IList 提供数据绑定引擎的最佳性能。

注意

若要完全支持将数据值从绑定源对象传输到绑定目标,集合中支持可绑定属性的每个对象都必须实现适当的属性更改通知机制,例如 INotifyPropertyChanged 接口。

测试使用ObservableCollection

新建WPF应用程序DataGridDemo,在默认的MainWindow.xaml设计器中添加DataGrid和Button

 MainWindow.xaml的设计器相关代码如下:

窗体绑定Loaded事件,按钮绑定Click事件

<Window x:Class="DataGridDemo.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:DataGridDemo"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800" Loaded="Window_Loaded">
    <Grid Margin="0,0,-49,0">
        <DataGrid Name="dgTest" ItemsSource="{Binding}" AutoGenerateColumns="False" HorizontalAlignment="Left" Height="387" Margin="6,6,0,0" VerticalAlignment="Top" Width="699">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding EnglishName}" Width="120" Header="Mes名称"/>
                <DataGridTextColumn Binding="{Binding FieldName}" Width="120" Header="字段名称"/>
                <DataGridTextColumn Binding="{Binding MappingName}" Width="120" Header="映射名称"/>
                <DataGridTextColumn Binding="{Binding ChineseName}" Width="120" Header="中文名称"/>
                <DataGridTextColumn Binding="{Binding DataType}" Width="120" Header="数据类型"/>
                <DataGridTextColumn Binding="{Binding Value}" Width="120" Header="当前值"/>
            </DataGrid.Columns>
        </DataGrid>
        <Button x:Name="btnSaveEdit" Content="保存编辑后的数据" HorizontalAlignment="Left" Margin="712,16,0,0" VerticalAlignment="Top" Width="101" Height="58" Click="btnSaveEdit_Click"/>

    </Grid>
</Window>

新建测试绑定类ParametricData

ParametricData.cs如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DataGridDemo
{
    /// <summary>
    /// 需要上传的某条生产数据,由name,value,dataType等组成
    /// </summary>
    public class ParametricData
    {
        /// <summary>
        /// 中文名称,该上传数据项的描述
        /// </summary>
        public string ChineseName { get; set; }
        /// <summary>
        /// 英文名称,上传数据的键名。例如:SCGL1【输出功率1】
        /// </summary>
        public string EnglishName { get; set; }
        /// <summary>
        /// 数据表的列名或字段名,与EnglishName组成对应关系。用于手动上传出站数据时,从数据表查找数据绑定到指定的键上
        /// </summary>
        public string FieldName { get; set; }
        /// <summary>
        /// PLC地址表配置的英文名称,与EnglishName组成映射关系,用于获取实际的生产数据值
        /// </summary>
        public string MappingName { get; set; }
        /// <summary>
        /// 数据类型
        /// </summary>
        public string DataType { get; set; }
        /// <summary>
        /// 当前值
        /// </summary>
        public string Value { get; set; }
    }
}

MainWindow.xaml.cs相关处理代码如下

using System;
using System.Collections.Generic;
using System.IO;
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 DataGridDemo
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        //List<ParametricData> ParametricDataList = new List<ParametricData>();
        System.Collections.ObjectModel.ObservableCollection<ParametricData> ParametricDataList = new System.Collections.ObjectModel.ObservableCollection<ParametricData>();
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            for (int i = 0; i < 10; i++)
            {
                ParametricDataList.Add(new ParametricData()
                {
                    EnglishName = $"TestData{i + 1}",
                    ChineseName = $"测试数据{i + 1}",
                    FieldName = $"TestData{i + 1}",
                    MappingName = $"TestData{i + 1}",
                    DataType = "数字",
                    Value = new Random(Guid.NewGuid().GetHashCode()).Next(1, 1000).ToString("D3"),
                });
            }
            dgTest.DataContext = ParametricDataList;
        }

        private void btnSaveEdit_Click(object sender, RoutedEventArgs e)
        {
            int affectCount = 0;
            for (int i = 0; i < dgTest.Items.Count; i++)
            {
                ParametricData parametricData = dgTest.Items.GetItemAt(i) as ParametricData;
                if (parametricData == null || string.IsNullOrWhiteSpace(parametricData.EnglishName)) 
                {
                    continue;
                }
                WriteLogCsv(AppDomain.CurrentDomain.BaseDirectory + "test.csv", parametricData);
                affectCount++;
            }
            MessageBox.Show($"保存编辑后的数据成功,保存数据条数:【{affectCount}】");
        }

        /// <summary>
        /// 写CSV日志 按列显示
        /// </summary>
        /// <param name="fileName">写入的csv文件名,全路径</param>
        /// <param name="barcode">条码</param>
        /// <param name="responseResult">MES请求与返回信息对象</param>
        /// <returns></returns>
        public static bool WriteLogCsv(string fileName, ParametricData parametricData)
        {
            try
            {
                string directoryPath = System.IO.Path.GetDirectoryName(fileName);
                if (!Directory.Exists(directoryPath))
                {
                    Directory.CreateDirectory(directoryPath);
                }
                string columnContents = "Mes名称,字段名称,映射名称,中文名称,数据类型,当前值\r\n";
                if (!File.Exists(fileName))
                {
                    File.AppendAllText(fileName, columnContents, Encoding.Default);
                }

                StringBuilder sb = new StringBuilder();
                using (StreamWriter write = new StreamWriter(fileName, true, Encoding.Default))
                {
                    sb.Append($"{parametricData.EnglishName},");
                    sb.Append($"{parametricData.FieldName},");
                    sb.Append($"{parametricData.MappingName},");
                    sb.Append($"{parametricData.ChineseName},");
                    sb.Append($"{parametricData.DataType},");
                    sb.Append($"{ProcessPunctuationForCsv(parametricData.Value)}");
                    write.WriteLine(sb.ToString());
                }
                return true;
            }
            catch (Exception ex)
            {
                MessageBox.Show("CSV文件写入失败:" + ex.Message);
                return false;
            }
        }

        /// <summary>
        /// 处理csv文件中的双引号和逗号,使其在Excel中完美显示为一个单元格
        /// </summary>
        /// <param name="srcStr"></param>
        /// <returns></returns>
        private static string ProcessPunctuationForCsv(string srcStr)
        {
            if (srcStr == null)
            {
                return string.Empty;
            }
            bool quoteFlag = false;//是否添加过双引号
            //如果存在双引号,需要将字符串的一个双引号 替换为 两个双引号。并且需要在字符串的前后加上双引号
            if (srcStr.Contains("\""))
            {
                srcStr = srcStr.Replace("\"", "\"\"");
                srcStr = "\"" + srcStr + "\"";
                quoteFlag = true;
            }
            //如果只存在逗号(不存在引号),将前后加引号即可
            if (srcStr.Contains(",") && !quoteFlag)
            {
                srcStr = "\"" + srcStr + "\"";
            }
            return srcStr;
        }
    }
}

运行效果如图:

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

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

相关文章

APP软件开发详细流程如何?

在互联网技术发达的今天&#xff0c;APP已经深入到我们生活的方方面面了&#xff0c;从购物、家政、洗车、教育到美容、旅游、餐饮等等&#xff0c;都可以通过各种各样的APP软件来实现&#xff0c;使我们的生活更加便捷化、智能化。不过&#xff0c;很多感兴趣的朋友对于APP软件…

亚马逊云科技宣布全面推出Amazon Aurora I/O-Optimized集群配置

自亚马逊云科技Amazon Aurora于2014年推出以来&#xff0c;成千上万的客户选择Aurora来运行其要求最严苛的应用程序。Aurora在全球范围内提供无与伦比的高性能和可用性&#xff0c;完全兼容MySQL和PostgreSQL&#xff0c;成本仅为商用数据库的十分之一。 许多亚马逊云科技客户受…

电竞小程序系统开发功能有哪些?

电竞小程序系统开发功能有哪些&#xff1f; 1、电竞资讯。对于电竞爱好者来说&#xff0c;每一场电竞比赛的相关信息都是不容错过的&#xff0c;因此用户可以通过小程序直接了解近期电竞相关资讯&#xff0c;例如&#xff1a;赛程安排、直播平台、参赛团队、比赛规则等&…

【CocosCreator问题总结】MotionStreak效果显示异常

&#x1f4e2;博客主页&#xff1a;肩匣与橘&#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;本文由肩匣与橘编写&#xff0c;首发于CSDN&#x1f649;&#x1f4e2;生活依旧是美好而又温柔的&#xff0c;你也是✨ …

公司新招了一个00后软件测试工程师,上来一顿操作给我看呆了...

前段时间公司新来了个同事&#xff0c;听说大学是学的广告专业&#xff0c;因为喜欢IT行业就找了个培训班&#xff0c;后来在一家小公司干了三年&#xff0c;现在跳槽来我们公司。来了之后把现有项目的性能优化了一遍&#xff0c;服务器缩减一半&#xff0c;性能反而提升4倍!给…

基于微信小程序的医院挂号预约系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

react学习2

props基本用法&#xff0c;把属性自动保存到props里 简写&#xff1a;三点展开&#xff0c;展开运算符无法展开对象&#xff0c;但是三点外侧包裹花括号可以复制对象{...P} 对props的属性进行限制 首先需要引入prop-types.js包 之后再去进行限制 props是只读的&#xff0c;只…

Vue之数据代理(getter、setter)

文章目录 前言一、数据代理1.Object.defineProperty()2.数据代理讲解 总结 前言 Object.defineProperty 数据代理 一、数据代理 1.Object.defineProperty() &#xff08;1&#xff09;实例对象可以通过Object.defineProperty()方法来添加属性&#xff0c;但是添加的属性默认…

进击的Mini LED:群雄逐“屏”,谁主沉浮

前不久&#xff0c;素有家电产业“风向标”之称的中国家电及消费电子博览会AWE在上海圆满闭幕。作为全球三大顶级家电与消费电子展会之一&#xff0c;每年各家企业都会携各自尖端技术亮剑上海滩&#xff0c;舞台中央的面孔也会逐年有些许不同&#xff0c;而从C位的演变中&#…

基于Spring Boot的秒杀系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SpringBoot 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;…

陌生交友发布动态圈子单聊打招呼群聊app开发

陌生交友发布动态圈子单聊打招呼群聊app开发 功能有&#xff0c;发布圈子&#xff0c;发布动态&#xff0c;查看附近的人&#xff0c;发布活动&#xff0c;实人认证&#xff0c;个人主页&#xff0c;相册查看,单聊&#xff0c;群聊。 即时通讯第三方goeasy接口。 好的&#x…

017+图解C语言中函数栈帧的创建与销毁(VS2022环境)

0.前言 您好&#xff0c;这里是limou3434的一篇个人博文&#xff0c;感兴趣的话您也可以看看我的其他文章。本次我将和您一起学习在C语言中函数栈帧的概念。 1.学习函数栈帧的意义 局部变量是怎么穿创建的&#xff1f;为什么局部变量的值是随机的函数是怎么传参的&#xff1…

满分Spring全家桶笔记:Spring+Spring Boot+Spring Cloud+Spring MVC

最近小编整理了一下一线架构师的Spring全家桶笔记&#xff1a;SpringSpring BootSpring CloudSpring MVC&#xff0c;分享给大家一起学习一下~ 01 Spring Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架。Spring框架是由于软件开发的复杂性而创建的。Spring使用的…

nacos+frp穿透实现局域网调用

简介&#xff1a;首先你要有外网服务器。在外网服务器上安装frp服务端。然后在你想要调用的局域网电脑上安装frp客户端 frp下载链接 Releases fatedier/frp GitHub 外网服务器上我用的是docker安装的。你也可以直接下载并启动。这里我就不描述了。 首先我们先创建某个目录…

ESP32 ADC测量电压 arduino

ADC ADCESP32的ADC通道衰减倍数代码实现精度问题 ADC ADC&#xff08;模拟-数字转换器&#xff09;&#xff0c;首先了解模拟信号和数字信号之间的差异。模拟信号是连续的&#xff0c;可以在其范围内取无限个离散值&#xff0c;例如声音、光线等。 数字信号则是离散的&#xf…

Redis(三)常用配置解析

文章目录 度量单位引入其他配置文件启动时加载模块网路配置GENERAL 通用配置REPLICATION 主从复制相关配置安全配置AOF配置 提示&#xff1a;Redis 6.2.6版本 度量单位 注意&#xff1a;g和gb有区别&#xff0c;不区分大小写&#xff0c;1gb 1GB都是一样的。引入其他配置文件…

Qt编程基础 | 第三章-控件 | 3.3、对话框

一、QDialog 1.1、定义 对话框&#xff1a;在主窗口中操作&#xff0c;有可能触发某一个行为动作&#xff0c;会弹出一个新的对话窗口&#xff0c;解决一个临时性的会话&#xff0c;在对话窗口中执行某一个功能。QDialog可以作为自定义对话框的基类&#xff0c;同时Qt也提供了…

Hadoop部署本地模式

​ 本地模式&#xff0c;即运行在单台机器上。没有分布式的思想&#xff0c;使用的是本地文件系统。使用本地模式主要是用于对MapReduce的程序的逻辑进行调试&#xff0c;确保程序的正确性。由于在本地模式下测试和调试MapReduce程序较为方便&#xff0c;因此&#xff0c;这种模…

java实现大气质量插值图及六项污染物插值图图片导出

软件导出成果图效果 一、技术实现应用背景 大气污染是当今世界面临的一个严重问题。它不仅对人类健康造成了危害&#xff0c;还对环境和生态系统产生了负面影响。在许多地区&#xff0c;大气污染已经成为了日常生活中不可忽视的问题。 虽然大气污染的问题是复杂的&#xff0c;…

关于如何使用 python 下载CSV格式数据

本章节内容节自《python 编程从入门到实践》第十六章&#xff0c;我们将从网络上下载数据&#xff0c;并对数据进行可视化。就可以对其进行分析甚至观察其规律和关联。 学习目标 我们将访问并可视化以下两种常见格式存储的数据&#xff1a; CSV 使用 Python 模块 CSV 来处理以…