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

mar*_*000 33 wpf events listbox 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));
Run Code Online (Sandbox Code Playgroud)

这是有效的,但它是为了它DoubleClick.虽然我不能让它工作一次.我试过MouseLeftButtonDownEvent- 因为似乎没有MouseClick事件,但它没有被调用.

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

我也尝试了子类化ListBoxItem和覆盖OnMouseLeftButtonDown- 但它也没有被调用.

And*_*ndy 49

我相信你的MouseLeftButtonDown处理程序没有被调用,因为在ListBox内部使用这个事件来激活它的SelectionChanged事件(想到在绝大多数情况下,SelectionChanged你只需要它).那就是说,你有几个选择.

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

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

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

private void OnMouseLeftButtonDown(object sender, RoutedEventArgs e)
{
}
Run Code Online (Sandbox Code Playgroud)

类处理程序在任何其他事件处理程序之前调用,但它们在整个应用程序中被调用指定类型的所有控件.因此,如果您有两个ListBoxes,那么只要ListBoxItem在其中任何一个中单击任何一个,就会调用此事件处理程序.

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

  • 有一件事,我想补充。不要使用 ButtonDown 事件。使用 ButtonUp 事件。按下按钮后立即执行操作的应用程序很奇怪。而且它还有一个用户交互的原因。在基本上所有流行的应用程序中,您可以通过在释放按钮之前将鼠标移开来取消按钮点击。 (2认同)

Ran*_*ngy 18

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

<ListBox Name="testListBox">
    <ListBox.ItemContainerStyle>
        <Style TargetType="{x:Type ListBoxItem}">
            <EventSetter Event="PreviewMouseLeftButtonDown" Handler="ListBox_MouseLeftButtonDown" />
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>
Run Code Online (Sandbox Code Playgroud)


Pav*_*l K 15

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

在XAML中:

<ListBox PreviewMouseDown="PlaceholdersListBox_OnPreviewMouseDown"/> 
Run Code Online (Sandbox Code Playgroud)

在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
    }
}
Run Code Online (Sandbox Code Playgroud)

受到这个答案的启发,但是它按名称使用listbox,我建议使用sender参数来避免不必要的依赖.


zen*_*dar 9

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

myListBox.AddHandler(UIElement.MouseDownEvent, 
        new MouseButtonEventHandler(ListBox_MouseDown), true);
Run Code Online (Sandbox Code Playgroud)

上面的第三个参数handledEventsToo确保将调用此处理程序,无论它是否已标记为Handled(ListBoxItem在ListBox中).
有关说明,请参阅将路由事件标记为已处理,以及类处理.
例如,请参阅如何附加到ListBox上的MouseDown事件 .