【轉】【WPF】MVVM模式的3種command

來源:互聯網
上載者:User

標籤:box   一個   自己   log   dma   copy   範圍   value   bug   

1.DelegateCommand

2.RelayCommand

3.AttachbehaviorCommand

因為MVVM模式適合於WPF和SL,所以這3種模式中也有一些小差異,比如RelayCommand下面的CommandManager方法就是WPF下面的,SL下面無法使用,不過我認為這3種方法中的基本思路都如出一轍,都是出自那位外國牛人的文章裡面。主要的區別在於和VIEW中的控制項的綁定使用上。有點不同的attachbehaviorcommand是prism4裡面的一種設計模式,這個區別有點大。但我自己覺得最方便的還是這個DelegateCommand。

DelegateCommand
    /// <summary>    /// Delegatecommand,這種WPF.SL都可以用,VIEW裡面直接使用INTERACTION的trigger激發。比較靠譜,適合不同的UIElement控制項    /// </summary>    public class DelegateCommand : ICommand    {        Func<object, bool> canExecute;        Action<object> executeAction;        bool canExecuteCache;        public DelegateCommand(Action<object> executeAction, Func<object, bool> canExecute)        {            this.executeAction = executeAction;            this.canExecute = canExecute;        }        #region ICommand Members        public bool CanExecute(object parameter)        {            bool temp = canExecute(parameter);            if (canExecuteCache != temp)            {                canExecuteCache = temp;                if (CanExecuteChanged != null)                {                    CanExecuteChanged(this, new EventArgs());                }            }            return canExecuteCache;        }        public event EventHandler CanExecuteChanged;        public void Execute(object parameter)        {            executeAction(parameter);        }        #endregion    }

這個類大概可以這樣來理解,建構函式中的action和func,action負責判斷是否執行這個command,action就是觸發這個command之後要執行的方法。這樣理解最淺顯,但對剛熟悉command的我來講,這樣最方便記憶和學習,為了使用ICommand介面實現的方法和事件的解釋搜搜就可以找到,但是剛開始理解起來還是有點晦澀。

下面是VM裡面用這個command的例子。綁定了一個button控制項,最簡單例子。cm1Click就是建構函式裡面的fuc,負責執行響應事件的方法。Cancm1Click就是建構函式裡面的action,負責判斷這個Command的響應事件是否執行,這裡沒有用到判斷式,直接賦了一個true.

public class TestViewModels:INotifyPropertyChanged{        public TestViewModels()        {            ......            cm1click = new DelegateCommand(cm1Click,Cancm1Click);   //初始化delegatecommand                    }       ....       //DelegateCommand        #region command1        public ICommand cm1click { get; set; }        public void cm1Click(object param)        {            MessageBox.Show("CM1 clicked!");        }        private bool Cancm1Click(object param)        {            return true;        }        #endregion command1       ......}

在XAML裡面,用interaction來綁定這個事件,而不是在button裡面用command來綁定,這樣做有個好處,就是非常直觀,並且可以響應其他的很多事件

<Button x:Name="BTN_CM1" Content="DelegateCommand" Height="115" Width="148" >            <i:Interaction.Triggers>                <i:EventTrigger EventName="Click">                    <i:InvokeCommandAction Command="{Binding cm1click}"/>                </i:EventTrigger>            </i:Interaction.Triggers>        </Button>

RelayCommand

RelayCommand本來是WPF下面用的一種自訂的command,主要是它用到了事件管理函數,這個SL下面是沒有的。不過這部分代碼如果修改一下,也可以在SL下面使用,和WPF下面的實現思路差不多。

先看下RelayCommand的定義,一共有2種。

public class RelayCommand<T> : ICommand    {        public RelayCommand(Action<T> execute)            : this(execute, null)        {        }        public RelayCommand(Action<T> execute, Predicate<T> canExecute)        {            if (execute == null)                throw new ArgumentNullException("execute");            _execute = execute;            _canExecute = canExecute;        }        [DebuggerStepThrough]        public bool CanExecute(object parameter)        {            return _canExecute == null ? true : _canExecute((T)parameter);        }        public event EventHandler CanExecuteChanged        {            add{}            remove{}             //add            //{            //    if (_canExecute != null)            //        CommandManager.RequerySuggested += value;            //}            //remove            //{            //    if (_canExecute != null)            //        CommandManager.RequerySuggested -= value;            //}        }        public void Execute(object parameter)        {            _execute((T)parameter);        }        readonly Action<T> _execute = null;        readonly Predicate<T> _canExecute = null;        bool ICommand.CanExecute(object parameter)        {            throw new NotImplementedException();        }        event EventHandler ICommand.CanExecuteChanged        {            add { throw new NotImplementedException(); }            remove { throw new NotImplementedException(); }        }        void ICommand.Execute(object parameter)        {            throw new NotImplementedException();        }    }

第一種是採用泛型的Relaycommand定義

public class RelayCommand : ICommand    {        public RelayCommand(Action execute)            : this(execute, null)        {        }        public RelayCommand(Action execute, Func<bool> canExecute)        {            if (execute == null)                throw new ArgumentNullException("execute");            _execute = execute;            _canExecute = canExecute;        }        [DebuggerStepThrough]        public bool CanExecute(object parameter)        {            return _canExecute == null ? true : _canExecute();        }        public event EventHandler CanExecuteChanged        {   //這裡把實現注釋掉了,這樣在SL下面也可以用。            add { }            remove { }            //add            //{            //    if (_canExecute != null)            //        CommandManager.RequerySuggested += value;            //}            //remove            //{            //    if (_canExecute != null)            //        CommandManager.RequerySuggested -= value;            //}        }        public void Execute(object parameter)        {            _execute();        }        readonly Action _execute;        readonly Func<bool> _canExecute;    }

第二種就是最常用的定義,可以看到在CanExecuteChanged事件裡面把commmandmanager方法給注釋掉了,就可以在SL下面使用這個類,而且現在看好像也沒有什麼問題。

在代碼上看,Relaycommand和delegatcommand基本上沒有啥區別,也是實現了func和action兩個參數的辦法,基本思路一樣。

它們最大的區別就是在前端的調用方式上。delegatecommand使用了expression的SDK裡面的interaction來綁定事件,而這種就是直接通過buttonbase的command屬性來綁定,因此只能執行單擊事件,所以使用範圍比較局限,不過如果用interaction來綁定事件的話,其實實現就和delegatecommand一樣了。不過為了總結下學習,還是分開來區別下。

前端XAML的代碼

<Button x:Name="BTN_CM2" Content="Command2" Height="103" HorizontalAlignment="Left" Margin="115,123,0,0" VerticalAlignment="Top" Width="109" Command="{Binding command2}" />

後台

private ICommand _command2;        public ICommand command2        {            get            {                if (this._command2 == null)                {                    this._command2 = new RelayCommand(                        () => this.cm2Click(),                        () => this.Cancm2Click);                }                return this._command2;            }            set { }        }        public bool Cancm2Click        {            get { return true; }        }        public void cm2Click()        {            MessageBox.Show("CM2 Clicked!");        }

【轉】【WPF】MVVM模式的3種command

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.