WPF_ObservableCollection基本使用及其注意项

news2024/9/17 7:37:01

文章目录

  • 一、引言
  • 二、ObservableCollection
  • 三、结语


一、引言

在GUI编程中经常会用到条目控件,常见的如ComboBox(下拉列表框),它内部往往有多个项。

在使用一些图形框架(Qt、WinForm)上进行原始开发时,往往在界面初始化阶段直接访问UI控件,往其中添加列表项;若后期有改动,通过事件触发处理程序来再往其中增删项。

这种方式有一定局限性,你想要更新列表中的数据并使之呈现在UI上就得直接访问控件。如果只是ComboBox这种简单的条目控件,那直接 comboBox.AddItem就好;但如果是在更复杂的控件中(如grid网格),要想添加新项,代码就没那么容易写了。

WPF中的ObservableCollection可以将控件与数据源绑定,使得控件与数据源保持同步。简单讲,在控件与数据源绑定后,你只需要往数据源中增删数据,而不需要管UI变更逻辑,且实现了前后端分离。

二、ObservableCollection

微软官方文档中描述,ObservableCollection是一个动态数据集合,当集合中的项增加、移除、更新,或整个列表刷新时,它会提供通知(通知绑定的控件做出改变)。

下面是我写的demo,左边是一个ComboBox,它的ItemSource绑定了集合对象;右边是一些按钮,按钮单击的命令会修改集合对象,
在这里插入图片描述
下面是界面主要的XAML代码:

   <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <ComboBox ItemsSource="{Binding Items}" Height="30" x:Name="comboBox"/>
        <StackPanel Grid.Column="1">
            <StackPanel.Resources>
                <Style TargetType="Button">
                    <Setter Property="Margin" Value="8"/>
                </Style>
            </StackPanel.Resources>
            <Button Content="添加一项" Command="{Binding AddItemCommand}"/>
            <Button Content="移除一项" Command="{Binding RemoveItemCommand}"/>
            <Button Content="更新项" Command="{Binding UpdateItemCommand}"/>
            <Button Content="替换整个列表" Command="{Binding ReplaceListCommand}"/>
            <Button Content="查看ItemSource绑定对象" Command="{Binding InspectObjectCommand}" CommandParameter="{Binding ElementName=comboBox}"/>
        </StackPanel>
    </Grid>

下面是后台ViewModel中的代码,主要是命令:

		public MainWindowViewModel()
        {
            _items = new ObservableCollection<string>()
            {
                "初始项1",
                "初始项2",
                "初始项3"
            };
        }

        private ObservableCollection<string> _items;
        public ObservableCollection<string> Items
        {
            get => _items;

        }

        private RelayCommand _addItemCommand;
        public RelayCommand AddItemCommand
        {
            get => _addItemCommand?? (_addItemCommand = new RelayCommand(() =>
            {
                _items.Add("新加项");
            }));
        }

        private RelayCommand _removeItemCommand = null;
        public RelayCommand RemoveItemCommand
        {
            get => _removeItemCommand ?? (_removeItemCommand = new RelayCommand(() =>
            {
                _items.Remove(_items.Last());
            }));
        }

        private RelayCommand _updateItemCommand;
        public RelayCommand UpdateItemCommand
        {
            get => _updateItemCommand ?? (_updateItemCommand = new RelayCommand(() =>
            {
                _items[0] = "更新项";
            }));
        }

        private RelayCommand _replaceListCommand;
        public RelayCommand ReplaceListCommand
        {
            get => _replaceListCommand ?? (_replaceListCommand = new RelayCommand(() =>
            {
                _items = new ObservableCollection<string>()
                {
                    "替换后的表"
                };
                MessageBox.Show("替换完毕");
            }));
        }

        private RelayCommand<object> _inspectObjectCommand;
        public RelayCommand<object> InspectObjectCommand
        {
            get => _inspectObjectCommand ?? (_inspectObjectCommand = new RelayCommand<object>((o) => 
            {
                ComboBox cb = o as ComboBox;
                MessageBox.Show(string.Format("HashCode:\nItemSource={0}\n_items={1}\n是否相等?{2}", 
                cb.ItemsSource.GetHashCode(), _items.GetHashCode(),cb.ItemsSource.Equals(_items)));
            }));
        }

其中增、删、改这三个命令都能即时反映到UI。而替换列表命令并不能起作用。单击 查看绑定对象 按钮,可以看到,ItemSource和后台_items的hashCode是相等的,并且用equals比较它们也是相等的;

在这里插入图片描述
接着,单击 替换整个列表 按钮,再查看绑定对象,这次ItemSource的hashCode并未发生变化,且equals也反映出与后台_items不等。
在这里插入图片描述
可见,对绑定的数据源做替换并不能修改ItemSource(访问控件的ItemSource做修改是可以的,虽然这是废话)。

