Avalonia11如何优雅的跨组件通信

news2024/11/8 8:55:35

背景:

官网只介绍了推荐适用ReactiveUI,没有过多的案例介绍,对于初入桌面应用开发的小白极其不友好。

本文介绍在Avalonia应用中通过ReactiveUI中的MessageBus进行跨组件通信.

假设需求案例:

MainWindowViewModel中发送消息,AnotherViewModel中接收MainWindowViewModel发送的消息。

安装依赖:

Avalonia.ReactiveUI

Microsoft.Extensions.DependencyInjection(DI依赖注入,非此案例必须)

实现思路:

  1. 使用MessageBus.SendMessage()发送消息;
  2. 需要接收消息的组件使用MessageBus.Listen()订阅消息;

关键代码:

  1. 在App.axaml.cs中注入MessageBus(使用DI);
private IServiceProvider _serviceProvider;
public override void Initialize()
{
    AvaloniaXamlLoader.Load(this);
    // 初始化 ReactiveUI
    RxApp.MainThreadScheduler = AvaloniaScheduler.Instance;
}

public override void OnFrameworkInitializationCompleted()
{
    ConfigureServices();
    if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
    {
        // Line below is needed to remove Avalonia data validation.
        // Without this line you will get duplicate validations from both Avalonia and CT
        BindingPlugins.DataValidators.RemoveAt(0);
        desktop.MainWindow = _serviceProvider.GetRequiredService<MainWindow>();
    }

    base.OnFrameworkInitializationCompleted();
}
private void ConfigureServices()
{
    var services = new ServiceCollection();

    // 注册 MessageBus 为 Singleton
    services.AddSingleton(MessageBus.Current);


    // 注册 ViewModel 为 Transient
    services.AddTransient<MainWindowViewModel>();
    services.AddTransient<AnotherViewModel>();
    // 注册 MainWindow
    services.AddTransient<MainWindow>();

    _serviceProvider = services.BuildServiceProvider();
}
  1. MainWindow.axaml中实例化AnotherViewModel,初始化是为了创建订阅信息监听
// 实例化 AnotherViewModel
_anotherViewModel = serviceProvider.GetRequiredService<AnotherViewModel>();
  1. 添加Send Message按钮测试;
<Button Content="Send Message" Command="{Binding SendTestMessageCommand}" />


public partial class MainWindowViewModel : ViewModelBase
{

    private readonly IMessageBus _messageBus;

    public ReactiveCommand<Unit, Unit> SendTestMessageCommand { get; }

    public MainWindowViewModel(IMessageBus messageBus)
    {
        _messageBus = messageBus;
        SendTestMessageCommand = ReactiveCommand.Create(SendTestMessage);

    }


    public void SendTestMessage()
    {
        var message = new TestMessage { Content = "Hello from MainViewModel" };
        _messageBus.SendMessage(message);
    }
}

4、在AnotherViewModel中订阅消息

private readonly IMessageBus _messageBus;
public AnotherViewModel(IMessageBus messageBus)
{
    _messageBus = messageBus;
    // 订阅消息
    _messageBus.Listen<TestMessage>()
        //.ObserveOn(RxApp.MainThreadScheduler)
        .Subscribe(Observer.Create<TestMessage>(HandleMessage));
}

private void HandleMessage(TestMessage message)
{
    // 处理接收到的消息
    Debug.WriteLine($"Message received in AnotherViewModel: {message.Content}");
    // 如果需要更新 UI,确保在主线程上执行
    Dispatcher.UIThread.InvokeAsync(() =>
    {
        // 这里可以执行 UI 更新操作
    });
}

5、运行测试结果

深潜

如果不使用ReactiveUI的MessageBus,还有什么什么实现方式?

1、通过构造函数注入,如果组件层级深,此方法会使代码耦合性极大增加,建议不超过3级;

2、使用ReactiveUI中ReactiveObject,使用RaiseAndSetIfChanged(),变化后通知;

3、使用ReactiveUI中的ReactiveList<T>处理集合变化,监听change和ItemChange事件;

4、使用.Net中的ObservableCollection<T>配合ReactiveUI的this.WhenAnyValue().BindTo().Subscrble().DisposeWith()使用,个人理解等同于ReactiveList<T>。

