Cómo capturar un mouse, haga clic en un elemento en un ListBox en WPF?
events click (6)
Deseo recibir una notificación cuando un elemento en un ListBox recibe un clic con el mouse, ya sea que esté seleccionado o no.
Busqué y encontré esto: ( http://kevin-berridge.blogspot.com/2008/06/wpf-listboxitem-double-click.html vea los comentarios)
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));
Esto funciona, pero lo hace para un DoubleClick
. Sin embargo, no puedo hacer que funcione con un solo clic. MouseLeftButtonDownEvent
, ya que no parece haber un evento MouseClick
, pero no se está llamando.
Una pregunta secundaria más general: ¿cómo puedo ver qué eventos existen y qué manejadores les corresponden y cuándo realmente hacen algo? Por ejemplo, ¿qué me dice que para MouseDoubleClickEvent
necesito MouseButtonEventHandler
? Tal vez para un MouseLeftButtonDownEvent
necesito algún otro controlador y es por eso que no está funcionando?
También intenté subclasificar ListBoxItem
y reemplazar OnMouseLeftButtonDown
, pero tampoco se llama.
Bagazo
Creo que la primera respuesta de Andy de usar PreviewMouseLeftButtonDown es la forma de hacerlo. En XAML se vería así:
<ListBox Name="testListBox">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="ListBox_MouseLeftButtonDown" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
Creo que su manejador MouseLeftButtonDown
no se llama porque el ListBox
utiliza este evento internamente para activar su evento SelectionChanged
(con la idea de que en la gran mayoría de los casos, SelectionChanged
es todo lo que necesita). Dicho eso, tienes un par de opciones.
En primer lugar, puede suscribirse al evento PreviewLeftButtonDown
lugar. La mayoría de los eventos enrutados tienen una estrategia de enrutamiento de Bubbling, lo que significa que el control que generó el evento lo recibe primero, y no manejado, el evento avanza en el árbol visual, dando a cada control la oportunidad de manejar el evento. Los eventos de Vista previa, por otro lado, son Túneles. Esto significa que comienzan en la raíz del árbol visual (generalmente Window
), y se abren camino hasta el control que generó el evento. Como su código tendría la posibilidad de manejar el evento antes de ListBoxItem
, se disparará (y no se manejará) para que se llame al controlador de eventos. Puede implementar esta opción reemplazando MouseDoubleClickEvent
en su muestra con PreviewMouseLeftButtonDown
.
La otra opción es registrar un controlador de clase que se notificará cada vez que un ListBoxItem
el evento MouseLeftButtonDown
. Eso se hace así:
EventManager.RegisterClassHandler(typeof(ListBoxItem),
ListBoxItem.MouseLeftButtonDownEvent,
new RoutedEventHandler(this.MouseLeftButtonDownClassHandler));
private void OnMouseLeftButtonDown(object sender, RoutedEventArgs e)
{
}
Los manejadores de clase se llaman antes que cualquier otro manejador de eventos, pero son llamados para todos los controles del tipo especificado en toda su aplicación. Entonces, si tiene dos ListBoxes
, cada vez que se ListBoxItem
clic en ListBoxItem
en cualquiera de ellos, se llamará a este controlador de eventos.
En cuanto a su segunda pregunta, la mejor manera de saber qué tipo de controlador de eventos necesita para un evento determinado y ver la lista de eventos disponibles para un control determinado es utilizar la documentación de MSDN. Por ejemplo, la lista de todos los eventos manejados por ListBoxItem
está en http://msdn.microsoft.com/en-us/library/system.windows.controls.listboxitem_events.aspx . Si hace clic en el enlace de un evento, incluye el tipo del controlador de eventos para ese evento.
Hay otra forma de obtener el evento MouseDown en ListBox. Puede agregar el controlador de eventos para los eventos que están marcados como gestionados mediante el uso de la firma AddHandler
método AddHandler
:
myListBox.AddHandler(UIElement.MouseDownEvent,
new MouseButtonEventHandler(ListBox_MouseDown), true);
El tercer parámetro anterior es handledEventsToo
que garantiza que se invocará este controlador independientemente de si ya está marcado como ListBoxItem
(que ListBoxItem
hace en ListBox).
Consulte Marcado de eventos enrutados como manejado y Manejo de clases para obtener una explicación.
Consulte Cómo adjuntar al evento MouseDown en ListBox, por ejemplo.
Puede usar Event="MouseLeftButtonUp"
A diferencia de "PreviewLeftButtonDown"
obtendrá el ListBoxItem manejado también.
Puede usar el argumento SelectionChangedEventArgs del evento SelectionChanged para encontrar qué elemento se agrega o quita a través de AddedItems y RemovedItems; por lo general, solo se hace clic en el último clic o, si no, mira el último elemento, el recuento-1.
También hay otra forma: manejar el evento PreviewMouseDown
y verificar si fue desencadenado por el elemento de la lista:
En XAML:
<ListBox PreviewMouseDown="PlaceholdersListBox_OnPreviewMouseDown"/>
En código subyacente:
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
}
}
Fue inspirado por this respuesta, pero usa listbox por nombre, propongo usar el argumento del remitente para evitar dependencias innecesarias.