前文不需要带参数的成熟命令:
WPF使用成熟的命令系统
需要的五个类如下所示:
定义分别如下所示:
IExecuteWithObject 接口:
public interface IExecuteWithObject
{
object Target { get; }
void ExecuteWithObject(object parameter);
void MarkForDeletion();
}
IExecuteWithObjectAndResult 接口:
public interface IExecuteWithObjectAndResult
{
object ExecuteWithObject(object parameter);
}
RelayCommand< T > 类:
public class RelayCommand<T> : ICommand
{
private readonly WeakAction<T> _execute;
private readonly WeakFunc<T, bool> _canExecute;
public RelayCommand(Action<T> execute, bool keepTargetAlive = false) : this(execute, null, keepTargetAlive) { }
public RelayCommand(Action<T> execute, Func<T, bool> canExecute, bool keepTargetAlive = false)
{
if (execute == null)
{
throw new ArgumentNullException("execute");
}
_execute = new WeakAction<T>(execute, keepTargetAlive);
if (canExecute != null)
{
_canExecute = new WeakFunc<T, bool>(canExecute, keepTargetAlive);
}
}
public event EventHandler CanExecuteChanged
{
add { if (_canExecute != null) { CommandManager.RequerySuggested += value; } }
remove { if (_canExecute != null) { CommandManager.RequerySuggested -= value; } }
}
public void RaiseCanExecuteChanged() { CommandManager.InvalidateRequerySuggested(); }
public bool CanExecute(object parameter)
{
if (_canExecute == null)
{
return true;
}
if (_canExecute.IsStatic || _canExecute.IsAlive)
{
if (parameter == null && typeof(T).IsValueType) { return _canExecute.Execute(default(T)); }
if (parameter == null || parameter is T) { return (_canExecute.Execute((T)parameter)); }
}
return false;
}
public virtual void Execute(object parameter)
{
var val = parameter;
if (parameter != null && parameter.GetType() != typeof(T))
{ if (parameter is IConvertible) { val = Convert.ChangeType(parameter, typeof(T), null); } }
if (CanExecute(val) && _execute != null && (_execute.IsStatic || _execute.IsAlive))
{
if (val == null)
{
if (typeof(T).IsValueType) { _execute.Execute(default(T)); }
else { _execute.Execute((T)val); }
}
else { _execute.Execute((T)val); }
}
}
}
WeakAction< T > 类:
public class WeakAction<T> : WeakAction, IExecuteWithObject
{
private Action<T> _staticAction;
public override string MethodName
{
get
{
if (_staticAction != null)
{
return _staticAction.Method.Name;
}
return Method.Name;
}
}
public override bool IsAlive
{
get
{
if (_staticAction == null && Reference == null) { return false; }
if (_staticAction != null)
{
if (Reference != null) { return Reference.IsAlive; }
return true;
}
return Reference.IsAlive;
}
}
public WeakAction(Action<T> action, bool keepTargetAlive = false)
: this(action == null ? null : action.Target, action, keepTargetAlive) { }
public WeakAction(object target, Action<T> 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 new void Execute() { Execute(default(T)); }
public void Execute(T parameter)
{
if (_staticAction != null)
{
_staticAction(parameter);
return;
}
var actionTarget = ActionTarget;
if (IsAlive)
{
if (Method != null && (LiveReference != null || ActionReference != null) && actionTarget != null)
{
Method.Invoke(actionTarget, new object[] { parameter });
}
}
}
public void ExecuteWithObject(object parameter)
{
var parameterCasted = (T)parameter;
Execute(parameterCasted);
}
public new void MarkForDeletion()
{
_staticAction = null;
base.MarkForDeletion();
}
}
WeakFunc< T > 类:
public class WeakFunc<T, TResult> : WeakFunc<TResult>, IExecuteWithObjectAndResult
{
private Func<T, TResult> _staticFunc;
public override string MethodName
{
get
{
if (_staticFunc != null) { return _staticFunc.Method.Name; }
return Method.Name;
}
}
public override bool IsAlive
{
get
{
if (_staticFunc == null && Reference == null) { return false; }
if (_staticFunc != null) { if (Reference != null) { return Reference.IsAlive; } return true; }
return Reference.IsAlive;
}
}
public WeakFunc(Func<T, TResult> func, bool keepTargetAlive = false)
: this(func == null ? null : func.Target, func, keepTargetAlive) { }
public WeakFunc(object target, Func<T, 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 new TResult Execute() { return Execute(default(T)); }
public TResult Execute(T parameter)
{
if (_staticFunc != null)
{
return _staticFunc(parameter);
}
var funcTarget = FuncTarget;
if (IsAlive)
{
if (Method != null && (LiveReference != null || FuncReference != null) && funcTarget != null)
{
return (TResult)Method.Invoke(funcTarget, new object[] { parameter });
}
}
return default(TResult);
}
public object ExecuteWithObject(object parameter)
{
var parameterCasted = (T)parameter;
return Execute(parameterCasted);
}
public new void MarkForDeletion()
{
_staticFunc = null;
base.MarkForDeletion();
}
}
假如我们需要访问Bing这个网页进行搜索,我需要一个参数,可以这样定义,如下所示:
实例命令:
方法如下所示:
这个 obj 就是我们传入的参数(TextBox类型,需要其中的SelectedText属性),XAML绑定情况如下所示:
1)快捷键:
菜单绑定:
现在执行这个命令就可以跳转到网页了,并且搜索指定的内容,如下所示: