• WPF 组件间通信 MVVM 进行解耦


    假设有这样一个需求,有这样一个聊天界面,主界面是选项卡,其一选项卡内部是真正的聊天列表和聊天界面,我们需要实时的在主界面显示未读消息的数量

    假设我们已经有方法可以拿到未读消息的数量,那么如何在主界面的选项卡上面进行显示呢,如钉钉

     第一,我们可以很暴力的直接在子控件的viewmodel或者后台代码中拿到主界面中绑定的一个属性值,直接进行修改。这种方法很简单,很方便,但是在程序内部无疑增加了耦合度

    刚毕业或工作一年的这样写我觉得可以,但是如果你是个有程序洁癖并且有了一定工作经验的程序员的话,你肯定很不爽。你可能会去百度看看别人是如何做的,其实你也很容易就能得到一些方案,比如MVVMLight自带的通信机制就是很好的选择,但是它很重,如果你的MVVM不是使用的它的话,那你为了这点功能而且选择使用它,其实很浪费,并且它的通信功能很强大,如果你的需求仅仅和文章开头差不多或者稍微复杂点则完全没必要。

    第二,我们则自己尝试制作这样一个消息通信中心。

    思考几分钟,首先,观察者模式充斥着我们的桌面开发中,利用发布/订阅这种模式,显示最合理也最简单,在面向事件开发中,订阅事件,将我们的动作绑定到事件上,触发事件同时调用我们的动作,则整个过程也顺利完成。

    1.完成带有消息存储和发布/订阅的事件处理中心

    我们使用键值对将我们的消息和事件进行绑定,并且完成发布/订阅两个方法,这里的方法会对所有订阅者进行发布,如果需要分组,过滤,多次执行等操作,可以重写该类及发布订阅方法。

    public class Messager
        {
            /// <summary>
            /// 消息集合
            /// </summary>
            private IDictionary<string, MessagerInvokeHandler> Messagers = 
                new Dictionary<string, MessagerInvokeHandler>();
    
            private Messager() { }
    
            private static Messager _message;
    
            public static Messager Default => _message??(_message=new Messager());
    
            /// <summary>
            /// 订阅
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="topic"></param>
            /// <param name="t"></param>
            public virtual void Register<T>(string topic,Action<MessagerContext> t) 
            {
                if (t == null)
                    throw new ArgumentException();
                if (Messagers.ContainsKey(topic))
                {
                    var value=Messagers.FirstOrDefault(o => o.Key == topic).Value;
                    value.MessagerInvokeEvent += t;
                    return;
                }
                var invoker=new MessagerInvokeHandler();
                invoker.MessagerInvokeEvent += t;
                Messagers.Add(topic, invoker);
            }
    
            /// <summary>
            /// 发布
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="topic"></param>
            /// <param name="element"></param>
            public virtual void Send<T>(string topic, T element) 
            {
                if (!Messagers.ContainsKey(topic))
                    return;
                var invoker = Messagers.FirstOrDefault(o => o.Key == topic).Value;
                invoker.Invoke(new MessagerContext() 
                {
                    Data=element,
                    Topic=topic
                });
            }
        }

    2.发布消息时的事件处理类

    包含一个事件用来绑定订阅的操作,以及一个方法执行事件

    /// <summary>
            /// 消息执行类
            /// </summary>
            public class MessagerInvokeHandler
            {
                public event Action<MessagerContext> MessagerInvokeEvent;
    
                public void Invoke(MessagerContext context) 
                {
                    MessagerInvokeEvent.Invoke(context);
                }
            }

    3.消息调用时的上下文参数

    这边大家可以根据自己的需求自行增加修改

    public class MessagerContext
        {
            /// <summary>
            /// 消息体
            /// </summary>
            public object Data { get; set; }
    
            /// <summary>
            /// 主题
            /// </summary>
            public string Topic { get; set; }
        }

    如何使用?

    订阅

    //注册修改单个消息的通知
                Messager.Default.Register<Int32>(MessagerTopic.ModifySingleCount, ModifySingleCount);
    
           private void ModifySingleCount(MessagerContext context) 
              {
                  。。。。
              }

    发布

    Messager.Default.Send<Int32>(MessagerTopic.ModifySingleCount,10);

    我已经在项目中使用该方法了,但是又缺陷就是设计问题,导致上下文没有使用泛型,data只能用object类型接收,有任何问题欢迎指正!

  • 相关阅读:
    invalid expression: missing ) after argument list in xxx 或者 console.error(("[Vue warn]: " + msg + trace));
    js的alert()
    第9节列表渲染
    第8节条件渲染
    第7节class与style绑定
    CF1215D Ticket Game 博弈论
    CF833A The Meaningless Game 思维
    蚯蚓 队列
    洛谷P2566[SCOI2009]围豆豆
    ants 思维
  • 原文地址:https://www.cnblogs.com/qwqwQAQ/p/13209035.html
Copyright © 2020-2023  润新知