Messenger在MVVM模式中的應用

Messenger在MVVM模式中的應用

Messenger在MVVM中應用的前提

    咱們知道在MVVM架構中,系統平臺的Silverlight客戶端界面開發和業務邏輯已經被分開,XAML是SL的主要部分,界面設計者只須要綁定ViewModel裏的數據便可。可是在ViewModel裏有些時候是須要界面發出響應的,在這種狀況下,Messenger顯示出它的用處。架構

Messenger的架構

 

Messager構件代碼

 

定義Imessager接口

 

註冊一個接收消息的類型,好比某一控件來接收消息ide

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

給最近註冊的類型發送消息設計

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

取消最近註冊的類型,當執行該句後,再也不接收任何消息token

  void Unregister(object recipient);接口

 

實現Imessager接口

  public class Messenger : IMessengerip

    {ci

        private static Messenger _defaultInstance;element

 

        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添加喝彩。

相關文章
相關標籤/搜索