更自动的解决方案!!!
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();
};
}
}
}