zoukankan      html  css  js  c++  java
  • Messenger在MVVM模式中的应用

    Messenger在MVVM模式中的应用

    Messenger在MVVM中应用的前提

        我们知道在MVVM架构中,系统平台的Silverlight客户端界面开发和业务逻辑已经被分开,XAML是SL的主要部分,界面设计者只需要绑定ViewModel里的数据即可。但是在ViewModel里有些时候是需要界面发出响应的,在这种情况下,Messenger显示出它的用处。

    Messenger的架构

     

    Messager构件代码

    定义Imessager接口

    注册一个接收消息的类型,比如某一控件来接收消息

      void Register<TMessage>(object recipient, Action<TMessage> action);

    给最近注册的类型发送消息

      void Send<TMessage, TTarget>(TMessage message);

    取消最近注册的类型,当执行该句后,不再接收任何消息

      void Unregister(object recipient);

    实现Imessager接口

      public class Messenger : IMessenger

        {

            private static Messenger _defaultInstance;

     

            private Dictionary<Type, List<WeakActionAndToken>> _recipientsOfSubclassesAction;

     

            private Dictionary<Type, List<WeakActionAndToken>> _recipientsStrictAction;

     

      

            public static Messenger Default

            {

                get

                {

                    if (_defaultInstance == null)

                    {

                        _defaultInstance = new Messenger();

                    }

     

                    return _defaultInstance;

                }

            }

     

       

            public static void OverrideDefault(Messenger newMessenger)

            {

                _defaultInstance = newMessenger;

            }

     

       

            public static void Reset()

            {

                _defaultInstance = null;

            }

     

         

            public virtual void Register<TMessage>(object recipient, Action<TMessage> action)

            {

                Register(recipient, null, false, action);

            }

     

      

            public virtual void Register<TMessage>(object recipient, bool receiveDerivedMessagesToo, Action<TMessage> action)

            {

                Register(recipient, null, receiveDerivedMessagesToo, action);

            }

     

        

            public virtual void Register<TMessage>(object recipient, object token, Action<TMessage> action)

            {

                Register(recipient, token, false, action);

            }

     

         

            public virtual void Register<TMessage>(

                object recipient,

                object token,

                bool receiveDerivedMessagesToo,

                Action<TMessage> action)

            {

                var messageType = typeof(TMessage);

     

                Dictionary<Type, List<WeakActionAndToken>> recipients;

     

                if (receiveDerivedMessagesToo)

                {

                    if (_recipientsOfSubclassesAction == null)

                    {

                        _recipientsOfSubclassesAction = new Dictionary<Type, List<WeakActionAndToken>>();

                    }

     

                    recipients = _recipientsOfSubclassesAction;

                }

                else

                {

                    if (_recipientsStrictAction == null)

                    {

                        _recipientsStrictAction = new Dictionary<Type, List<WeakActionAndToken>>();

                    }

     

                    recipients = _recipientsStrictAction;

                }

     

                List<WeakActionAndToken> list;

     

                if (!recipients.ContainsKey(messageType))

                {

                    list = new List<WeakActionAndToken>();

                    recipients.Add(messageType, list);

                }

                else

                {

                    list = recipients[messageType];

                }

     

                var weakAction = new WeakAction<TMessage>(recipient, action);

                var item = new WeakActionAndToken

                {

                    Action = weakAction,

                    Token = token

                };

                list.Add(item);

     

                Cleanup();

            }

     

        

            public virtual void Send<TMessage>(TMessage message)

            {

                SendToTargetOrType(message, null, null);

            }

     

         

            [SuppressMessage(

                "Microsoft.Design",

                "CA1004:GenericMethodsShouldProvideTypeParameter",

                Justification = "This syntax is more convenient than other alternatives.")]

            public virtual void Send<TMessage, TTarget>(TMessage message)

            {

                SendToTargetOrType(message, typeof(TTarget), null);

            }

     

          

            public virtual void Send<TMessage>(TMessage message, object token)

            {

                SendToTargetOrType(message, null, token);

            }

     

            /// <summary>

         

            public virtual void Unregister(object recipient)

            {

                UnregisterFromLists(recipient, _recipientsOfSubclassesAction);

                UnregisterFromLists(recipient, _recipientsStrictAction);

            }

     

     

            [SuppressMessage(

                "Microsoft.Design",

                "CA1004:GenericMethodsShouldProvideTypeParameter",

                Justification =

                    "The type parameter TMessage identifies the message type that the recipient wants to unregister for.")]

            public virtual void Unregister<TMessage>(object recipient)

            {

                Unregister<TMessage>(recipient, null);

            }

     

            public virtual void Unregister<TMessage>(object recipient, Action<TMessage> action)

            {

                UnregisterFromLists(recipient, action, _recipientsStrictAction);

                UnregisterFromLists(recipient, action, _recipientsOfSubclassesAction);

                Cleanup();

            }

     

            private static void CleanupList(IDictionary<Type, List<WeakActionAndToken>> lists)

            {

                if (lists == null)

                {

                    return;

                }

     

                var listsToRemove = new List<Type>();

                foreach (var list in lists)

                {

                    var recipientsToRemove = new List<WeakActionAndToken>();

                    foreach (var item in list.Value)

                    {

                        if (item.Action == null

                            || !item.Action.IsAlive)

                        {

                            recipientsToRemove.Add(item);

                        }

                    }

     

                    foreach (var recipient in recipientsToRemove)

                    {

                        list.Value.Remove(recipient);

                    }

     

                    if (list.Value.Count == 0)

                    {

                        listsToRemove.Add(list.Key);

                    }

                }

     

                foreach (var key in listsToRemove)

                {

                    lists.Remove(key);

                }

            }

     

            private static bool Implements(Type instanceType, Type interfaceType)

            {

                if (interfaceType == null

                    || instanceType == null)

                {

                    return false;

                }

     

                var interfaces = instanceType.GetInterfaces();

                foreach (var currentInterface in interfaces)

                {

                    if (currentInterface == interfaceType)

                    {

                        return true;

                    }

                }

     

                return false;

            }

     

            private static void SendToList<TMessage>(

                TMessage message,

                IEnumerable<WeakActionAndToken> list,

                Type messageTargetType,

                object token)

            {

                if (list != null)

                {

                 

                    var listClone = list.Take(list.Count()).ToList();

     

                    foreach (var item in listClone)

                    {

                        var executeAction = item.Action as IExecuteWithObject;

     

                        if (executeAction != null

                            && item.Action.IsAlive

                            && item.Action.Target != null

                            && (messageTargetType == null

                                || item.Action.Target.GetType() == messageTargetType

                                || Implements(item.Action.Target.GetType(), messageTargetType))

                            && ((item.Token == null && token == null)

                                || item.Token != null && item.Token.Equals(token)))

                        {

                            executeAction.ExecuteWithObject(message);

                        }

                    }

                }

            }

     

            private static void UnregisterFromLists(object recipient, Dictionary<Type, List<WeakActionAndToken>> lists)

            {

                if (recipient == null

                    || lists == null

                    || lists.Count == 0)

                {

                    return;

                }

     

                lock (lists)

                {

                    foreach (var messageType in lists.Keys)

                    {

                        foreach (var item in lists[messageType])

                        {

                            var weakAction = item.Action;

     

                            if (weakAction != null

                                && recipient == weakAction.Target)

                            {

                                weakAction.MarkForDeletion();

                            }

                        }

                    }

                }

            }

     

            private static void UnregisterFromLists<TMessage>(

                object recipient,

                Action<TMessage> action,

                Dictionary<Type, List<WeakActionAndToken>> lists)

            {

                var messageType = typeof(TMessage);

     

                if (recipient == null

                    || lists == null

                    || lists.Count == 0

                    || !lists.ContainsKey(messageType))

                {

                    return;

                }

     

                lock (lists)

                {

                    foreach (var item in lists[messageType])

                    {

                        var weakActionCasted = item.Action as WeakAction<TMessage>;

     

                        if (weakActionCasted != null

                            && recipient == weakActionCasted.Target

                            && (action == null

                                || action == weakActionCasted.Action))

                        {

                            item.Action.MarkForDeletion();

                        }

                    }

                }

            }

     

            private void Cleanup()

            {

                CleanupList(_recipientsOfSubclassesAction);

                CleanupList(_recipientsStrictAction);

            }

     

            private void SendToTargetOrType<TMessage>(TMessage message, Type messageTargetType, object token)

            {

                var messageType = typeof(TMessage);

     

                if (_recipientsOfSubclassesAction != null)

                {

            

                    var listClone = _recipientsOfSubclassesAction.Keys.Take(_recipientsOfSubclassesAction.Count()).ToList();

     

                    foreach (var type in listClone)

                    {

                        List<WeakActionAndToken> list = null;

     

                        if (messageType == type

                            || messageType.IsSubclassOf(type)

                            || Implements(messageType, type))

                        {

                            list = _recipientsOfSubclassesAction[type];

                        }

     

                        SendToList(message, list, messageTargetType, token);

                    }

                }

     

                if (_recipientsStrictAction != null)

                {

                    if (_recipientsStrictAction.ContainsKey(messageType))

                    {

                        var list = _recipientsStrictAction[messageType];

                        SendToList(message, list, messageTargetType, token);

                    }

                }

     

                Cleanup();

            }

     

            private struct WeakActionAndToken

            {

                public WeakAction Action;

     

                public object Token;

            }

        }

    Messager在MVVM的实例

    在ViewModel端

           public void UpdateJob(object sender, RoutedEventArgs v)

            {

                var focusrow = (JobMVVMClient.JobBL.View_T_SegmentJob)SelectRow;

                if (focusrow != null)

                {

                    JobMVVMClient.JobBL.JobBLClient Job = new          JobMVVMClient.JobBL.JobBLClient();

                    var row = (JobMVVMClient.JobBL.View_T_SegmentJob)selectRow;

                    if (row.班次号 == null || row.班组号 == null

                        || row.计划结束时间 == null || row.计划开始时间 == null || row.投产量 == 0.0)

                        return;

                    Job.UpdateSegmentJobBySomeThingCompleted += (s, e) =>

                    {

                        if (e.Result)

                        {

                            MessageBox.Show(PromptString.UpdateJobYes);

     

                            foreach (var element in jobModel.Gradeinfo)

                            {

                                if (element.DetailID == row.班次号.ToString())

                                    row.班次 = element.DetailName;

                            }

                            foreach (var element in jobModel.Groupinfo)

                            {

                                if (element.DetailID == row.班组号.ToString())

                                    row.班组 = element.DetailName;

                            }

                    

                        }

                    };

     

     

            Messenger.Default.Send<bool?,JobMVVMClinet.Views.JobPlanUpdateView>(true);

           //给位于View层中的JobPlanUpdateView这个界面发送bool消息,这个消息是true.

     Job.UpdateSegmentJobBySomeThingAsync(row.工单ID, row.投产量, (DateTime)row.计划开始时间, (DateTime)row.计划结束时间, (int)row.班次号, (int)row.班组号);

     

                    Job.CloseAsync();

                }

            }

    在VIEW端

       public partial class JobPlanUpdateView : ChildWindow

        {

            public JobPlanUpdateView(CreateJobViewModel model)

            {

                InitializeComponent();

                DataContext = model;

     

                Messenger.Default.Register<bool?>(this, m => this.DialogResult = m);

                //注册接收消息,并且做出响应处理

     

             }

        }

    Messager总结

    消息在MVVM中广泛应用,更好的运用MESSAGER能更好的处理View与ViewModel的关系,为MVVM添加喝彩。

  • 相关阅读:
    管理信息系统 第三部分 作业
    密码保护
    实现搜索功能
    完成个人中心—导航标签
    个人中心标签页导航
    评论列表显示及排序,个人中心显示
    完成评论功能
    管理信息系统 课程设计
    期末作品检查
    管理信息系统 第三部分 作业
  • 原文地址:https://www.cnblogs.com/TiTiArchitect/p/4473540.html
Copyright © 2011-2022 走看看