温故知新,分流WPF的按钮单击和整个区域双击事件响应,治愈错乱的交互应答

背景

在WPF客户端项目中,遇到一个异常,一个DataGrid表格组件中,已经存在了一个全局的双击事件,还存在一个单击按钮,这两个按钮绑定的事件和作用是同一个,然后测试人员就发现,快速在单击按钮上单击,就会产生误触事件,出现点2次,实际上触发了3次的情况。

image

其实也很好理解,因为快速单击两次就同时触发了双击事件嘛,所以我们需要分流按钮单击和整个区域双击事件响应,来治理这个情况。

解决方案

移除原来的双击事件

这里的思路,主要是改造双击事件,全局的双击事件是有问题的。

<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.参数哈。

参考

posted @ 2021-07-13 15:19  TaylorShi  阅读(659)  评论(0编辑  收藏  举报