天天看點

【wpf】Command Binding 指令綁定的使用前言Command BindingCommandManager強制觸發滑鼠和鍵盤

前言

這次講解的指令綁定,主要解決的問題是,為實作MVVM模式進行鋪墊,實作前背景邏輯的解耦。

我們知道如果Button直接實作Click事件,那麼實作的邏輯必然在Window背景代碼中,為了實作MVVM,我要将業務邏輯放在ViewMode裡面,這時需要Command Binding。

Command Binding

使用Command 替換 Click

前台代碼:

<Button Grid.Row="2"  
    Command="{Binding BtnSaveCommand}"
    CommandParameter="{Binding RelativeSource={RelativeSource Self}}">儲存</Button>
           

建立CommandBase類

然後建立CommandBase類,該類實作ICommand接口。

ICommand需要實作一個事件:CanExecuteChanged

兩個方法: Execute, CanExecute

Execute 是指令促發後,系統會調用的回調函數

CanExecute 是當CanExecuteChanged事件觸發後,體統會調用它,并更具它的傳回值判斷控件是否可用。

public class CommandBase : ICommand
{
    public event EventHandler CanExecuteChanged;
    public Action<object> DoExecute { get; set; }
    
    // 這裡給個預設的值,不實作就傳回true
    public Func<object, bool> DoCanExecute { get; set; } = new Func<object, bool>(obj => true);

    public bool CanExecute(object parameter)
    {
        // 讓執行個體去實作這個委托
        return DoCanExecute?.Invoke(parameter) == true;// 綁定的對象 可用
    }

    public void Execute(object parameter)
    {
        // 讓執行個體去實作這個委托
        DoExecute?.Invoke(parameter);
    }


    //目的 就是觸發一次CanExecuteChanged事件   
    public void DoCanExecuteChanged()
    {
        // 觸發事件的目的就是重新調用CanExecute方法
        CanExecuteChanged?.Invoke(this, EventArgs.Empty);
    }
}
           

ViewMode中執行個體化指令

public CommandBase BtnSaveCommand { get; set; }

public ConfigInfoViewMode()
{

    BtnSaveCommand = new CommandBase()
    {
        DoExecute = new Action<object>(SaveTo),
        DoCanExecute = new Func<object, bool>(CanSave)
    };
}

//最終按鈕會觸發到改函數
void Save(object obj)
{
    
}

//決定按鍵是否可用(這也是指令額外的一個作用)
// 通過調用DoCanExecuteChanged,可以觸發該元素
public bool CanSave(object obj)
{
    return true;
}
           

事件觸發

//目的 就是觸發一次CanExecuteChanged事件   
    public void DoCanExecuteChanged()
    {
        // 觸發事件的目的就是重新調用CanExecute方法
        CanExecuteChanged?.Invoke(this, EventArgs.Empty);
    }
           

觸發事件的目的就是重新調用CanExecute方法,進而從新判斷控件是否可用。

但是這個DoCanExecuteChanged(),是需要我們人為調用的。

CommandManager

如果不想手動調用DoCanExecuteChanged(),還有一個辦法就是CommandManager。

另外一種寫法可以讓系統去調用,我們需要一個新的知識點CommandManager

以下兩種寫法都可以,隻需要在定義CanExecuteChanged時稍微改動一下:

// 通知:目前按鈕檢查可用條件     觸發 一次CanExecute
// 寫法一
public event EventHandler? CanExecuteChanged
{
    add { CommandManager.RequerySuggested += value; }
    remove { CommandManager.RequerySuggested -= value; }
}

//寫法二
public event EventHandler? CanExecuteChanged
{
    add => CommandManager.RequerySuggested += value; 
    remove => CommandManager.RequerySuggested -= value; 
}
           

這裡的意思是,通過靜态變量CommandManager将CanExecuteChanged挂載到,RequerySuggested 這個事件上,這裡的value是指CanExecuteChanged本身,下圖可以證明。(這個和屬性的value有着異曲同工之妙)

【wpf】Command Binding 指令綁定的使用前言Command BindingCommandManager強制觸發滑鼠和鍵盤

 從此之後,這個檢測調用的工作交給系統。

【wpf】Command Binding 指令綁定的使用前言Command BindingCommandManager強制觸發滑鼠和鍵盤

我發現這個檢測的時機其實和綁定有關。

<TextBox Text="{Binding mainModel.Value1,UpdateSourceTrigger=PropertyChanged}"/>
<TextBox Text="{Binding mainModel.Value3}"/>
           

我們在檢擦函數中這麼寫的:

// Hello指令的的可用判斷邏輯
public bool CanHello(object obj)
{
    // 指令可用條件
    // 當調用 CanExecuteChanged  事件後,重新進行條件檢查
    return this.mainModel.Value1 != 0;
}


public bool CanWorld(object obj)
{
    return this.mainModel.Value3 != 0;
}
           

也就是說,TextBox中的值會決定Button是否可用!

那麼第一個TextBox的值,隻要一發生改變,那麼就會觸發檢查是否可用,而第二個TextBox隻有

失去焦點的時候,才會觸發檢查。

這裡有個小疑問,我們的Command是寫在Button上的,是以判斷是Button是否可用,同時Command實作了CanExecuteChanged事件,并挂載到了全局,以便系統調用,那系統是怎麼知道

變化的Value和Button的關系的呢?也不知道微軟是什麼時候将這個指和Button關聯上的。

強制觸發

當然,此時如果你覺得你想在某個時刻進行強制觸發檢測,也是可以的,還是使用CommandManager這個靜态變量:

CommandManager.InvalidateRequerySuggested();
           

滑鼠和鍵盤

寫道這裡,其實還存在一個問題,Button的Command是由但是觸發的,如果我想通過輕按兩下或者快捷鍵觸發怎麼辦呢?

InputBindings

InputBindings,滿足你的需求:

<Button Content="Button">
    <Button.InputBindings>
        <MouseBinding MouseAction="LeftDoubleClick"
                      Command="{Binding Btn1Command}"
                      CommandParameter="123"/>
        <KeyBinding Key="Q" Modifiers="Alt"
                    Command="{Binding Btn1Command}"
                    CommandParameter="123"/>
    </Button.InputBindings>
</Button>
           

MouseBinding 中的MouseAction還有如下操作: 

  • 單擊滑鼠左鍵 :LeftClick
  • 輕按兩下滑鼠左鍵:LeftDoubleClick
  • 單擊滑鼠中鍵 :MiddleClick
  • 輕按兩下滑鼠中鍵:MiddleDoubleClick
  • 單擊滑鼠右鍵:RightClick
  • 輕按兩下滑鼠右鍵:RightDoubleClick
  • 不執行任何操作:None
  • 旋轉滑鼠滾輪:WheelClick

KeyBinding 

KeyBinding 可以幫我們實作快捷鍵和快捷鍵組合,簡直完美~~。

繼續閱讀