当前位置: 首页 > news >正文

ReactiveUI MVVM框架(1)-Collections

ReactiveUI MVVM框架(1)-Collections

ReactiveUI使用动态数据(DynamicData)用于集合的操作。

当对动态数据集合进行更改时,会产生更改通知,通知表示为ChangeSet,里面包含了更改信息,多个更改通知为IObservable<ChangeSet>。动态数据提供了两种特定的集合,分别是SourceCache<TObject, TKey>SourceList<T>。第一个为带key的字典式,也就是不能重复,第二个为集合式。如何要将这两种集合转换为IObservable<ChangeSet>,可以使用Connect方法。

需要注意的是,这跟WPF中常用的ObservableCollection<T>的实现方式是不同的。

简单使用

从wpf中常用的ObservableCollection<T>得到IObservable<ChangeSet>

// 'myList' is ObservableCollection<T>
// 'myDerivedList' is IObservableList<T>
var myDerivedList = myList.ToObservableChangeSet().Filter(t => t.Status == "Something").AsObservableList();// 'myList' is ObservableCollection<T>
// 'myDerivedCache' is IObservableCache<T, TKey>
var myDerivedCache = myList.ToObservableChangeSet(t => t.Id).Filter(t => t.Status == "Something").AsObservableCache();

以上两种方式是线程不安全的,加入myList绑定到了View上,那么在View上也可能对myList进行更改。推荐的方法是先创建一个数据源。

var myList = new SourceList<T>()
var disposable = myList.Connect() // 获得IObservable<ChangeSet>.\\some other operation

这种方法的好处是可以在后台线程上进行维护。比如:

//ReadOnlyObservableCollection可以多线程操作
ReadOnlyObservableCollection<T> bindingData;
var disposable = mySource.Connect() // make the source an observable change set.Sort(SortExpressionComparer<T>.Ascending(t => t.DateTime)).ObserveOn(RxApp.MainThreadScheduler) // 'mySource' 会在其他线程上更新.Bind(out bindingData).Subscribe(); 

ReactiveUI使用动态数据

开发时,会遇到可变集合和不可变集合,当对不可变集合进行处理时,简单情况下可以使用ObservableAsPropertyHelper<T>,它包含一个Observable<T>。每次给集合赋予新的集合时会触发通知事件。

而对于可变集合,往往采用动态数据的方式。

案例

public class Service 
{//定义一个数据集private readonly SourceList<bool> _items = new SourceList<bool>();//暴露给外面public IObservable<IChangeSet<bool>> Connect() => _items.Connect();public Service(){        _items.Add(true);_items.RemoveAt(0);_items.Add(false);}
}

ReadOnlyObservableCollection

  • 动态数据往往使用ReadOnlyObservableCollection<T>之类的类型对外公开,而不是它本身的类型。IObservable<IChangeSet<T>>IObservable<IChangeSet<TObject, TKey>>是可以观测类型,IObservable<IChangeSet<T>>中含有集合更改的内容,第一次使用ToObservableChangeSet()时会发出集合的当前状态。
  • SourceListSourceCache是可以使用多线程进行创建IObservable<IChangeSet<T>>等,通常SourceListSourceCache应该定义为Private,而是通过Connect方法暴露给View。
