WPF使用成熟的命令系统

需要的三个类如下所示:
)

对应的代码分别如下所示,直接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对象中有多种重载版本 . . .

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值