1. 程式人生 > 其它 >溫故知新,分流WPF的按鈕單擊和整個區域雙擊事件響應,治癒錯亂的互動應答

溫故知新,分流WPF的按鈕單擊和整個區域雙擊事件響應,治癒錯亂的互動應答

背景

在WPF客戶端專案中,遇到一個異常,一個DataGrid表格元件中,已經存在了一個全域性的雙擊事件,還存在一個單擊按鈕,這兩個按鈕繫結的事件和作用是同一個,然後測試人員就發現,快速在單擊按鈕上單擊,就會產生誤觸事件,出現點2次,實際上觸發了3次的情況。

其實也很好理解,因為快速單擊兩次就同時觸發了雙擊事件嘛,所以我們需要分流按鈕單擊和整個區域雙擊事件響應,來治理這個情況。

解決方案

移除原來的雙擊事件

這裡的思路,主要是改造雙擊事件,全域性的雙擊事件是有問題的。

<i:EventTrigger EventName="MouseDoubleClick">
    <i:InvokeCommandAction  
        Command="{Binding AddCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}}"
        CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}, Path=SelectedItem}"
        />
</i:EventTrigger>

我們把這段註釋掉。

監聽滑鼠左鍵按下事件

<i:EventTrigger EventName="MouseLeftButtonDown">
    <command:EventToCommand
        PassEventArgsToCommand="True"
        Command="{Binding MouseLeftButtonDownCommand}"
        />
</i:EventTrigger>

這裡我們通過繫結的EventToCommand方法來監聽MouseLeftButtonDown這個動作的EventArgs

private MouseButtonEventArgs _mouseButtonEventArgs;
public ICommand MouseLeftButtonDownCommand
{
    get
    {
        return new RelayCommand<MouseButtonEventArgs>((args) =>
        {
            _mouseButtonEventArgs = args;
        });
    }
}

在ViewModel裡面,我們來繫結接收來自介面的這個EventArgs,可以暫時託管在臨時變數_mouseButtonEventArgs

中即可。

響應滑鼠左鍵按下事件

<i:EventTrigger EventName="MouseLeftButtonDown">
    <i:InvokeCommandAction
        Command="{Binding MouseLeftButtonDown, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}}"
        CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}, Path=SelectedItem}"
        />
</i:EventTrigger>

這裡還是老辦法,通過InvokeCommandAction方法響應MouseLeftButtonDown事件,並且自動把當前DataGirdSelectedItem帶過去。

在ViewModel裡面,我們通過MouseLeftButtonDown來接收並且響應滑鼠左鍵按下事件。

public ICommand MouseLeftButtonDown
{
    get
    {
        return new RelayCommand<SelectDto>((selectitem) =>
        {
            if (_mouseButtonEventArgs != null)
            {
                switch (_mouseButtonEventArgs.ClickCount)
                {
                    case 2:
                    {
                        if (selectitem != null)
                        {
                            // TODO
                        }
                    }
                    break;
                }
            }

        });
    }
}

通過雙擊和單擊事件的錯開,我們成功分流了兩個互動,這下,快速單擊不會觸發雙擊了,而雙擊功能也得到了保留。

這裡根據需要,看是否需要新增繫結前的DataContext.引數哈。

參考