如何捕获 WPF 中 ListBox 中项目的鼠标单击?

发布于 2024-08-01 23:25:16 字数 1239 浏览 4 评论 0 原文

我想在鼠标单击列表框中的项目时收到通知,无论它是否已被选中。

我搜索并发现了这个:(http://kevin- berridge.blogspot.com/2008/06/wpf-listboxitem-double-click.html 查看评论)

private void AddDoubleClickEventStyle(ListBox listBox, MouseButtonEventHandler mouseButtonEventHandler)
{
    if (listBox.ItemContainerStyle == null)
        listBox.ItemContainerStyle = new Style(typeof(ListBoxItem));
    listBox.ItemContainerStyle.Setters.Add(new EventSetter()
    {
        Event = MouseDoubleClickEvent,
        Handler = mouseButtonEventHandler
    });
}

//Usage:
AddDoubleClickEventStyle(listView1, new MouseButtonEventHandler(listView1_MouseDoubleClick));

这可行,但它适用于 DoubleClick。 但我无法通过单击来使其工作。 我尝试了 MouseLeftButtonDownEvent - 因为似乎没有 MouseClick 事件,但它没有被调用。

一个更一般的附带问题:我如何才能看到哪些事件确实存在,哪些处理程序对应于它们以及它们何时实际执行某些操作? 例如,什么告诉我对于 MouseDoubleClickEvent 我需要 MouseButtonEventHandler? 也许对于 MouseLeftButtonDownEvent 我需要一些其他处理程序,这就是它不起作用的原因?

我还尝试子类化 ListBoxItem 并覆盖 OnMouseLeftButtonDown - 但它也没有被调用。

马克

I want to get notified when an item in a ListBox gets clicked by the mouse, whether it is already selected or not.

I searched and found this: (http://kevin-berridge.blogspot.com/2008/06/wpf-listboxitem-double-click.html see the comments)

private void AddDoubleClickEventStyle(ListBox listBox, MouseButtonEventHandler mouseButtonEventHandler)
{
    if (listBox.ItemContainerStyle == null)
        listBox.ItemContainerStyle = new Style(typeof(ListBoxItem));
    listBox.ItemContainerStyle.Setters.Add(new EventSetter()
    {
        Event = MouseDoubleClickEvent,
        Handler = mouseButtonEventHandler
    });
}

//Usage:
AddDoubleClickEventStyle(listView1, new MouseButtonEventHandler(listView1_MouseDoubleClick));

This works, but it does it for a DoubleClick. I can't get it working for a single click though. I tried MouseLeftButtonDownEvent - as there doesn't seem to be a MouseClick event, but it's not being called.

A bit more general side question: How can I see what events do exist and which handlers correspond to them and when they actually do something? For example, what tells me that for a MouseDoubleClickEvent I need a MouseButtonEventHandler? Maybe for a MouseLeftButtonDownEvent I need some other handler and that's why it's not working?

I also tried subclassing ListBoxItem and override OnMouseLeftButtonDown - but it doesn't get called either.

Marc

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

李白 2024-08-08 23:25:16

我相信您的 MouseLeftButtonDown 处理程序未被调用,因为 ListBox 在内部使用此事件来触发其 SelectionChanged 事件(想法是在绝大多数情况下,SelectionChanged 就是您所需要的)。 也就是说,你有几个选择。

首先,您可以改为订阅 PreviewLeftButtonDown 事件。 大多数路由事件都具有冒泡路由策略,这意味着生成事件的控件首先获取该事件,如果未处理,该事件将沿着可视树向上移动,从而使每个控件都有机会处理该事件。 另一方面,预览事件是隧道事件。 这意味着它们从可视化树的根部(通常是Window)开始,并向下到达生成事件的控件。 由于您的代码将有机会在 ListBoxItem 之前处理该事件,因此该事件将被触发(并且不会被处理),因此您的事件处理程序将被调用。 您可以通过将示例中的 MouseDoubleClickEvent 替换为 PreviewMouseLeftButtonDown 来实现此选项。

另一种选择是注册一个类处理程序,只要 ListBoxItem 触发 MouseLeftButtonDown 事件,该处理程序就会收到通知。 这样做是这样的:

EventManager.RegisterClassHandler(typeof(ListBoxItem),
    ListBoxItem.MouseLeftButtonDownEvent,
    new RoutedEventHandler(this.MouseLeftButtonDownClassHandler));

private void OnMouseLeftButtonDown(object sender, RoutedEventArgs e)
{
}

类处理程序在任何其他事件处理程序之前被调用,但它们是为整个应用程序中指定类型的所有控件调用的。 因此,如果您有两个 ListBox,那么每当在其中任何一个中单击任何 ListBoxItem 时,都会调用此事件处理程序。

至于第二个问题,了解给定事件所需的事件处理程序类型以及查看给定控件可用的事件列表的最佳方法是使用 MSDN 文档。 例如,ListBoxItem 处理的所有事件的列表位于 http://msdn.microsoft.com/en-us/library/system.windows.controls.listboxitem_events.aspx。 如果单击某个事件的链接,它会包含该事件的事件处理程序的类型。

I believe that your MouseLeftButtonDown handler is not called because the ListBox uses this event internally to fire its SelectionChanged event (with the thought being that in the vast majority of cases, SelectionChanged is all you need). That said, you have a couple of options.

First, you could subscribe to the PreviewLeftButtonDown event instead. Most routed events have a routing strategy of Bubbling, which means that the control that generated the event gets it first, and if not handled, the event works its way up the visual tree giving each control a chance at handling the event. The Preview events, on the other hand, are Tunneling. This means that they start at the root of the visual tree (generally Window), and work their way down to the control that generated the event. Since your code would get the chance to handle the event prior to the ListBoxItem, this will get fired (and not be handled) so your event handler will be called. You can implement this option by replacing MouseDoubleClickEvent in your sample with PreviewMouseLeftButtonDown.

The other option is to register a class handler that will be notified whenever a ListBoxItem fires the MouseLeftButtonDown event. That is done like this:

EventManager.RegisterClassHandler(typeof(ListBoxItem),
    ListBoxItem.MouseLeftButtonDownEvent,
    new RoutedEventHandler(this.MouseLeftButtonDownClassHandler));

private void OnMouseLeftButtonDown(object sender, RoutedEventArgs e)
{
}

Class Handlers are called before any other event handlers, but they're called for all controls of the specified type in your entire application. So if you have two ListBoxes, then whenever any ListBoxItem is clicked in either of them, this event handler will be called.

As for your second question, the best way to know what type of event handler you need for a given event, and to see the list of events available to a given control, is to use the MSDN documentation. For example, the list of all events handled by ListBoxItem is at http://msdn.microsoft.com/en-us/library/system.windows.controls.listboxitem_events.aspx. If you click on the link for an event, it includes the type of the event handler for that event.

不忘初心 2024-08-08 23:25:16

还有另一种方法 - 处理 PreviewMouseDown 事件并检查它是否由列表项触发:

在 XAML 中:

<ListBox PreviewMouseDown="PlaceholdersListBox_OnPreviewMouseDown"/> 

在代码隐藏中:

private void PlaceholdersListBox_OnPreviewMouseDown(object sender, MouseButtonEventArgs e)
{
    var item = ItemsControl.ContainerFromElement(sender as ListBox, e.OriginalSource as DependencyObject) as ListBoxItem;
    if (item != null)
    {
        // ListBox item clicked - do some cool things here
    }
}

受到 this 答案的启发,但它按名称使用列表框,我建议使用 sender 参数来避免不必要的依赖关系。

There is also another way - to handle PreviewMouseDown event and check if it was triggered by the list item:

In XAML:

<ListBox PreviewMouseDown="PlaceholdersListBox_OnPreviewMouseDown"/> 

In codebehind:

private void PlaceholdersListBox_OnPreviewMouseDown(object sender, MouseButtonEventArgs e)
{
    var item = ItemsControl.ContainerFromElement(sender as ListBox, e.OriginalSource as DependencyObject) as ListBoxItem;
    if (item != null)
    {
        // ListBox item clicked - do some cool things here
    }
}

Was inspired by this answer, but it uses listbox by name, I propose to use sender argument to avoid unnecessary dependencies.

终止放荡 2024-08-08 23:25:16

我认为 Andy 的答案中的第一个选项是使用 PreviewMouseLeftButtonDown 的方法去做这件事吧。 在 XAML 中,它看起来像这样:

<ListBox Name="testListBox">
    <ListBox.ItemContainerStyle>
        <Style TargetType="{x:Type ListBoxItem}">
            <EventSetter
                Event="PreviewMouseLeftButtonDown" 
                Handler="ListBox_MouseLeftButtonDown" />
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

I think the first option in Andy's answer, of using PreviewMouseLeftButtonDown, is the way to go about this. In XAML it would look like this:

<ListBox Name="testListBox">
    <ListBox.ItemContainerStyle>
        <Style TargetType="{x:Type ListBoxItem}">
            <EventSetter
                Event="PreviewMouseLeftButtonDown" 
                Handler="ListBox_MouseLeftButtonDown" />
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>
脱离于你 2024-08-08 23:25:16

还有另一种方法可以获取 ListBox 中的 MouseDown 事件。 您可以使用 AddHandler 方法的 handledEventsToo 签名为标记为已处理的事件添加事件处理程序:

myListBox.AddHandler(UIElement.MouseDownEvent, 
        new MouseButtonEventHandler(ListBox_MouseDown), true);

上面的第三个参数是 handledEventsToo,它确保此无论处理程序是否已标记为 HandledListBoxItem 在 ListBox 中的作用),都将被调用。
请参阅将路由事件标记为已处理以及类处理 进行解释。
请参阅
如何例如,附加到 ListBox 上的 MouseDown 事件

There is another way to get MouseDown event in ListBox. You can add event handler for events that are marked as handled by using handledEventsToo signature of AddHandler method:

myListBox.AddHandler(UIElement.MouseDownEvent, 
        new MouseButtonEventHandler(ListBox_MouseDown), true);

Third parameter above is handledEventsToo which ensures that this handler will be invoked no matter if it is already marked as Handled (which ListBoxItem does in ListBox).
See Marking Routed Events as Handled, and Class Handling for explanation.
See How to Attach to MouseDown Event on ListBox for example.

好倦 2024-08-08 23:25:16

您可以使用 Event="MouseLeftButtonUp"
"PreviewLeftButtonDown" 不同,它也会处理 ListBoxItem。

You can use Event="MouseLeftButtonUp"
Unlike "PreviewLeftButtonDown" it will get the ListBoxItem handled too.

帥小哥 2024-08-08 23:25:16

您可以使用SelectionChanged事件的SelectionChangedEventArgs参数通过AddedItems和RemovedItems来查找添加或删除了哪些项目,通常只有最新点击的项目,如果没有,则查看最后一个项目,即count-1。

You can use the SelectionChangedEventArgs argument of the SelectionChanged event to find what item is add or removed through AddedItems and RemovedItems, usually only have the latest clicked on, or if not, then look at the last item which is the count-1.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文