在caliburn micro中评估动作防护

时间:2013-08-31 13:21:27

标签: wpf caliburn.micro inotifypropertychanged

我是否必须通过视图模型中的每个功能/属性更改已更改的属性,以根据caliburn micro更新工具栏的按钮状态?这听起来不太好。

我可以回复我的反思命令吗?或者我错过了什么?

 public void New()
 {
    // do something
    NotifyOfPropertyChange(() => CanFirst);
    NotifyOfPropertyChange(() => CanLast);
    NotifyOfPropertyChange(() => CanPrevious);
    NotifyOfPropertyChange(() => CanNext);
    NotifyOfPropertyChange(() => CanNew);
    NotifyOfPropertyChange(() => CanUpdate);
    NotifyOfPropertyChange(() => CanDelete);
    NotifyOfPropertyChange(() => CanSave);
    NotifyOfPropertyChange(() => CanActive);
    .
    .
    .
 }

2 个答案:

答案 0 :(得分:0)

如果您提出更改通知的所有属性都在提升更改通知的同一视图模型上,那么您只需致电Refresh()继承自PropertyChangedBase

public void New()
{
    base.Refresh();
}

答案 1 :(得分:0)

更自动的解决方案!!!

using System;
using System.Linq;
using System.Reflection;
using Caliburn.Micro;
using Action = System.Action;

namespace Framework.Wpf
{

    public class ActionManager
    {
        public event EventHandler ReEvaluateCanExecuteChanged;

        [ThreadStatic]
        private static ActionManager _actionManager;

        public static ActionManager Current
        {
            get
            {
                if (_actionManager == null)
                    _actionManager = new ActionManager();

                return _actionManager;
            }
        }

        protected virtual void OnReEvaluateCanExecuteChanged()
        {
            if (ReEvaluateCanExecuteChanged != null)
                ReEvaluateCanExecuteChanged(this, new EventArgs());
        }



        public void SuggestPropertyChanged()
        {
            OnReEvaluateCanExecuteChanged();
        }
    }

    public static class CaliburnMicroConfig
    {
        /// <summary>
        ///     Prepares the context.
        /// </summary>
        /// <param name="context">The context.</param>
        private static void PrepareContext(ActionExecutionContext context)
        {
            ActionMessage.SetMethodBinding(context);
            if (context.Target != null && context.Method != null)
            {

                MethodInfo guard = TryFindGuardMethod(context);
                if (guard != null)
                {
                    EventHandler handler = null;

                    handler = (s, e) => ((Action)(() =>
                    {
                        var message = context.Message;
                        if (message == null)
                            ActionManager.Current.ReEvaluateCanExecuteChanged -= handler;
                        else
                            message.UpdateAvailability();
                    })).OnUIThread();

                    ActionManager.Current.ReEvaluateCanExecuteChanged += handler;

                    context.Disposing += (s, e) => ActionManager.Current.ReEvaluateCanExecuteChanged -= handler;
                    context.Message.Detaching += (s, e) => ActionManager.Current.ReEvaluateCanExecuteChanged -= handler;


                    context.CanExecute = () =>
                    {
                        return (bool)guard.Invoke(context.Target, MessageBinder.DetermineParameters(context, guard.GetParameters()));
                    };
                }
            }
        }


        private static MethodInfo TryFindGuardMethod(ActionExecutionContext context)
        {
            string name = string.Format("Can{0}", context.Method.Name);
            MethodInfo method = context.Target.GetType().GetMethod(name);

            if (method == null)
                return null;

            if (method.ContainsGenericParameters)
                return null;

            if (typeof(bool) != method.ReturnType)
                return null;

            ParameterInfo[] methodParameters = method.GetParameters();
            ParameterInfo[] contextMethodParameters = context.Method.GetParameters();

            if (methodParameters.Length == 0)
                return method;

            if (methodParameters.Length != contextMethodParameters.Length)
                return null;

            return methodParameters.Zip(contextMethodParameters, (x, y) => x.ParameterType == y.ParameterType).Any(x => !x) ? null : method;
        }

        public static void EnableAutoActionGuardMethodReEvaluate()
        {
            ActionMessage.PrepareContext = PrepareContext;

            Action<ActionExecutionContext> old = ActionMessage.InvokeAction;

            ActionMessage.InvokeAction = context =>
            {
                old(context);
                ActionManager.Current.SuggestPropertyChanged();
            };
        }
    }
}