引用类型与基本类型


这里的本质问题其实是引用类型与基本类型的赋值问题。

int a = 1;
int b = a;

基本类型(如 数字、字串、布尔,通常是较简单的)的赋值,是把值拷贝过去。
声明基本类型时,会在栈内存中开辟一块空间,存放变量的值。当a的值赋给b时,a的值会被复制到b的空间中。它们两值的存放是独立的,在不同空间中,如下图。
在这里插入图片描述
而引用类型数据的变量名存放在栈内存中,值存放在堆内存中,栈内存会提供一个引用地址用于指向堆内存中的值。非常类似于C语言中的指针,
在这里插入图片描述
所以这里的情况就是,
在这里插入图片描述
_items = new ObservableCollection(){ "替换后的表"}其实就是在堆空间中再开辟一块内存,然后将_items变量的栈内存控件里的地址指向它。因此ItemSource并不会改变。

因此想替换整个列表,应该直接替换ItemSource的值。

三、结语

ObservableCollection基本使用如上述代码示例所示。其中要注意的是,替换ViewModel中的绑定对象并不能真实替换ItemSource。还有ObservableCollection不是线程安全的,ItemSource绑定其后,不能跨线程(UI线程外)修改ObservableCollection,关于这点会另辟文进行介绍。

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

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

相关文章

安卓mvvm

AndroidX的意思是android extension libraries, 也就是安卓扩展包 AndroidX其实是Jetpack类库的命名空间 (190条消息) AndroidX初识_Neda Wang的博客-CSDN博客https://blog.csdn.net/weixin_38261570/article/details/111500044 viewmodel ViewModel类旨在以注重生命周期的方…

【机器学习】决策树-C4.5算法

1.C4.5算法 C4.5算法与ID3相似&#xff0c;在ID3的基础上进行了改进&#xff0c;采用信息增益比来选择属性。ID3选择属性用的是子树的信息增益&#xff0c;ID3使用的是熵&#xff08;entropy&#xff0c; 熵是一种不纯度度量准则&#xff09;&#xff0c;也就是熵的变化值&…

回溯算法理论基础及组合问题

文章目录回溯算法理论基础什么是回溯法回溯法的效率回溯法解决的问题如何理解回溯法回溯法模板组合问题回溯算法理论基础 什么是回溯法 回溯法也可以叫做回溯搜索法&#xff0c;它是一种搜索的方式。 回溯是递归的副产品&#xff0c;只要有递归就会有回溯。 所以以下讲解中&…

LPWAN及高效弹性工业物联网核心技术方案

20多年前的一辆拖拉机就是一个纯机械的产品&#xff0c;里面可能并没有电子或者软件的构成&#xff1b;而随后随着软件的发展&#xff0c;拖拉机中嵌入了软件&#xff0c;它能控制发动机的功率及拖拉机防抱死系统&#xff1b;接下来&#xff0c;通过融入各种软件&#xff0c;拖…

js逆向基础篇-某房地产网站-登录

提示!本文章仅供学习交流,严禁用于任何商业和非法用途,如有侵权,可联系本文作者删除! 网站链接:aHR0cHM6Ly9tLmZhbmcuY29tL215Lz9jPW15Y2VudGVyJmE9aW5kZXgmY2l0eT1iag== 案例分析: 本篇文章分析的是登录逻辑。话不多说,先看看登录中有哪些加密参数,在登录页面随便输入…

K8S DNS解析过程和延迟问题

一、Linux DNS查询解析原理&#xff08;对于调用glibc库函数gethostbyname的程序&#xff09;我们在浏览器访问www.baidu.com这个域名&#xff0c;dns怎么查询到这台主机呢&#xff1f;  1、在浏览器中输入www.baidu.com域名&#xff0c;操作系统会先查找本地DNS解析器缓存&a…

实例2:树莓派GPIO控制外部LED灯闪烁

实例2&#xff1a;树莓派GPIO控制外部LED灯闪烁 实验目的 通过背景知识学习&#xff0c;了解四足机器人mini pupper搭载的微型控制计算机&#xff1a;树莓派。通过树莓派GPIO操作的学习&#xff0c;熟悉GPIO的读写控制。通过外部LED灯的亮灭控制&#xff0c;熟悉树莓派对外界…

vue3 + vite 使用 svg 可改变颜色

文章目录vue3 vite 使用 svg安装插件2、配置插件 vite.config.js3、根据vite配置的svg图标文件夹&#xff0c;建好文件夹&#xff0c;把svg图标放入4、在 src/main.js内引入注册脚本5、创建一个公共SvgIcon.vue组件6.1 全局注册SvgIcon.vue组件6.2、在想要引入svg的vue组件中引…

Boom 3D最新版本下载电脑音频增强应用工具

