首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

如何使用多虚拟机模式通知所有ViewModels一个ViewModel在模型类的属性中所做的更改

在软件开发中,特别是在使用MVVM(Model-View-ViewModel)架构的应用程序中,确保当模型类的属性发生变化时,所有的ViewModels都能得到通知是一个常见的需求。这通常涉及到实现一种机制,使得当模型的状态改变时,能够触发一个事件,所有的ViewModels都能够监听这个事件并作出相应的反应。

基础概念

观察者模式(Observer Pattern):这是一种设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。当主题对象的状态发生变化时,它会通知所有观察者对象,使它们能够自动更新。

INotifyPropertyChanged接口:在.NET框架中,这是一个接口,用于实现属性更改通知。当一个对象的公共属性值更改时,它可以触发一个PropertyChanged事件。

相关优势

  • 解耦:观察者模式允许对象之间保持松耦合,因为主题对象不需要知道观察者的具体实现。
  • 可扩展性:可以轻松添加新的观察者,而不需要修改现有的代码。
  • 实时更新:当模型发生变化时,所有相关的视图模型都会立即得到通知并更新。

类型

  • 推模型(Push Model):主题对象在状态改变时主动推送更新给观察者。
  • 拉模型(Pull Model):观察者在收到通知后,根据需要从主题对象中拉取数据。

应用场景

  • UI更新:当数据模型中的数据发生变化时,自动更新用户界面。
  • 分布式系统:在分布式系统中,当一个节点的状态发生变化时,其他节点可以得到通知并进行相应的处理。

实现步骤

  1. 定义模型类:模型类需要实现INotifyPropertyChanged接口,并在属性的setter中触发PropertyChanged事件。
