Вопрос по events, listbox, wpf, listboxitem, click – Как захватить щелчок мышью на элементе в ListBox в WPF?

32

Я хочу получать уведомления, когда элемент в 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 - но он также не вызывается.

Марк

Я решил обернуть каждый элемент списка кнопкой и использовать вместо нее событие кнопки.stackoverflow.com/questions/17057022/… Dummy

Ваш Ответ

6   ответов
0

Ты можешь использоватьEvent="MouseLeftButtonUp"
В отличие от"PreviewLeftButtonDown" он также обработает ListBoxItem.

0

ctionChanged, чтобы найти, какой элемент добавляется или удаляется с помощью AddedItems и RemovedItems, обычно на него нажимают только последние, или, если нет, то посмотрите на последний элемент, который является count-1.

48

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, Если щелкнуть ссылку для события, она включает тип обработчика события для этого события.

@StefanFabian да, но элементы в списке обычно выбираются в mousedown. И удаление мыши все еще может работать.
Господи, это хороший ответ!
Я хотел бы добавить одну вещь. Не используйте событие ButtonDown. Используйте событие ButtonUp. Приложения, которые делают вещи, как только вы удерживаете кнопку, просто странные. И это также имеет причину взаимодействия с пользователем. Практически во всех популярных приложениях вы можете отменить нажатие кнопки, отодвинув мышь перед тем, как отпустить кнопку.
@PaulGibson Хм. Я предполагаю, что они приняли дизайнерское решение, которое вызывается всегда и щелкается только в том случае, если оно не отменено. Таким образом, вам придется самостоятельно проверять, находится ли мышь над элементом, если вы хотите отменить функцию.
@ StefanFabian Я пробовал оба события предварительного просмотра (вверх и вниз), и мне нравится, что вы думаете, что с помощью вверх вы можете вывести мышь из-под контроля и отменить щелчок, но я не вижу, чтобы это произошло. Независимо от того, где находится мышь, когда я отпускаю кнопку, мое событие вызывается (используя метод триггеров System.Windows.Interaction).
13

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
    }
}

Был вдохновленэтот ответ, но он использует список по имени, я предлагаю использовать аргумент отправителя, чтобы избежать ненужных зависимостей.

в любом случае, чтобы найти индексListBoxItem на что нажали?
На данный момент лучшее решение, которое я нашел, - это перебирать список элементов, пока не найдете совпадение. Это работает для моего случая, так как у меня есть очень маленькие списки, но это не может хорошо масштабироваться для других.
9

авить обработчик событий для событий, помеченных как обработанные с помощьюhandledEventsToo подписьAddHandler метод:

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

Третий параметр вышеhandledEventsToo что гарантирует, что этот обработчик будет вызываться независимо от того, помечен ли он какHandled (которыйListBoxItem делает в ListBox).
УвидетьMarking Routed Events as Handled, and Class Handling для объяснения.
УвидетьHow to Attach to MouseDown Event on ListBox  например.

17

что первый ответ Энди об использовании PreviewMouseLeftButtonDown - это способ сделать это. В XAML это будет выглядеть так:

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

Похожие вопросы