(六)WPF資料驅動模式

灰色小五發表於2024-10-02

WPF開發方式; MVVM(Model View ViewModel)
1.繫結XAML資料方式
在 XAML中新增繫結資料和繫結的操作屬性
Content="{Binding MyVar}"

 在XAML對應了的窗體類的建構函式新增資料繫結
this.DataContext = mainViewModel; //讓此頁面的資料取MainViewModel物件裡去尋找

2.實現INotifyPropertyChanged介面更新XAML資料
因為只在建構函式新增了資料繫結,如果在後續資料變動時則無法更新資料,所以要在MainViewMoel業務邏輯(已經包含資料模型了)中實現INotifyPropertyChanged介面,然後透過委託型別的事件更新繫結欄位的資料:

3.建立CommandBase實現ICommand介面執行按鈕動作方法
建立一個類CommandBase實現ICommand介面:按鈕 Command="{Binding ValueCommand}" 行為繫結ValueCommand欄位

    class CommandBase : ICommand
    {
        public event EventHandler CanExecuteChanged;

        public bool CanExecute(object parameter)
        {
            //繫結的這個命令的按鈕是否可用
            return DoCanExecute?.Invoke(parameter) == true;//這裡面沒有任何執行邏輯,邏輯都被委託Func丟出去了,例項化時傳進來含返回值的方法即可
        }

        public void Execute(object parameter)//parameter是訂閱此此介面方法的按鈕傳遞過來的引數
        {
        
            DoAction?.Invoke(parameter);//在應用程式主執行緒上執行指定委託?是Require的縮寫?
            
        }

        public Action<object> DoAction { get; set; }//定義一個Action<object> 委託型別,委託需要Invoke()執行
        //那麼這個委託在建立CommandBase物件時就可以傳遞進來一個自定義方法執行了
        //此類是非靜態的,所以所有Control都可以使用
        public Func<object, bool> DoCanExecute { get;set; }//定義有返回值的委託型別Func
    }

  在實現三個方法同時,自定義一個無返回值的Action委託型別(有返回值的則是Func<>)DoAction,Action<T1,T2,...>引數和傳遞進來的方法引數對應,屬性為空,類為非靜態,所以在建立CommandBase物件時就可以透過委託傳遞進來一個方法。
在業務邏輯類MainViewModel定義ICommand型別欄位,在欄位封裝屬性同時建立CommandBase物件,並建立類內DoAction委託將方法傳進去給Execute()方法執行,Execute會在繫結ValueCommand欄位按鈕動作時執行。

  public class MainViewModel:INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private string myVar="AA";
        private Brush _valueColor=Brushes.Orange;

        public Brush ValueColor
        {
            get { return _valueColor; }
            set { _valueColor = value; }
        }

        public string MyVar
        {
            get { return myVar; }
            set { myVar = value;
                PropertyChanged?.Invoke(this,new PropertyChangedEventArgs("MyVar"));//更新繫結此屬性的控制元件

            }
        }


        //行為繫結處理

        private ICommand _valueCommand;//定義介面型別的欄位,
        //透過按鈕Command屬性繫結行為,按鈕點選則會觸發實現介面類CommandBase中的Execute()方法
        //透過屬性CommandParameter="123"傳遞引數

        public ICommand ValueCommand
        {
            get {
                if (_valueCommand == null)
                {
                    _valueCommand = new CommandBase() { DoAction = new Action<object>(ValueCommandAction),
                                                       DoCanExecute=new Func<object, bool>(CanExcute) };//例項化同時傳遞方法給委託DoAction在CommandBase中執行,父類引用指向子類物件
                  
                }
                return _valueCommand;
                }
            set { _valueCommand = value; }
        }

        private void ValueCommandAction(object obj)
        {
            MessageBox.Show("Test");
        }

        private bool CanExcute(object obj)
        {
            return !string.IsNullOrEmpty(MyVar);//判斷是否為空
        }
    }

相關文章