总结:

  1. 使用MessageBus可解耦,省去中间传参处理参数环节且在ReactiveUI中开箱即用,较推荐使用。
  2. 对于非ReativeUI的MVVM项目可以使用.Net中的ObservableCollection<T>;
  3. 层级简单较容易实现的,根据实际情况出发,非必要引入消息总线。
  4. 关于Avalonia+ReactiveUI开发,是在使用中探索,加之网上开发相关资料并不丰富,特此分享,欢迎指正!!!

本文完。

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

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

相关文章

【开发实战】彻底了解 ThreadLocal

👉博主介绍: 博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家,WEB架构师,阿里云专家博主,华为云云享专家,51CTO 专家博主 ⛪️ 个人社区:个人社区 💞 个人主页:个人主页 🙉 专栏地址: ✅ Java 中级 🙉八股文专题:剑指大厂,手撕 J…

基于开源 AI 智能名片、S2B2C 商城小程序的用户获取成本优化分析

摘要&#xff1a;本文围绕用户获取成本&#xff08;CAC&#xff09;这一关键指标展开深入剖析&#xff0c;详细阐述其计算方式&#xff0c;并紧密结合开源 AI 智能名片与 S2B2C 商城小程序的独特性质&#xff0c;从多个维度探讨如何通过挖掘新的获客渠道、巧妙运用私域流量池等…

KV260 - PYNQ 主目录 - U盘挂载

目录 1. 简介 2. 具体操作 2.1 查看 USB 设备 2.2 查看 U 盘设备节点 2.3 挂载 U 盘到指定目录 2.4 查看挂载状态 2.5 卸载 U 盘 3. 总结 1. 简介 在 KV260 使用 Jupyter Lab 可以非常方便开发各种应用。有时不方便在 PC 端连接 U 盘&#xff0c;那么可以把 U 盘连在 …

金媒婚恋相亲系统10.4择爱开源旗舰版支持微信小程和抖音小程序上架

最近大家应该注意到了&#xff0c;金媒婚恋相亲系统已经更新至最新的10.4版本了&#xff01;本人作为商业用户也已经更新至最新的旗舰版了&#xff0c;更新的内容是啥&#xff01;这个官方都有列出&#xff0c;一个方面就是更新了多端的登录逻辑和UI 和后台CRM及很多细节的优化…

用环形数组实现队列(多种高级方法,由浅入深)

同普通数组实现的队列相比&#xff0c;普通数组的头结点和尾节点都是固定的&#xff0c;在进行移除的时候如果移除了一个节点&#xff0c;后面所有节点都需要进行移除操作&#xff0c;需要的时间复杂度更高 在环形数组中&#xff0c;确定了头尾指针的环形数组很好地解决了这一…

【毫米波雷达(七)】自动驾驶汽车中的精准定位——RTK定位技术

一、什么是RTK&#xff1f; RTK&#xff0c;英文全名叫做Real-time kinematic&#xff0c;也就是实时动态。这是一个简称&#xff0c;全称其实应该是RTK&#xff08;Real-time kinematic&#xff0c;实时动态&#xff09;载波相位差分技术。 二、RTK的组装 如上图所示&#x…

小北的字节跳动青训营与调用模型:调用模型:OpenAI API vs 微调开源Llama2/ChatGLM(持续更新中~~~)

前言 最近&#xff0c;字节跳动的青训营再次扬帆起航&#xff0c;作为第二次参与其中的小北&#xff0c;深感荣幸能借此机会为那些尚未了解青训营的友友们带来一些详细介绍。青训营不仅是一个技术学习与成长的摇篮&#xff0c;更是一个连接未来与梦想的桥梁~ 小北的青训营 X M…

通过DNS服务器架构解释DNS请求过程

在前面的章节&#xff0c;这里&#xff0c;基于PCAP数据包和RFC文档详细介绍了DNS请求和响应的每个字段的含义。但是在现实的网络世界中&#xff0c;DNS请求和响应的数据包是怎么流动的&#xff0c;会经过哪些设备。本文将着重说明一下目前网络空间中DNS请求和响应的流动过程。…

Netty实现WebSocket Server是否开启压缩深度分析

