WPF使用成熟的命令系统
程序员文章站
2024-02-16 10:49:58
...
需要的三个类如下所示:
对应的代码分别如下所示,直接Copy即可(只需要 注意一下命名空间
):
RelayCommand 命令类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace Notepad_WPF.Helpers
{
public class RelayCommand : ICommand
{
private readonly WeakAction _execute;
private readonly WeakFunc<bool> _canExecute;
public RelayCommand(Action execute, bool keepTargetAlive = false)
: this(execute, null, keepTargetAlive)
{
}
public RelayCommand(Action execute, Func<bool> canExecute, bool keepTargetAlive = false)
{
if (execute == null)
{
throw new ArgumentNullException("execute");
}
_execute = new WeakAction(execute, keepTargetAlive);
if (canExecute != null)
{
_canExecute = new WeakFunc<bool>(canExecute, keepTargetAlive);
}
}
private EventHandler _requerySuggestedLocal;
public event EventHandler CanExecuteChanged
{
add
{
if (_canExecute != null)
{
EventHandler handler2;
EventHandler canExecuteChanged = _requerySuggestedLocal;
do
{
handler2 = canExecuteChanged;
EventHandler handler3 = (EventHandler)Delegate.Combine(handler2, value);
canExecuteChanged = System.Threading.Interlocked.CompareExchange<EventHandler>(
ref _requerySuggestedLocal,
handler3,
handler2);
}
while (canExecuteChanged != handler2);
CommandManager.RequerySuggested += value;
}
}
remove
{
if (_canExecute != null)
{
EventHandler handler2;
EventHandler canExecuteChanged = this._requerySuggestedLocal;
do
{
handler2 = canExecuteChanged;
EventHandler handler3 = (EventHandler)Delegate.Remove(handler2, value);
canExecuteChanged = System.Threading.Interlocked.CompareExchange<EventHandler>(
ref this._requerySuggestedLocal,
handler3,
handler2);
}
while (canExecuteChanged != handler2);
CommandManager.RequerySuggested -= value;
}
}
}
public void RaiseCanExecuteChanged()
{
CommandManager.InvalidateRequerySuggested();
}
public bool CanExecute(object parameter)
{
return _canExecute == null
|| (_canExecute.IsStatic || _canExecute.IsAlive)
&& _canExecute.Execute();
}
public virtual void Execute(object parameter)
{
if (CanExecute(parameter)
&& _execute != null
&& (_execute.IsStatic || _execute.IsAlive))
{
_execute.Execute();
}
}
}
}
WeakAction 辅助类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Notepad_WPF.Helpers
{
public class WeakAction
{
private Action _staticAction;
protected MethodInfo Method
{
get;
set;
}
public virtual string MethodName
{
get
{
if (_staticAction != null)
{
return _staticAction.Method.Name;
}
return Method.Name;
}
}
protected WeakReference ActionReference
{
get;
set;
}
protected object LiveReference
{
get;
set;
}
protected WeakReference Reference
{
get;
set;
}
public bool IsStatic
{
get
{
return _staticAction != null;
}
}
protected WeakAction()
{
}
public WeakAction(Action action, bool keepTargetAlive = false)
: this(action == null ? null : action.Target, action, keepTargetAlive)
{
}
public WeakAction(object target, Action action, bool keepTargetAlive = false)
{
if (action.Method.IsStatic)
{
_staticAction = action;
if (target != null)
{
Reference = new WeakReference(target);
}
return;
}
Method = action.Method;
ActionReference = new WeakReference(action.Target);
LiveReference = keepTargetAlive ? action.Target : null;
Reference = new WeakReference(target);
if (ActionReference != null
&& ActionReference.Target != null
&& !keepTargetAlive)
{
var type = ActionReference.Target.GetType();
if (type.Name.StartsWith("<>")
&& type.Name.Contains("DisplayClass"))
{
System.Diagnostics.Debug.WriteLine(
"You are attempting to register a lambda with a closure without using keepTargetAlive. Are you sure? Check http://galasoft.ch/s/mvvmweakaction for more info.");
}
}
}
public virtual bool IsAlive
{
get
{
if (_staticAction == null
&& Reference == null
&& LiveReference == null)
{
return false;
}
if (_staticAction != null)
{
if (Reference != null)
{
return Reference.IsAlive;
}
return true;
}
if (LiveReference != null)
{
return true;
}
if (Reference != null)
{
return Reference.IsAlive;
}
return false;
}
}
public object Target
{
get
{
if (Reference == null)
{
return null;
}
return Reference.Target;
}
}
protected object ActionTarget
{
get
{
if (LiveReference != null)
{
return LiveReference;
}
if (ActionReference == null)
{
return null;
}
return ActionReference.Target;
}
}
public void Execute()
{
if (_staticAction != null)
{
_staticAction();
return;
}
var actionTarget = ActionTarget;
if (IsAlive)
{
if (Method != null
&& (LiveReference != null
|| ActionReference != null)
&& actionTarget != null)
{
Method.Invoke(actionTarget, null);
return;
}
}
}
public void MarkForDeletion()
{
Reference = null;
ActionReference = null;
LiveReference = null;
Method = null;
_staticAction = null;
}
}
}
WeakFunc 辅助类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Notepad_WPF.Helpers
{
public class WeakFunc<TResult>
{
private Func<TResult> _staticFunc;
protected MethodInfo Method
{
get;
set;
}
public bool IsStatic
{
get
{
return _staticFunc != null;
}
}
public virtual string MethodName
{
get
{
if (_staticFunc != null)
{
return _staticFunc.Method.Name;
}
return Method.Name;
}
}
protected WeakReference FuncReference
{
get;
set;
}
protected object LiveReference
{
get;
set;
}
protected WeakReference Reference
{
get;
set;
}
protected WeakFunc()
{
}
public WeakFunc(Func<TResult> func, bool keepTargetAlive = false)
: this(func == null ? null : func.Target, func, keepTargetAlive)
{
}
public WeakFunc(object target, Func<TResult> func, bool keepTargetAlive = false)
{
if (func.Method.IsStatic)
{
_staticFunc = func;
if (target != null)
{
Reference = new WeakReference(target);
}
return;
}
Method = func.Method;
FuncReference = new WeakReference(func.Target);
LiveReference = keepTargetAlive ? func.Target : null;
Reference = new WeakReference(target);
if (FuncReference != null
&& FuncReference.Target != null
&& !keepTargetAlive)
{
var type = FuncReference.Target.GetType();
if (type.Name.StartsWith("<>")
&& type.Name.Contains("DisplayClass"))
{
System.Diagnostics.Debug.WriteLine(
"You are attempting to register a lambda with a closure without using keepTargetAlive. Are you sure? Check http://galasoft.ch/s/mvvmweakaction for more info.");
}
}
}
public virtual bool IsAlive
{
get
{
if (_staticFunc == null
&& Reference == null
&& LiveReference == null)
{
return false;
}
if (_staticFunc != null)
{
if (Reference != null)
{
return Reference.IsAlive;
}
return true;
}
// Non static action
if (LiveReference != null)
{
return true;
}
if (Reference != null)
{
return Reference.IsAlive;
}
return false;
}
}
public object Target
{
get
{
if (Reference == null)
{
return null;
}
return Reference.Target;
}
}
protected object FuncTarget
{
get
{
if (LiveReference != null)
{
return LiveReference;
}
if (FuncReference == null)
{
return null;
}
return FuncReference.Target;
}
}
public TResult Execute()
{
if (_staticFunc != null)
{
return _staticFunc();
}
var funcTarget = FuncTarget;
if (IsAlive)
{
if (Method != null
&& (LiveReference != null
|| FuncReference != null)
&& funcTarget != null)
{
return (TResult)Method.Invoke(funcTarget, null);
}
}
return default(TResult);
}
public void MarkForDeletion()
{
Reference = null;
FuncReference = null;
LiveReference = null;
Method = null;
_staticFunc = null;
}
}
}
使用方式非常的简单方便,如下所示:
其中的 RelayCommand对象中有多种重载版本 . . .
上一篇: 让程序使用自带的字体2
下一篇: WPF 可视化树