<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          WPF 原生綁定和命令功能使用指南

          共 3723字,需瀏覽 8分鐘

           ·

          2020-07-27 00:25

          WPF?原生綁定命令功能使用指南


          如今,當(dāng)談到?WPF?時(shí),我們言必稱 MVVM、框架(如 Prism)等,似乎已經(jīng)忘了不用這些的話該怎么使用 WPF 了。當(dāng)然,這里說的不用框架和 MVVM,并不是說像使用 Winform 那樣使用 WPF,而是追本溯源,重識(shí) WPF 與生俱來的綁定命令的風(fēng)采。

          ?

          一、綁定的使用

          ?

          目標(biāo):前臺(tái)頁面通過綁定獲取后臺(tái)屬性的值。

          這個(gè)目標(biāo)實(shí)際上分為兩部分,一是前臺(tái)獲取后臺(tái)的屬性值,二是屬性值變動(dòng)后能夠及時(shí)體現(xiàn)出來。

          要實(shí)現(xiàn)目標(biāo)的第一部分,實(shí)際只需在窗體后臺(tái)的構(gòu)造函數(shù)中添加一行代碼即可:

          this.DataContext?=?this;

          這行代碼很關(guān)鍵,MVVM 模式中頁面與 ViewModel 關(guān)聯(lián)也是通過指定頁面類的 DataContext 為相應(yīng)的 ViewModel 對象來實(shí)現(xiàn)的。

          ?

          下面再來說說如何實(shí)現(xiàn)目標(biāo)的第二部分,也就是屬性變化后能及時(shí)體現(xiàn)出來,包括后臺(tái)屬性變化后前臺(tái)顯示自動(dòng)變化,以及前臺(tái)修改了內(nèi)容,后臺(tái)屬性的值跟著改變。眾所周知,這就是綁定,而要實(shí)現(xiàn)這一功能,需要相關(guān)類實(shí)現(xiàn)一個(gè)屬性變動(dòng)通知接口 —— InotifyPropertyChanged 。具體演變過程可參考網(wǎng)上的文章《?.NET 4.5 (C#):INotifyPropertyChanged 執(zhí)行的演變:從表達(dá)式樹到調(diào)用方信息的 BindableBase 類型 | Mgen》,這里直接給出最后的結(jié)果。

          ?

          首先,實(shí)現(xiàn) InotifyPropertyChanged 當(dāng)然是必要的,如果是要綁定其他類,則讓該類實(shí)現(xiàn)之,如果是直接在窗口后臺(tái)做相關(guān)功能,則最終窗口類看上去像這樣:

          public?partial?class?MainWindow?:?Window,?INotifyPropertyChanged

          ?

          然后添加一個(gè)事件和兩個(gè)方法:

          public event PropertyChangedEventHandler PropertyChanged;
          protected void OnPropertyChanged([CallerMemberName] string propertyName = null){ var eventHandler = this.PropertyChanged; eventHandler?.Invoke(this, new PropertyChangedEventArgs(propertyName));}
          protected bool SetProperty(ref T storage, T value, [CallerMemberName] String propertyName = null){ if (Equals(storage, value)) return false;
          storage = value; this.OnPropertyChanged(propertyName); return true;}



          最后就是要提供綁定的屬性了,可以像下面這樣寫:

          private string _UserName = "wlh";public string UserName{    get => _UserName;    set => SetProperty(ref _UserName, value);}



          前臺(tái)綁定就很簡單了:

          <TextBox?Text="{Binding?UserName,?Mode=TwoWay}">TextBox>

          ?

          二、命令?ICommand

          ?

          WPF 和 Winform 的重大區(qū)別就是,用戶的交互、數(shù)據(jù)的變化等,在 Winform 中,都需要程序員一點(diǎn)一點(diǎn)仔細(xì)地手動(dòng)處理,而在 WPF 中,數(shù)據(jù)是綁定的,交互通過命令傳遞,所以很多事情其實(shí) WPF 這個(gè)大框架就可以幫我們自動(dòng)處理了。說了這么多,其實(shí)就是說 Winform 是事件驅(qū)動(dòng)的,而 WPF 是數(shù)據(jù)驅(qū)動(dòng)的,所以在 Winform 中常用的按鈕點(diǎn)擊事件等各種事件,在 WPF 中是不怎么用了,而是使用命令。

          命令也是綁定的,先來看看前臺(tái)的樣子:

          <Button?Command="{Binding?GetTokenCommand}">獲取TokenButton>

          ?

          至于后臺(tái)怎么寫,先不急,通過《[WPF]?ICommand?最佳使用方法》一文,我們知道首先需要一個(gè)輔助類:

          public class class='wp_keywordlink_affiliate'>"http://dlgcy.com/tag/relaycommand/" title="View all posts in RelayCommand" target="_blank">RelayCommand</a>span> : ICommand{    private readonly Predicate _CanExecute;    private readonly Action _Execute;
          public RelayCommand(Predicate canExecute, Action execute) { this._CanExecute = canExecute; this._Execute = execute; }
          public event EventHandler CanExecuteChanged { add => CommandManager.RequerySuggested += value; remove => CommandManager.RequerySuggested -= value; }
          public bool CanExecute(object parameter) { return _CanExecute(parameter); }
          public void Execute(object parameter) { _Execute(parameter); }}



          可見 ICommand 中主要有兩個(gè)方法,一個(gè)檢查命令是否可用的 CanExecute (),以及實(shí)際干活的 Execute () 。

          ?

          然后在后臺(tái)添加一個(gè) “DoSomething” 的命令,也就是上面新建的 RelayCommand 類型:

          private ICommand _DoSomething;public ICommand DoSomethingCommand{    get    {        return _DoSomething ??= new RelayCommand(            o => _CanDoSomething(o),            o => { _DoSomethingMethod(o); });    }}
          private readonly Predicate _CanDoSomething = o => true;
          // 可在之后再賦值,避免方法體中訪問屬性等受阻;private readonly Action _DoSomethingMethod = o =>{ // do something};



          這些還可以進(jìn)一步簡化為:

          public ICommand DoSomethingCommand { get; set; }
          /// /// 命令方法賦值(在構(gòu)造方法中調(diào)用)/// private void SetCommandMethod(){ DoSomethingCommand ??= new RelayCommand(o => true, async o => { // do something });}



          最后來看看對應(yīng)前臺(tái)”GetTokenCommand” 命令的實(shí)際業(yè)務(wù)代碼:

          public ICommand GetTokenCommand { get; set; }
          /// /// 命令方法賦值(在構(gòu)造函數(shù)中調(diào)用)/// private void SetCommandMethod(){ GetTokenCommand ??= new RelayCommand(o => !(string.IsNullOrEmpty(UserName) || string.IsNullOrEmpty(Password)), async o => { var req = new ReqGetToken() { userName = UserName, password = Password, };
          var res = await GetToken(req); if (res.Code) { Token = res.Token; } });}

          ?

          可以看到,在檢查命令是否可用的部分,沒有像樣板代碼那樣直接返回 true ,而是按照實(shí)際情況判斷,這樣的效果就是,當(dāng)條件不滿足時(shí),前臺(tái)相關(guān)控件自動(dòng)禁用:

          6a781a32cc089fdaa6eb95749f8f1dba.webp

          最后,經(jīng)過我們這樣寫,其實(shí)和 MVVM 模式已經(jīng)很接近了,只要把后臺(tái)所有代碼都移到另一個(gè)類,然后將頁面的 DataContext 重新指定一下,就能實(shí)現(xiàn)頁面顯示和業(yè)務(wù)邏輯分離了。

          瀏覽 35
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                    <th id="afajh"><progress id="afajh"></progress></th>
                    欧美三级韩国三级日本三斤在线观看 | 日韩有码第4页 | 天堂AV中文在线 | 亚洲美女被操 | 插插插视频 |