为了更好地感受音乐的魅力&#xff0c;Boom 3D 可以让你对音效进行个性化增强&#xff0c;并集成 3D 环绕立体声效果&#xff0c;可以让你在使用任何耳机时&#xff0c;都拥有纯正、优质的音乐体验。Boom 3D是一款充满神奇魅力的3D环绕音效升级版&#xff0c;BOOM 3D是一个全新…

MyBatis 之四(动态SQL之 if、trim、where、set、foreach 标签)

文章目录动态 SQL1. if 标签2. trim 标签3. where 标签4. set 标签5. foreach 标签回顾一下&#xff0c;在上一篇 MyBatis 之三&#xff08;查询操作 占位符#{} 与 ${}、like查询、resultMap、association、collection&#xff09;中&#xff0c;学习了针对查询操作的相关知识点…

【C++】map和set的封装

文章目录一、前情回顾二、简化源码三、仿函数四、迭代器五、set的实现六、map的实现七、红黑树代码一、前情回顾 set 参数只有 key&#xff0c;但是map除了key还有value。我们还是需要KV模型的红黑树的&#xff1a; #pragma once #include <iostream> #include <ass…

游戏服务器算法-AOI基本介绍

一、直接比较所有对象 最直观也是最效率最低的一种方法。当一个事件发生&#xff0c;我们需要获得AOI范围以内的物体时&#xff0c;直接遍历游戏中所有的对象&#xff0c;并且进行坐标判断&#xff0c;如果小于或者等于AOI的范围&#xff0c;则为需要的游戏对象。 这种方法实…

零基础小白如何学会云计算?

云计算作为新兴互联网技术&#xff0c;也是IT服务的集大成者&#xff0c;包括了基础硬件服务、平台服务、应用程序开发、系统架构等服务内容。云计算的出现承接了众多IT技术和其他行业的发展&#xff0c;比如大数据、人工智能以及工业、金融、医疗、物流等&#xff0c;是经济社…

VBA提高篇_26 Textbox多行_ListBox_ComboBox

文章目录1. 文本框多行换行2. ListBox: 列表框2.1 列表框中添加条目的三种方法:3. ComboBox 组合框: 属性方法等同于以上ListBox1. 文本框多行换行 MultiLine: 控制文本框多行自动换行() Enterkeybehevior: True 代表允许在文本框中使用回车键换行 WordWrap: True 代表自动换…

/etc/fstab文件

文件/etc/fstab存放的是系统中的文件系统信息&#xff0c;当系统启动的时候&#xff0c;系统会自动地从这个文件读取信息&#xff0c;并且会自动将此文件中指定的文件系统挂载到指定的目录。当正确的设置了该文件&#xff0c;则可以通过mount /directoryname命令来加载一个文件…

Tapdata Connector 实用指南:数据入仓场景之数据实时同步到 BigQuery

【前言】作为中国的 “Fivetran/Airbyte”, Tapdata 是一个以低延迟数据移动为核心优势构建的现代数据平台&#xff0c;内置 60 数据连接器&#xff0c;拥有稳定的实时采集和传输能力、秒级响应的数据实时计算能力、稳定易用的数据实时服务能力&#xff0c;以及低代码可视化操作…

恢复 iPhone 和 iPad 数据的 10 种简单工具

它发生了.. 有时您需要从您的手机或平板设备恢复重要数据。 许多人已经开始将重要文件存储在手机上&#xff0c;因为他们几乎可以在任何情况下随时随地轻松访问数据。 从技术上讲&#xff0c;您会在几分之一秒内丢失所有存储的信息、照片、视频、音乐、文档等。因此&#xff…

一文3000字用Postman从0到1实现UI自动化测试

“阅读本文大概需要4分钟。Postman不是做接口测试的吗&#xff1f;为什么还能做UI自动化测试呢&#xff1f; 其实&#xff0c;只要你了解Selenium的运行原理&#xff0c;就可以理解为什么Postman也能实现UI自动化测试了。 Selenium底层原理 运行代码&#xff0c;启动浏览器后…

笔试题(十六):计算矩阵面积

# 我们给出了一个&#xff08;轴对齐的&#xff09;二维矩形列表 rectangles。 # 对于 rectangle[i] [xi1, yi1, xi2, yi2]&#xff0c;表示第i个矩形的坐标&#xff0c; # (xi1, yi1)是该矩形左下角的坐标&#xff0c; (xi2, yi2)是该矩形右上角的坐标。 # 计算平面中所有 r…

CAJ论文怎么批量免费转换成Word

大家都知道CAJ文件吗&#xff1f;这是中国学术期刊数据库中的文件&#xff0c;这种文件类型比较特殊。如果想要提取其中的内容使用&#xff0c;该如何操作呢&#xff1f;大家可以试试下面这种免费的caj转word的方法,多个文档也可以一起批量转换。准备材料&#xff1a;CAJ文档、…