更改布局时,防止WPF ListBox在鼠标下选择项目 [英] Prevent WPF ListBox from selecting item under mouse when layout changes

查看:434
本文介绍了更改布局时,防止WPF ListBox在鼠标下选择项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果在按住鼠标按钮的同时WPF ListBox收到MouseMove事件,它将更改列表框的选择.也就是说,如果在项目#1上单击鼠标,然后将其拖到项目#2上,它将取消选择项目#1并选择项目#2. 如何防止这种情况?

If a WPF ListBox gets a MouseMove event while the mouse button is held down, it will change the listbox's selection. That is, if you click the mouse on item #1, and then drag over item #2, it will deselect item #1 and select item #2 instead. How can I prevent this?

那是简短的版本.稍长一点的版本是这样的:当用户双击ListBox中的项目时,我对布局进行了其他更改,包括在ListBox上方显示其他控件.这会将ListBox向下移动,这意味着鼠标现在位于与用户双击时不同的ListBoxItem上.

That's the short version. The slightly longer version is this: When the user double-clicks an item in my ListBox, I make other changes to my layout, which includes showing other controls above the ListBox. This moves the ListBox downwards, which means the mouse is now positioned over a different ListBoxItem than it was when the user double-clicked.

由于我是根据DoubleClick事件(这是鼠标按下事件)对这些布局进行更改的,因此很有可能在此布局更改完成后仍会按下鼠标按钮,这意味着WPF将向ListBox发送一个MouseMove事件(因为鼠标相对于ListBox的位置已更改). ListBox将其视为拖动,并选择鼠标下的事件.

Since I make these layout changes in response to the DoubleClick event (which is a mouse-down event), it's very likely that the mouse button will still be pressed when this layout change completes, which means WPF will send the ListBox a MouseMove event (since the mouse's position, relative to the ListBox, has changed). ListBox treats this as a drag, and selects the event that's now under the mouse.

我不希望在获得双击事件的时间与用户释放鼠标的时间(可能在布局更改后很好)之间进行选择更改.我怀疑实现此目的的最简单方法是禁用拖动时更改选择"行为,但我愿意接受其他建议.

I don't want the selection to change between the time I get the double-click event and the time the user releases the mouse (which might be well after the layout changes). I suspect that the simplest way to achieve this would be to disable the "change selection on drag" behavior, but I'm open to other suggestions.

如何在双击时锁定"所选内容,并防止更改直到鼠标悬停?

How can I "lock in" the selection on double-click, and prevent it from changing until mouseup?

推荐答案

ILSpy 中进行了一些挖掘之后,我发现没有任何属性可以禁用拖动以选择"行为,也没有可以标记为已处理"的事件来阻止它.

After some digging around in ILSpy, I found that there's no property that disables the "drag to select" behavior, nor is there an event I can mark as Handled to stop it.

但是有一个很好的拐点可以更改此行为:ListBoxItem.OnMouseEnter是虚拟的,它回调到列表框中以更改选择.它似乎并没有做任何实质性的事情,所以我要做的就是覆盖它,什么也不做.

But there is a good inflection point for changing this behavior: ListBoxItem.OnMouseEnter is virtual, and it calls back into the listbox to change the selection. It doesn't seem to do anything else substantive, so all I need to do is override it and do nothing.

事实证明,以上内容仅在您将鼠标移到列表框内时,使选择保持不变.如果将鼠标移到列表框的上方或下方都无济于事-然后自动滚动会启动并移动所选内容.大多数自动滚动代码还是使用非虚拟方法.看来,防止自动滚动的最佳方法可能是禁用鼠标捕获. ListBoxItem上的另一个重写可以解决此问题.

As it turns out, the above only keeps the selection from changing while you move the mouse around inside the listbox. It doesn't help if you move the mouse above or below the listbox -- then the auto-scroll kicks in and moves the selection. Most of the auto-scroll code is again in non-virtual methods; it looks like the best way to prevent auto-scroll is probably to disable mouse capture. Another override on ListBoxItem can take care of this.

使用我自己的ListBoxItem后代的最佳方法似乎是从ListBox继承.最终代码如下所示:

It looks like the best way to use my own ListBoxItem descendant is to descend from ListBox. The final code looks something like this:

public class ListBoxEx : ListBox
{
    protected override DependencyObject GetContainerForItemOverride()
    {
        return new ListBoxExItem();
    }
    protected override bool IsItemItsOwnContainerOverride(object item)
    {
        return item is ListBoxExItem;
    }
}
public class ListBoxExItem : ListBoxItem
{
    private Selector ParentSelector
    {
        get { return ItemsControl.ItemsControlFromItemContainer(this) as Selector; }
    }

    protected override void OnMouseEnter(MouseEventArgs e)
    {
    }
    protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
    {
        base.OnMouseLeftButtonDown(e);
        ParentSelector?.ReleaseMouseCapture();
    }
}

这篇关于更改布局时,防止WPF ListBox在鼠标下选择项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