是否开启压缩会直接影响与客户端是否能够成功握手。 一、具体分析 通常客户端发起与Websocket连接一般是以下形式。 1&#xff09;包含6个必要的Header Request Headers Sec-WebSocket-Version: 13 Sec-WebSocket-Key: Nlpc0kiHFjRom5/62lj8bA Connection: Upgrade Upgrade…

IntelliJ IDEA 2023.2——配置说明

IntelliJ IDEA 2023.2——配置说明 IntelliJ IDEA 的官方下载地址 IntelliJ IDEA 官网下载地址 一路上NEXT 到结尾&#xff1a; 继续NEXT 下一步: 界面如下图所示 界面如下图所示 ctrl F 查找 “码猿趣事” 查找【idea99】

算法通关(4)-- 前缀树

前缀数原理和代码 原理 前缀树&#xff08;Trie树&#xff09;&#xff0c;也称为字典树&#xff0c;是一种用于高效存储和检索字符串的数据结构。它是一种树形结构&#xff0c;能够利用字符串的公共前缀来减少存储空间和查询时间。 现在有“acb”,"cba","ac…

【CSS】“flex: 1“有什么用?

flex 属性的组成 flex 属性是一个复合属性&#xff0c;包含以下三个子属性&#xff1a; flex-grow&#xff1a;决定元素在容器中剩余空间的分配比例。默认值为 0&#xff0c;表示元素不会扩展。当设置为正数时&#xff0c;元素会按照设定比例扩展。flex-shrink&#xff1a;决…

【dvwa靶场:XSS系列】XSS (Stored)低-中-高级别,通关啦

更改name的文本数量限制大小&#xff0c; 其他我们只在name中进行操作 【除了低级可以在message中进行操作】 一、低级low <script>alert("假客套")</script> 二、中级middle 过滤了小写&#xff0c;咱们可以大写 <Script>alert("假客套…

大数据-212 数据挖掘 机器学习理论 - 无监督学习算法 KMeans 基本原理 簇内误差平方和

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

神经网络基础--什么是正向传播??什么是方向传播??

前言 本专栏更新神经网络的一些基础知识&#xff1b;这个是本人初学神经网络做的笔记&#xff0c;仅仅堆正向传播、方向传播就行了了一个讲解&#xff0c;更加系统的讲解&#xff0c;本人后面会更新《李沐动手学习深度学习》&#xff0c;会更有详细讲解;案例代码基于pytorch&a…

【大模型系列】Grounded-VideoLLM(2024.10)

Paper&#xff1a;https://arxiv.org/pdf/2410.03290Github&#xff1a;https://github.com/WHB139426/Grounded-Video-LLMHuggingface&#xff1a;https://huggingface.co/WHB139426/Grounded-Video-LLMAuthor&#xff1a;Haibo Wang et al. 加州大学&#xff0c;复旦 动机&a…

IDEA2024下安装kubernetes插件并配置进行使用

【1】安装插件 其实2024.2.3下默认已经安装了kubernetes插件&#xff0c;如果你发现自己IDEA中没有&#xff0c;在市场里面检索并下载即可。 【2】kubernetes配置 ① 前置工作 首先你要准备一个config文件和一个kubectl.exe 。 config文件类似如下&#xff1a; apiVersi…

onnx-web + yolov8n 在视频流里做推理

顺着我上一篇文章 使用onnxruntime-web 运行yolov8-nano推理 继续说&#xff0c;有朋友在问能不能接入 视频流动&#xff0c;实时去识别物品。 首先使用 getUserMedia 获取摄像头视频流 getUserMedia API 可以访问设备的摄像头和麦克风。你可以使用这个 API 获取视频流&#…

Python练习11

Python日常练习 题目&#xff1a; 编写一个石头剪刀布游戏&#xff0c;该程序要求完成如下功能&#xff1a; (1) 显示游戏规则&#xff0c;提醒用户输入一个1-3的整数或者直接回车。 用户输入回车时游戏结束。 用户输入不合法&#xff08;包括输入的…

航展畅想:从F35机载软件研发来看汽车车载软件研发

两款经典战机的机载软件 F-22和F-35战斗机的研制分别始于1980年代和1990年代末&#xff0c;F-22项目在1981年启动&#xff0c;主要由洛克希德马丁&#xff08;Lockheed Martin&#xff09;和波音公司&#xff08;Boeing&#xff09;合作开发&#xff0c;以满足美军“先进战术战…