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

时间:2009-08-13 11:22:33

标签: wpf listbox events click listboxitem

我希望在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 - 但它也没有被调用。

马克

6 个答案:

答案 0 :(得分:49)

我认为您的MouseLeftButtonDown处理程序未被调用,因为ListBox在内部使用此事件来触发其SelectionChanged事件(考虑到在绝大多数情况下,{你只需{1}}。也就是说,你有几个选择。

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

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

MouseLeftButtonDown

类处理程序在任何其他事件处理程序之前调用,但它们在整个应用程序中被调用指定类型的所有控件。因此,如果您有两个EventManager.RegisterClassHandler(typeof(ListBoxItem), ListBoxItem.MouseLeftButtonDownEvent, new RoutedEventHandler(this.MouseLeftButtonDownClassHandler)); private void OnMouseLeftButtonDown(object sender, RoutedEventArgs e) { } ,那么只要在其中任何一个中单击任何ListBoxes,就会调用此事件处理程序。

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

答案 1 :(得分:17)

我认为Andy使用PreviewMouseLeftButtonDown的第一个答案是解决这个问题的方法。在XAML中它看起来像这样:

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

答案 2 :(得分:14)

还有另一种方法 - 处理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参数来避免不必要的依赖。

答案 3 :(得分:9)

答案 4 :(得分:0)

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

答案 5 :(得分:0)

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