如何捕获 WPF 中 ListBox 中项目的鼠标单击?
我想在鼠标单击列表框中的项目时收到通知,无论它是否已被选中。
我搜索并发现了这个:(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
- 但它也没有被调用。
马克
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我相信您的
MouseLeftButtonDown
处理程序未被调用,因为ListBox
在内部使用此事件来触发其SelectionChanged
事件(想法是在绝大多数情况下,SelectionChanged
就是您所需要的)。 也就是说,你有几个选择。首先,您可以改为订阅
PreviewLeftButtonDown
事件。 大多数路由事件都具有冒泡路由策略,这意味着生成事件的控件首先获取该事件,如果未处理,该事件将沿着可视树向上移动,从而使每个控件都有机会处理该事件。 另一方面,预览事件是隧道事件。 这意味着它们从可视化树的根部(通常是Window
)开始,并向下到达生成事件的控件。 由于您的代码将有机会在ListBoxItem
之前处理该事件,因此该事件将被触发(并且不会被处理),因此您的事件处理程序将被调用。 您可以通过将示例中的MouseDoubleClickEvent
替换为PreviewMouseLeftButtonDown
来实现此选项。另一种选择是注册一个类处理程序,只要
ListBoxItem
触发MouseLeftButtonDown
事件,该处理程序就会收到通知。 这样做是这样的:类处理程序在任何其他事件处理程序之前被调用,但它们是为整个应用程序中指定类型的所有控件调用的。 因此,如果您有两个
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 theListBox
uses this event internally to fire itsSelectionChanged
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 (generallyWindow
), 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 theListBoxItem
, this will get fired (and not be handled) so your event handler will be called. You can implement this option by replacingMouseDoubleClickEvent
in your sample withPreviewMouseLeftButtonDown
.The other option is to register a class handler that will be notified whenever a
ListBoxItem
fires theMouseLeftButtonDown
event. That is done like this: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 anyListBoxItem
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.还有另一种方法 - 处理
PreviewMouseDown
事件并检查它是否由列表项触发:在 XAML 中:
在代码隐藏中:
受到 this 答案的启发,但它按名称使用列表框,我建议使用 sender 参数来避免不必要的依赖关系。
There is also another way - to handle
PreviewMouseDown
event and check if it was triggered by the list item:In XAML:
In codebehind:
Was inspired by this answer, but it uses listbox by name, I propose to use sender argument to avoid unnecessary dependencies.
我认为 Andy 的答案中的第一个选项是使用
PreviewMouseLeftButtonDown
的方法去做这件事吧。 在 XAML 中,它看起来像这样: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 中的 MouseDown 事件。 您可以使用
AddHandler
方法的handledEventsToo
签名为标记为已处理的事件添加事件处理程序:上面的第三个参数是
handledEventsToo
,它确保此无论处理程序是否已标记为Handled
(ListBoxItem
在 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 ofAddHandler
method:Third parameter above is
handledEventsToo
which ensures that this handler will be invoked no matter if it is already marked asHandled
(whichListBoxItem
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.
您可以使用
Event="MouseLeftButtonUp"
与
"PreviewLeftButtonDown"
不同,它也会处理 ListBoxItem。You can use
Event="MouseLeftButtonUp"
Unlike
"PreviewLeftButtonDown"
it will get the ListBoxItem handled too.您可以使用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.