代码语言:txt
复制
public class Model : INotifyPropertyChanged
{
    private string _name;
    public string Name
    {
        get { return _name; }
        set
        {
            if (_name != value)
            {
                _name = value;
                OnPropertyChanged(nameof(Name));
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
  1. 创建ViewModels:ViewModels需要订阅模型的PropertyChanged事件。
代码语言:txt
复制
public class ViewModel
{
    private readonly Model _model;

    public ViewModel(Model model)
    {
        _model = model;
        _model.PropertyChanged += Model_PropertyChanged;
    }

    private void Model_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        // 处理属性变化
    }
}
  1. 多虚拟机模式下的通知:如果应用程序运行在多台虚拟机上,可以使用消息队列或者发布/订阅模式来跨虚拟机传递通知。
代码语言:txt
复制
// 假设使用了一个消息总线服务
public class MessageBus
{
    public event EventHandler<string> PropertyChanged;

    public void Publish(string propertyName)
    {
        PropertyChanged?.Invoke(this, propertyName);
    }
}

// 在模型中发布消息
public class Model : INotifyPropertyChanged
{
    private readonly MessageBus _messageBus;

    public Model(MessageBus messageBus)
    {
        _messageBus = messageBus;
    }

    private string _name;
    public string Name
    {
        get { return _name; }
        set
        {
            if (_name != value)
            {
                _name = value;
                OnPropertyChanged(nameof(Name));
                _messageBus.Publish(nameof(Name));
            }
        }
    }

    // ... 其他代码 ...
}

// 在ViewModels中订阅消息
public class ViewModel
{
    private readonly MessageBus _messageBus;

    public ViewModel(MessageBus messageBus)
    {
        _messageBus = messageBus;
        _messageBus.PropertyChanged += MessageBus_PropertyChanged;
    }

    private void MessageBus_PropertyChanged(object sender, string propertyName)
    {
        // 处理属性变化
    }
}

遇到的问题及解决方法

问题:如果多个ViewModels订阅了同一个模型的属性变化,但是只有部分ViewModels得到了通知。

原因:可能是由于事件订阅不正确或者在某些情况下事件没有被正确触发。

解决方法

  • 确保每个ViewModel都正确地订阅了模型的PropertyChanged事件。
  • 检查是否有异常处理阻止了事件的传播。
  • 使用调试工具跟踪事件的触发和处理过程。

通过上述方法,可以在多虚拟机模式下有效地通知所有ViewModels模型类属性的变化。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

C# WPF MVVM开发框架Caliburn.Micro 名称Transformer⑩①

使用名称Transformer NameTransformer是在Caliburn.Micro v1.1中引入的,它是ViewLocator和ViewModelLocator如何将类名映射到其伙伴角色的一个组成部分...可选择的 为了说明如何使用此方法,我们可以查看ViewLocator类添加的一个内置规则: NameTransformer.AddRule("Model$", string.Empty); 此转换规则查找终止...第一个参数中的“$”表示模式必须在源字符串的末尾匹配。如果“模型”存在于其他任何地方,则模式不匹配。...如果需要“交换”任何一个单独的组件,则可以使用单独的组件。 上面示例中的捕获组“后缀”对以“ViewModels”结尾的名称进行模式匹配。...使用此捕获组的主要原因是防止子字符串“ViewModels”在“basename”组中被捕获,在大多数情况下,这是字符串转换的一部分。

1.8K20

C# WPF MVVM开发框架Caliburn.Micro 关于Conventions⑧

v1.1的更改v1.1中我们完全更改了LocateForModelType函数的实现。现在,我们使用新的NameTransformer类的一个实例以及预先配置的基于RexEx的规则来进行名称映射。...另一个有趣的区别在于我们如何获得ViewModel本身的实例。由于ViewModels可能由接口或具体类注册,因此我们也尝试生成可能的接口名称。如果我们找到匹配项,我们将从IoC容器中解析它。...绑定完成后,视图被注入到定义属性的元素中。这是ViewModel的第一个使用模式。使用ViewModelBinder的第二个位置是Bind.Model attached属性的实现内部。...ElementConvention定义了一个ApplyBinding Func,它接受视图模型类型、属性路径、属性信息、元素实例和约定本身。此Func负责使用提供的所有上下文信息在元素上创建绑定。...但是,了解这些约定是什么以及在整个框架中如何使用它们是很重要的。在本文的最底部是一个代码列表,它显示了如何开箱即用地配置所有元素。

2.8K20
  • ViewModel 和 LiveData:为设计模式打 Call 还是唱反调?

    ❌ 不要让 ViewModel(或Presenter)直接使用 Android 框架内的类 条件语句、循环和一般的判定等语句应该在 ViewModel 或者应用程序的其他层中完成,而不是在 Activity...❌ 避免在 ViewModel 里持有视图层的引用 推荐使用观察者模式作为 ViewModel 层和 View 层的通信方式,可以使用 LiveData 或者其他库中的 Observable 对象作为被观察者...由于保持缓存和数据库与网络同步的算法通常很琐碎复杂,所以建议为每个仓库创建一个类作为处理同步的单一入口。 如果是许多种并且差别很大的数据模型,考虑使用多个数据仓库。...在示例中,我们继承 LiveData 创建一个叫做 SingleLiveEvent 的类来解决这个问题。它仅仅发送发生在订阅后的更新,要注意的是这个类只支持一个观察者。...ViewModel 如何与其他组件进行通信取决于你,但要注意泄漏问题和边界情况。看下面这个图,其中 Presenter 层使用观察者模式,数据层使用回调: ?

    3.1K30

    C# WPF MVVM开发框架Caliburn.Micro 自定义Conventions⑩

    换句话说,没有简单的方法可以在维护名称空间的标准转换的同时添加对自定义视图名称后缀的支持,也没有简单的方法可以在维护类型名称的标准转换的同时更改名称空间转换。...名称转换是一个通用术语,用于描述如何进行类型解析。类型的完全限定名作为源,然后“转换”为输出类型的名称。...在最低级别,NameTransformer类负责此操作,并使用基于正则表达式的“转换规则”执行转换。 类型映射是一个术语,用于描述添加到定位器类中的新功能。...请注意,按照惯例,无论此属性的值如何,如果视图后缀是ViewModel后缀的一部分,则假定忽略视图后缀(即CustomerViewModel而不是CustomerViewModel)。...(可选) 为了使多视图支持正常工作,ViewLocator需要跟踪应用程序可能使用的所有视图后缀。

    68720

    C# WPF MVVM开发框架Caliburn.Micro入门介绍①

    Micro对这些模式的实现是Caliburn中的模式的演变,支持执行任何类型的类,而不仅仅是IScreen的实现。这些改进正在重新引入Caliburn。...此外,通过在Xaml中附加View.Context,我们支持同一视图模型上的多个视图。...因此,给定与上面相同的模型,但使用View.Context=“Master”我们将搜索MyApplication.Views.Shell.Master。当然,所有这些都是可定制的。...Micro实现支持基于字符串和lambda的更改通知。它还确保在UI线程上引发所有事件。...您可以开始使用Caliburn.Micro进行开发,然后,如果您遇到边缘情况或有其他需要转移到Caliburn,您将能够在应用程序中进行少量更改或不进行任何更改。

    1.8K20

    C# WPF MVVM开发框架Caliburn.Micro Screens, Conductors 和 Composition⑦

    虽然这些模式主要通过从特定基类继承ViewModels来在CM中使用,但将它们视为角色而不是视图模型是很重要的。事实上,根据您的体系结构,屏幕可以是用户控件、演示者或视图模型。不过这有点超前了。...它添加了一个IsNotifying属性(可用于关闭/打开所有更改通知)、一个NotifyOfPropertyChange方法(可调用该方法引发属性更改)和一个Refresh方法(可用于刷新对象上的所有绑定...除了标准字符串机制之外,它还提供了一个基于lambda的NotifyOfPropertyChange方法,支持强类型更改通知。此外,所有属性更改事件都会自动封送到UI线程。...这个适配器是由PhoneBootstrapper设置的,它理解导体所做的相同的细粒度生命周期接口,并确保在导航过程中在适当的时候在ViewModels上调用它们。...之前,我们在Caliburn.Micro中讨论了屏幕和导体的理论和基本API。现在,我将介绍几个示例中的第一个。此特定示例演示如何使用导体和两个“页面”视图模型设置一个简单的导航样式shell。

    2.6K20

    使用 Architecture Component 实现 MVVM 的正确姿势

    一、MVVM 之初体验 网上关于 MVVM 的介绍非常多,这里不再赘述,直接看一个例子,用直观的代码来感受一下用 MVVM 开发,是一种什么样的感受 class MvvmViewModel : ViewModel...这里使用 LiveData 和 ViewModel 实现了一个简单的 MVVM:数据的变化能够自动通知 View 然后做出相应的 UI 改变,并且能在 Activity 生命周期结束前停止监听 二、认识...,ViewModel 的生命周期是比 Activity 长的,因此我们不应该在 ViewModel 中持有 View 或者任何和 Activity context 引用关系的类,否则会引发内存泄露的风险...参考官博:ViewModel 和 LiveData 的模式和反模式 image.png 各层之间的职责边界 ViewModel 中的 LiveData 是提供给 View 监听的,View 应该只需要关系...,逻辑代码应该在 ViewModel 中处理好再通知 View 直接更新 UI,View 只需要关系如何更新 UI 以及把用户的交互事件发送给 ViewModel 即可,这种模式叫做 Passive View

    78820

    ViewModel:持久化、onSaveInstanceState()、UI 状态恢复和 Loader

    我在上篇博文中用新的 ViewModel 类开发了一个简单的用例来保存配置更改过程中的篮球分数。ViewModel 被设计用来以与生命周期相关的方式保存和管理 UI 相关的数据。...译者:Feximin 介绍 我在上篇博文中用新的 ViewModel 类开发了一个简单的用例来保存配置更改过程中的篮球分数。...简而言之,对,ViewModel 结合其他几个类可以代替 Loader 使用。 图模型是否对数据进行了持久化? 简而言之,没有。 还像平常那样去持久化。...Room 确保你的数据库更新时,LiveData 被通知到。 由于 Loader 在 UI 控制器中作为回调被实现,因此 ViewModel 的一个额外优点是将 UI 控制器与数据加载分离开来。...一些使用 ViewModels 、LiveData 为加载数据的方法: 在这篇文章中,Ian Lake 概述了如何使用 ViewModel 和 LiveData 来代替 AsyncTaskLoader。

    1K20

    ViewModels and LiveData- Patterns + AntiPatterns

    ❌ 不要让ViewModels(和Presenters)知道Android框架类的情况 条件语句、循环和一般决策应该在ViewModels或应用程序的其他层中完成,而不是在Activities或Fragments...视图通常没有单元测试(除非你使用Robolectric),所以代码行数越少越好。视图应该只知道如何显示数据并将用户事件发送到ViewModel(或Presenter)。这就是所谓的被动视图模式。...✅将Activity和Fragment中的逻辑保持在最低限度 View references in ViewModels 视图模型与Activity或Fragment有不同的作用域。...在ViewModels和View之间进行通信的推荐方式是观察者模式,使用LiveData或来自其他库的观察变量方式。...建议有一个单独的存储库类作为处理这种复杂性的单一入口。 如果你有多个非常不同的数据模型,可以考虑添加多个存储库。

    1.1K30

    ViewModel:持久化、onSaveInstanceState()、UI 状态恢复和 Loader

    译文出自:掘金翻译计划 本文永久链接:github.com/xitu/gold-m… 译者:Feximin 介绍 我在上篇博文中用新的 ViewModel 类开发了一个简单的用例来保存配置更改过程中的篮球分数...简而言之,对,ViewModel 结合其他几个类可以代替 Loader 使用。 图模型是否对数据进行了持久化? 简而言之,没有。 还像平常那样去持久化。...Room 确保你的数据库更新时,LiveData 被通知到。 ? 由于 Loader 在 UI 控制器中作为回调被实现,因此 ViewModel 的一个额外优点是将 UI 控制器与数据加载分离开来。...一些使用 ViewModels 、LiveData 为加载数据的方法: 在这篇文章中,Ian Lake 概述了如何使用 ViewModel 和 LiveData 来代替 AsyncTaskLoader。...随着代码变得越来越复杂,你可以考虑在一个单独的类里进行实际的数据加载。一个 ViewModel 类的目的是为 UI 控制器持有数据。

    3.8K30

    Android面试题之Kotlin Jetpack的三大核心组件

    ViewModel 和 LiveData 是 Android Jetpack 组件库中的两个核心组件,它们能帮助开发者更有效地管理 UI 相关的数据,并且能够在配置变更(如屏幕旋转)时保存和恢复 UI...用于ViewModel数据返回时通知View更新,是ViewModel和View之间的桥梁 那么如何在 Kotlin 中正确优雅地使用 ViewModel 和 LiveData 呢。...创建一个继承自 ViewModel 的类: import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import...在 Fragment 中使用 ViewModel 如果在 Fragment 中使用 ViewModel,可以使用 viewModels 或 activityViewModels: import android.os.Bundle...Lifecycle Jetpack 组件中的 Lifecycle 是一个用于管理和观察 Android 组件(如 Activity、Fragment)生命周期的库。

    19710

    已中招!Android 基础面试常常吊死在这几个问题上……

    3、面试官:为什么字节码不能在Android中运行? 应聘者:Android 使用的是 DVM ( Dalvik 虚拟机)而不是 JVM ( Java 虚拟机)。 面试官:不错,答上来了!...BuildType 定义了 Gradle 在构建和打包 Android 应用时使用的属性。...应聘者:使用 ViewModels 和的组合 onSaveInstanceState() , ViewModel 具有 LifeCycle-Aware 的功能。...换句话说,如果 ViewModel 的所有者因配置更改(例如,旋转)而被销毁,则不会销毁它。所有者的新实例将重新连接到现有的 ViewModel 。...通常的做法是将数据存储在 ViewModel 类中(因为它在配置更改期间保留数据),并使用 OnSaveInstanceState 存储少量UI数据。 面试官:回答得不错!

    2K20

    「Android 架构」—— MVVM 详解

    它只负责显示一些东西在屏幕上(比如从 ViewModels 拿到的一些数据),执行 Android 特定操作并将用户交互事件(点击、滑动等)发送到各自的 ViewModel。...当你查看上面的架构模型图时,你可能想知道 View 如何获取它应该显示的所有数据。如图,箭头仅指向一个方向 -> ViewModel。...当数据发生变化时,所有观察它的 View 都将收到相应的更改通知(onChange() 被回调)。 ?...Model Model 就是你放置所有特定业务代码的地方,虽然从技术上讲,ViewModel 和 Model 之间存在一个以 Repository 形式存在的中间步骤,你可以将 Repository 中的所有内容视为远离用户界面的一组类...总结 在这篇文章中,你了解了MVVM架构模式背后的概念。现在您已经掌握了基础知识,快开始使用这种模式构建一个真正的应用程序吧?

    1.9K40

    Android MVVM框架搭建(一)ViewModel + LiveData + DataBinding

    从Google的官方说明来看,ViewModel 类旨在以注重生命周期的方式存储和管理界面相关的数据。ViewModel 类让数据可在发生屏幕旋转等配置更改后继续留存。...① 绑定Activity 在MVVM的框架中,每一个Activity都应该对应一个ViewModel,而现在我们有一个MainActivity,因此可以新建一个viewmodels包,包下新建一个MainViewModel...layout标签,然后将原来的布局放在layout里面,再增加一个数据源,也就是user对象,然后再底部的两个tv_account和tv_pwd两个TextView中的text属性中绑定了user对象中的属性值...下面运行一下: ② 双向绑定   双向绑定是建立在单向绑定的基础上,实际的开发中用到双向绑定的地方并没有单向绑定多,双向绑定举一个例子,在输入框输入数据时候直接将数据源中的数据进行改变,这里会用到...,某一个对象都会通知,现在notifyPropertyChanged()就具有针对性,只通知对应属性改变。

    17K97

    Android MVVM框架搭建(一)ViewModel + LiveData + DataBinding

    同时还与View 存在一定的耦合,可以通过观察者模式通知 View 状态的改变来让view 更新。   ...从Google的官方说明来看,ViewModel 类旨在以注重生命周期的方式存储和管理界面相关的数据。ViewModel 类让数据可在发生屏幕旋转等配置更改后继续留存。...① 绑定Activity 在MVVM的框架中,每一个Activity都应该对应一个ViewModel,而现在我们有一个MainActivity,因此可以新建一个viewmodels包,包下新建一个MainViewModel...下面运行一下: ② 双向绑定   双向绑定是建立在单向绑定的基础上,实际的开发中用到双向绑定的地方并没有单向绑定多,双向绑定举一个例子,在输入框输入数据时候直接将数据源中的数据进行改变,这里会用到...,某一个对象都会通知,现在notifyPropertyChanged()就具有针对性,只通知对应属性改变。

    2.7K32

    Android 面试题:为什么 Activity 都重建了 ViewModel 还存在?—— Jetpack 系列(3)

    ViewModel 的作用可以区分 2 个维度来理解: 1、界面控制器维度: 在最初的 MVC 模式中,Activity / Fragment 中承担的职责过重,因此,在后续的 UI 开发模式中,我们选择将...Activity / Fragment 中与视图无关的职责抽离出来,在 MVP 模式中叫作 Presenter,在 MVVM 模式中叫作 ViewModel。...MVVM 模式示意图: MVI 模式示意图: ViewModel 生命周期示意图: 1.2 ViewModel 的使用方法 1、添加依赖: 在 build.gradle 中添加 ViewModel...正因为同一个 ViewModel 宿主使用的是同一个 ViewModelStore 映射表,因此在同一个宿主上重复调用 ViewModelProvider#get() 返回同一个 ViewModel 实例...例如: 方法 1: 在 ViewModel#onCleared() 中通知数据层丢弃对 ViewModel 回调监听器的引用; 方法 2: 在数据层使用对 ViewModel 回调监听器的弱引用(这要求

    1.2K20

    跨平台开发框架 MvvmCross 初体验

    跨平台开发框架 MvvmCross 初体验 MvvmCross 的特点 尽量使用可移植类库进行编码, 可以包括 视图模型 (ViewModel) 、 模型 (Model) 、 服务 (Service)...甚至界面 (View) 使用 MVVM 模式和数据绑定 (Data Binding) 技术 使用目标平台的本地化界面 框架的任何部分都可以被重写 准备使用 MvvmCross 推荐的方式是建立自己的 git...使用 MvvmCross 创建跨平台应用 MvvmCross 应用至少包含两个项目, 一个是基于 PCL 的 Core 项目, 包含所有的视图模型、 服务以及应用程序逻辑代码; 一个是目标平台的界面项目...MvvmCross Core 项目必须包含一个 App 类, 继承自 MvxApplication , 负责 ViewModel 和逻辑代码的启动, 代码如下: using FirstMvxApp.ViewModels...添加一个 Setup 类, 负责 MvvmCross 在 iOS 应用中的启动, 代码如下: using Cirrious.MvvmCross.Touch.Platform; using MonoTouch.UIKit

    1.3K30
    领券