36

我想在鼠标单击 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事件,但它没有被调用。

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

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

马克

4

6 回答 6

55

我相信你的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)
{
}

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

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

于 2009-08-13T12:19:30.483 回答
22

我认为Andy的回答中的第一个选项 usingPreviewMouseLeftButtonDown是解决这个问题的方法。在 XAML 中,它看起来像这样:

<ListBox Name="testListBox">
    <ListBox.ItemContainerStyle>
        <Style TargetType="{x:Type ListBoxItem}">
            <EventSetter
                Event="PreviewMouseLeftButtonDown" 
                Handler="ListBox_MouseLeftButtonDown" />
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>
于 2009-08-13T16:26:23.717 回答
22

还有另一种方法 - 处理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
    }
}

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

于 2014-07-23T11:52:20.117 回答
10

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

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

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

于 2010-07-25T14:49:36.513 回答
2

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

于 2018-03-17T22:45:43.857 回答
0

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

于 2015-06-22T14:06:03.463 回答