为 MVVM 用户控件和应用程序实现一个简单的 Messenger

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 63w+ 字,讲解图 2808+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2200+ 小伙伴加入学习 ,欢迎点击围观

用户控件很棒。您将一个易于使用(最好的情况下)的组件放在一起,以便在您的项目中重用。有时,您甚至将该控件放入(可移植的)类库中以使其跨平台可用。大多数用户控件都是在没有 MVVM 的情况下编写的,仅使用 DependencyProperties 和匹配的代码隐藏文件。

但是 – 可以创建一个带有自己的 ViewModel 的用户控件,只保留代码中的 DependencyProperties。对于由控件视图生成的值,存在一些限制。如果不创建对它的引用,就无法将它们放入 ViewModel(在某些人看来这可能会破坏 MVVM 模式)。好吧,有些人会争辩说“谁在乎,我需要让它工作,所以我得到了对 DataContext 的引用。”这没关系,但在我看来还有另一个更优雅的解决方案。一个监听那些的类更改值,将它们拉入您的 ViewModel——所谓的信使。

你们中的一些人可能使用过 MVVMLight、Prism 或类似的框架/工具包。如果你想在类库中使用它们,你会发现一些障碍,比如缺少 ViewModelLocator 等等。在工作中,我正在为我们的 LOB 应用程序开发通用用户控件。由于该控件涉及其视图中的许多值,因此我需要一种智能且快速的方法来将这些值放入我的 ViewModel 中。我用我自己的简单信使实现了它,使我能够避免我控制的任何框架/工具包。

我是这样做的。首先我创建了一个新的 Singleton 类 。如果您不知道单例是什么,只需单击前面句子中的链接即可。长话短说:Singleton 使类成为静态的,并确保所有其他类都在使用一个实例(以最终获得正确的值)。提示:可能由于时机不对,您仍然有多个实例。在这种情况下,您应该查看对 Singleton 实例的调用的不同实现方式。

在我的例子中,我使用的是简单的实现,如果没有,它会自动创建第一个实例:


 public class SimpleMessenger
    {
        private static SimpleMessenger _instance;
    public static SimpleMessenger Instance => _instance ?? (_instance = new SimpleMessenger());
 }

下一步是创建一个 EventHandler,它会在 SimpleMessenger 有新值时通知我们。创建您自己的 EventArgs 以传递给 EventHandler 是绝对有意义的。只需收集您想要在派生自 EventArgs 的类中提供的数据,并使 EventHandler 使用此类作为其事件数据:


 public class SimpleMessenger
    {
        private static SimpleMessenger _instance;
    public static SimpleMessenger Instance => _instance ?? (_instance = new SimpleMessenger());
 }

此类中最重要的功能是引发事件:


 public class SimpleMessenger
    {
        private static SimpleMessenger _instance;
    public static SimpleMessenger Instance => _instance ?? (_instance = new SimpleMessenger());
 }

我只使用了三个所需的基本值:更改的属性的名称、旧值和更新后的值。这已经使我能够在 View 和 ViewModel 之间发送数据,甚至可以发送到我无法控制的范围内。当然,您想了解如何使用我的 SimpleMessenger 发送“消息”。这也很简单。

首先,您需要获取对当前实例的引用:


 public class SimpleMessenger
    {
        private static SimpleMessenger _instance;
    public static SimpleMessenger Instance => _instance ?? (_instance = new SimpleMessenger());
 }

要发送数据,只需使用 RaiseMessageValueChanged 事件:


 public class SimpleMessenger
    {
        private static SimpleMessenger _instance;
    public static SimpleMessenger Instance => _instance ?? (_instance = new SimpleMessenger());
 }

最后但同样重要的是,我们还可以在其他地方读取这些值:


 public class SimpleMessenger
    {
        private static SimpleMessenger _instance;
    public static SimpleMessenger Instance => _instance ?? (_instance = new SimpleMessenger());
 }

如您所见,使用此类以解耦方式获取值很简单(就像 MVVM 模式所要求的那样)。当然,您仍然需要注意不要过度使用它。例如,我正在使用它来获取我的控件在 ViewModel 中具有的 DependencyProperties 的更改值(否则只能通过引用它才能实现)。

这个 SimpleMessenger 可能不如流行的框架/工具包中的功能强大,但对于在用户控件或小型应用程序中使用它应该非常适合。我附上了一个非常简单的项目来演示 SimpleMessenger。只需启动项目,然后使用鼠标调整应用程序窗口的大小。它会将根网格的大小写入控制台。

下载示例

一如既往,我希望这篇文章对你们中的一些人有所帮助。

相关文章