public class ViewModel : ReactiveObject
{private readonly ReadOnlyObservableCollection<bool> _items;public ReadOnlyObservableCollection<bool> Items => _items;public ViewModel(){var service = new Service();service.Connect()// Transform 和Select方法类似,只不过是观察一个集合的变化且将元素投影到另一个集合.Transform(x => !x)// Filter 类似于Where.Filter(x => x)// 确保更先到UI线程..ObserveOn(RxApp.MainThreadScheduler)// 通过 .Bind() 方法实现可变集合包含新的数据并且刷新UI.Bind(out _items).Subscribe();}
}

ObservableCollectionExtended

ObservableCollectionExtended<T>是一个单线程集合,如果要同步VM中的两个集合,可以将其中一个声明为ObservableCollectionExtended<T>,另一个声明为ReadOnlyObservableCollection<T>,然后使用.ToObservableChangeSet()方法将其转换为IObservable<IChangeSet<T>>

public class SynchronizedCollectionsViewModel : ReactiveObject
{private readonly ReadOnlyObservableCollection<bool> _derived;public ReadOnlyObservableCollection<bool> Derived => _derived;public ObservableCollectionExtended<bool> Source { get; }public SynchronizedCollectionsViewModel(){Source = new ObservableCollectionExtended<bool>();Source.ToObservableChangeSet().Transform(value => !value)// 在这里不需要使用ObserveOn更新UI线程,因为它是单线程.Bind(out _derived).Subscribe();Source.Add(true);Source.RemoveAt(0);Source.Add(false);Source.Add(true);}
}

根据集合中的更改

ReactiveObject类实现了INotifyPropertyChanged,动态数据可以对ReactiveObject类进行跟踪。

// 'collectionOfReactiveObjects' 是 ObservableCollection<T>
//  T inherits 继承自 ReactiveObject
// 'databasesValid' 则是 IObservable<bool>
var databasesValid = collectionOfReactiveObjects.ToObservableChangeSet().AutoRefresh(model => model.IsValid) // 订阅IsValid属性的更改.ToCollection()                      // 获取新项目集合.Select(x => x.All(y => y.IsValid)); // 验证是否满足条件.// 将IObservable<bool> 转为视图模型
// '_databasesValid' 是ObservableAsPropertyHelper<bool> 类型
_databasesValid = databasesValid.ToProperty(this, x => x.DatabasesValid);

ReactiveList转为动态数据

如果使用的是ReactiveList<T>,并且仅从UI线程添加/删除,则使用ObservableCollectionExtended<T>

相关文章:

ReactiveUI MVVM框架(1)-Collections

ReactiveUI MVVM框架&#xff08;1&#xff09;-Collections ReactiveUI使用动态数据&#xff08;DynamicData&#xff09;用于集合的操作。 当对动态数据集合进行更改时&#xff0c;会产生更改通知&#xff0c;通知表示为ChangeSet&#xff0c;里面包含了更改信息&#xff0…...

【微服务】五. Nacos服务注册

Nacos服务注册 5.1 Nacos服务分级存储模型Nacos服务分级存储模型&#xff1a;服务集群属性&#xff1a;总结&#xff1a; 5.2 根据集群负载均衡总结 5.3 Nacos服务实例的权重设置总结&#xff1a; 5.6 环境隔离namespace总结 5.7 Nacos和Eureka的对比总结 5.1 Nacos服务分级存储…...

Lnmp架构-Redis

网站&#xff1a;www.redis.cn redis 部署 make的时候需要gcc和make 如果在纯净的环境下需要执行此命令 [rootserver3 redis-6.2.4]# yum install make gcc -y 注释一下这几行 vim /etc/redis/6739.conf 2.Redis主从复制 设置 11 是master 12 13 是slave 在12 上 其他节…...

Python 二进制数据处理与转换

不得不说&#xff0c;Python能火是有原因的&#xff0c;物联网开发中常用的数据处理方式&#xff0c;Python都有内置的函数或方法&#xff0c;相当方便&#xff0c;官方文档见二进制序列类型&#xff0c;下面是一些示例代码 string Hello World! # 字符串转二进制数据 data …...

【LeetCode】297.二叉树的序列化与反序列化

题目 序列化是将一个数据结构或者对象转换为连续的比特位的操作&#xff0c;进而可以将转换后的数据存储在一个文件或者内存中&#xff0c;同时也可以通过网络传输到另一个计算机环境&#xff0c;采取相反方式重构得到原数据。 请设计一个算法来实现二叉树的序列化与反序列化…...

Java HashSet

HashSet 基于 HashMap 来实现的&#xff0c;是一个不允许有重复元素的集合。 HashSet 允许有 null 值。 HashSet 是无序的&#xff0c;即不会记录插入的顺序。 HashSet 不是线程安全的&#xff0c; 如果多个线程尝试同时修改 HashSet&#xff0c;则最终结果是不确定的。 您必…...

在iPhone上构建自定义数据采集完整指南

在iPhone上构建自定义数据采集工具可以帮助我们更好地满足特定需求&#xff0c;提高数据采集的灵活性和准确性。本文将为您提供一份完整的指南和示例代码&#xff0c;教您如何在iPhone上构建自定义数据采集工具。 自定义数据采集工具的核心组件 a、数据模型 数据模型是数据采…...

Android MediaRecorder录音

1. 简介 在android中录制音频有两种方式&#xff0c;MediaRecorder和AudioRecord。两者的区别如下&#xff1a; MediaRecorder 简单方便&#xff0c;不需要理会中间录制过程&#xff0c;结束录制后可以直接得到音频文件进行播放&#xff1b;录制的音频文件是经过压缩的&#…...

软件提示vcruntime140_1.dll丢失的解决方法,以及丢失的原因总结

在运行某些程序时&#xff0c;可能会出现“vcruntime140_1.dll 丢失”的错误提示。这是因为 vcruntime140_1.dll 是 Visual C Redistributable 的一部分&#xff0c;它通常被安装在 Windows 操作系统上。如果该文件丢失或无法找到&#xff0c;可能会导致程序无法正常运行。在我…...

Datax抽取mysql的bit类型数据

背景&#xff1a;使用datax抽取mysql的一张表&#xff0c;里面有两个bit类型的字段&#xff0c;抽取出来显示如下&#xff1a; 需要在抽取reader里面进行处理配置 最终生成的datax的json文件reader的配置会转换为具体的数值 最终查询效果&#xff1a;...

git 后悔药

前言 自上而下&#xff0c;撤销可以分为从远程库撤销&#xff0c;从本地库撤销&#xff0c;从暂存库撤销。 例子&#xff1a;代码已经提交了三个记录到远程库&#xff0c;分别对应了记录1&#xff0c;内容1&#xff0c;记录2&#xff0c;内容2&#xff0c;记录3&#xff0c;内…...

vue-cli搭建一个新项目及基础配置

vue-cli搭建一个新项目及基础配置 一、安装步骤二、main.js配置三、router下的index.js 一、安装步骤 1.安装node环境&#xff1a;下载地址&#xff1a;Node.js 2.安装脚手架&#xff1a;npm install -g vue/cli 3.创建vue项目&#xff1a;vue create 项目名 4.进入项目&…...

【C++】 C++11(右值引用,移动语义,bind,包装器,lambda,线程库)

文章目录 1. C11简介2. 统一的列表初始化2.1 &#xff5b;&#xff5d;初始化2.2 std::initializer_list 3. 声明3.1 auto3.2 decltype3.3 auto与decltype区别3.4 nullptr 4. 右值引用和移动语义4.1 左值引用和右值引用4.2 左值引用与右值引用比较4.3 右值引用使用场景和意义4.…...

附录1-爬虫的一些技巧

目录 1 寻找url与显示内容的关系 2 修改请求头 3 局部刷新 4 阅读返回信息 5 多尝试页面其他的使用方式 6 尝试不同类型参数 7 表单类型的post多用data发&#xff0c;接口类型的post多用json发 8 消除degger 9 你在浏览器上看到的html与你下载下来的html不一…...

【android12-linux-5.1】【ST芯片】【RK3588】【LSM6DSR】HAL移植

一、环境介绍 RK3588主板搭载Android12操作系统,内核是Linux5.10,使用ST的六轴传感器LSM6DSR芯片。 二、芯片介绍 LSM6DSR是一款加速度和角速度(陀螺仪)六轴传感器,还内置了一个温度传感器。该芯片可以选择I2C,SPI通讯,还有可编程终端,可以后置摄像头等设备,功能是很…...

DragGAN应运而生,未来在4G视频上都可能利用拖拽式编辑

原创 | 文 BFT机器人 2023年8月14日-15日&#xff0c;第七届GAIR全球人工智能与机器人大会在新加坡乌节大酒店成功举办。 在「AIGC 和生成式内容」分论坛上&#xff0c;南洋理工大学科学与工程学院助理教授潘新钢以《Interacitve Point-Dragging Manipulation of Visual Cont…...

【C++技能树】多态解析

Halo&#xff0c;这里是Ppeua。平时主要更新C&#xff0c;数据结构算法&#xff0c;Linux与ROS…感兴趣就关注我bua&#xff01; 文章目录 0.多态的概念0.1 多态的定义 1. 重写2.Final与Override3.抽象类4.多态中的内存分布.4.1虚表存在哪里? 5.多态调用原理5.1 动态绑定与静…...

【爬虫笔记】Python爬虫简单运用爬取代理IP

一、前言 近些年来&#xff0c;网络上的爬虫越来越多&#xff0c;很多网站都针对爬虫进行了限制&#xff0c;封禁了一些不规则的请求。为了实现正常的网络爬虫任务&#xff0c;爬虫常用代理IP来隐藏自己的真实IP&#xff0c;避免被服务器封禁。本文将介绍如何使用Python爬虫来…...

IP协议-NAT机制(理解网络结构的关键要点)

前言 我们现在使用得最多的IP协议版本是IPv4&#xff0c;IPv4是4个字节&#xff0c;32位&#xff0c;也就是说我们的IP地址最多就只有2^32&#xff08;42亿&#xff09;个&#xff0c;在日常生活中&#xff0c;我们需要联网的设备都需要有IP地址才能进行通讯&#xff0c;很明显…...

Python UI自动化 —— 关键字+excel表格数据驱动

步骤&#xff1a; 1. 对selenium进行二次封装&#xff0c;创建关键字的库 2. 准备一个表格文件来写入所有测试用例步骤 3. 对表格内容进行读取&#xff0c;使用映射关系来对用例进行调用执行 4. 执行用例 1. 对selenium进行二次封装&#xff0c;创建关键字的库 from time imp…...

KubeSphere 容器平台高可用:环境搭建与可视化操作指南

Linux_k8s篇 欢迎来到Linux的世界&#xff0c;看笔记好好学多敲多打&#xff0c;每个人都是大神&#xff01; 题目&#xff1a;KubeSphere 容器平台高可用&#xff1a;环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

19c补丁后oracle属主变化,导致不能识别磁盘组

补丁后服务器重启&#xff0c;数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后&#xff0c;存在与用户组权限相关的问题。具体表现为&#xff0c;Oracle 实例的运行用户&#xff08;oracle&#xff09;和集…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...

保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek

文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama&#xff08;有网络的电脑&#xff09;2.2.3 安装Ollama&#xff08;无网络的电脑&#xff09;2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲

文章目录 前言第一部分&#xff1a;体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分&#xff1a;体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...

嵌入式常见 CPU 架构

架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集&#xff0c;单周期执行&#xff1b;低功耗、CIP 独立外设&#xff1b;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel&#xff08;原始…...

WPF八大法则:告别模态窗口卡顿

⚙️ 核心问题&#xff1a;阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程&#xff0c;导致后续逻辑无法执行&#xff1a; var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题&#xff1a…...

算术操作符与类型转换:从基础到精通

目录 前言&#xff1a;从基础到实践——探索运算符与类型转换的奥秘 算术操作符超级详解 算术操作符&#xff1a;、-、*、/、% 赋值操作符&#xff1a;和复合赋值 单⽬操作符&#xff1a;、--、、- 前言&#xff1a;从基础到实践——探索运算符与类型转换的奥秘 在先前的文…...

云原生时代的系统设计:架构转型的战略支点

&#x1f4dd;个人主页&#x1f339;&#xff1a;一ge科研小菜鸡-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 一、云原生的崛起&#xff1a;技术趋势与现实需求的交汇 随着企业业务的互联网化、全球化、智能化持续加深&#xff0c;传统的 I…...

CentOS 7.9安装Nginx1.24.0时报 checking for LuaJIT 2.x ... not found

Nginx1.24编译时&#xff0c;报LuaJIT2.x错误&#xff0c; configuring additional modules adding module in /www/server/nginx/src/ngx_devel_kit ngx_devel_kit was configured adding module in /www/server/nginx/src/lua_nginx_module checking for LuaJIT 2.x ... not…...