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);//判斷是否為空 } }