0

我是否必须通知视图模型中每个功能/属性中的属性更改,以便根据 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);
    .
    .
    .
 }
4

2 回答 2

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();
            };
        }
    }
}
于 2013-09-01T07:08:57.773 回答
0

如果您为其提出更改通知的所有这些属性都在提出更改通知的同一视图模型上,那么您可以简单地调用Refresh()继承自PropertyChangedBase

public void New()
{
    base.Refresh();
}
于 2013-08-31T14:28:38.510 回答