Wpf caliburn micro中行动防护装置的评估
是否必须根据caliburn micro通知视图模型中每个函数/属性中更改的属性以更新工具栏的按钮状态?听起来不太好 我能收回我的反射指令吗?还是我错过了什么Wpf caliburn micro中行动防护装置的评估,wpf,caliburn.micro,inotifypropertychanged,Wpf,Caliburn.micro,Inotifypropertychanged,是否必须根据caliburn micro通知视图模型中每个函数/属性中更改的属性以更新工具栏的按钮状态?听起来不太好 我能收回我的反射指令吗?还是我错过了什么 public void New() { // do something NotifyOfPropertyChange(() => CanFirst); NotifyOfPropertyChange(() => CanLast); NotifyOfPropertyChange(() =>
public void New()
{
// do something
NotifyOfPropertyChange(() => CanFirst);
NotifyOfPropertyChange(() => CanLast);
NotifyOfPropertyChange(() => CanPrevious);
NotifyOfPropertyChange(() => CanNext);
NotifyOfPropertyChange(() => CanNew);
NotifyOfPropertyChange(() => CanUpdate);
NotifyOfPropertyChange(() => CanDelete);
NotifyOfPropertyChange(() => CanSave);
NotifyOfPropertyChange(() => CanActive);
.
.
.
}
如果要引发更改通知的所有属性都位于引发更改通知的同一视图模型上,则只需调用继承自
PropertyChangedBase
的Refresh()
:
public void New()
{
base.Refresh();
}
一个更自动化的解决方案
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();
};
}
}
}
使用系统;
使用System.Linq;
运用系统反思;
使用Caliburn.Micro;
使用Action=System.Action;
名称空间框架.Wpf
{
公共类ActionManager
{
公共事件处理程序重新评估Nexecutechanged;
[线程静态]
私有静态ActionManager\u ActionManager;
公共静态ActionManager当前版本
{
得到
{
如果(_actionManager==null)
_actionManager=新的actionManager();
返回操作管理器;
}
}
重新评估Nexecutechanged()上受保护的虚拟无效
{
如果(重新评估Nexecutechanged!=null)
重新评估Nexecutechanged(这是新的EventArgs());
}
public void SuggestPropertyChanged()
{
重新评估Nexecutechanged();
}
}
公共静态类CaliburnMicroConfig
{
///
///准备上下文。
///
///上下文。
私有静态void PrepareContext(ActionExecutionContext上下文)
{
ActionMessage.SetMethodBinding(上下文);
if(context.Target!=null&&context.Method!=null)
{
MethodInfo guard=TryFindGuardMethod(上下文);
如果(保护!=null)
{
EventHandler=null;
处理程序=(s,e)=>((操作)(()=>
{
var message=context.message;
如果(消息==null)
ActionManager.Current.ReevalueCanexecuteChanged-=处理程序;
其他的
message.UpdateAvailability();
})).OnUIThread();
ActionManager.Current.ReevalueCanexecuteChanged+=处理程序;
context.Disposing+=(s,e)=>ActionManager.Current.ReEvaluateCanExecuteChanged-=处理程序;
context.Message.Detaching+=(s,e)=>ActionManager.Current.ReevalueCanexecuteChanged-=处理程序;
context.CanExecute=()=>
{
return(bool)guard.Invoke(context.Target,MessageBinder.DetermineParameters(context,guard.GetParameters());
};
}
}
}
私有静态MethodInfo TryFindGuardMethod(ActionExecutionContext上下文)
{
string name=string.Format(“Can{0}”,context.Method.name);
MethodInfo method=context.Target.GetType().GetMethod(名称);
if(方法==null)
返回null;
if(方法包含通用参数)
返回null;
if(typeof(bool)!=方法返回类型)
返回null;
ParameterInfo[]methodParameters=method.GetParameters();
ParameterInfo[]contextMethodParameters=context.Method.GetParameters();
如果(methodParameters.Length==0)
返回法;
if(methodParameters.Length!=contextMethodParameters.Length)
返回null;
返回methodParameters.Zip(contextMethodParameters,(x,y)=>x.ParameterType==y.ParameterType).Any(x=>!x)?null:方法;
}
public static void enableAutoActionGuardMethodEvaluate()
{
ActionMessage.PrepareContext=PrepareContext;
Action old=ActionMessage.InvokeAction;
ActionMessage.InvokeAction=context=>
{
旧(上下文);
ActionManager.Current.SuggestPropertyChanged();
};
}
}
}
谢谢,但不幸的是,它们不在同一视图模型中,并且每个操作都有十几个不同的notify属性发生了更改。@Nima OKRefresh()
通知给定视图模型上所有属性的属性已更改,您可以在每个视图模型上单独使用它。我将以不同的方式设计我的应用程序,方法是给可能修改工具栏状态的组件,给它们一个对该工具栏的引用,以便它们可以随意禁用或启用操作。