Come catturare un clic del mouse su un object in un ListBox in WPF?

Voglio ricevere una notifica quando un object in un ListBox viene cliccato con il mouse, sia che sia già selezionato o meno.

Ho cercato e trovato questo: ( http://kevin-berridge.blogspot.com/2008/06/wpflistboxitem-double-click.html vedere i commenti)

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)); 

Funziona, ma lo fa per un DoubleClick . Non riesco a farlo funzionare per un solo clic però. Ho provato MouseLeftButtonDownEvent – poiché non sembra essere un evento MouseClick , ma non viene chiamato.

Una domanda un po ‘più generale: come posso vedere quali eventi esistono e quali gestori corrispondono a loro e quando effettivamente fanno qualcosa? Ad esempio, cosa mi dice che per un MouseDoubleClickEvent ho bisogno di un MouseButtonEventHandler ? Forse per un MouseLeftButtonDownEvent ho bisogno di qualche altro gestore ed è per questo che non funziona?

Ho anche provato la sottoclass di ListBoxItem e l’override di OnMouseLeftButtonDown – ma non viene chiamato neanche.

Marc

Credo che il tuo gestore MouseLeftButtonDown non venga chiamato perché il ListBox usa internamente questo evento per MouseLeftButtonDown suo evento SelectionChanged (con il pensiero che nella maggior parte dei casi, SelectionChanged è tutto ciò che serve). Detto questo, hai un paio di opzioni.

In primo luogo, è ansible iscriversi invece all’evento PreviewLeftButtonDown . La maggior parte degli eventi indirizzati ha una strategia di routing di Bubbling, il che significa che il controllo che ha generato l’evento lo ottiene per primo, e non ha gestito l’evento che si sviluppa lungo l’albero visivo dando a ciascun controllo la possibilità di gestire l’evento. Gli eventi di anteprima, d’altra parte, sono Tunneling. Ciò significa che iniziano alla radice dell’albero visivo (generalmente Window ) e si dirigono verso il controllo che ha generato l’evento. Dal momento che il tuo codice avrà la possibilità di gestire l’evento prima di ListBoxItem , questo verrà generato (e non gestito) in modo che il tuo gestore di eventi venga chiamato. È ansible implementare questa opzione sostituendo MouseDoubleClickEvent nel campione con PreviewMouseLeftButtonDown .

L’altra opzione è di registrare un gestore di class che verrà avvisato ogni volta che un object ListBoxItem MouseLeftButtonDown evento MouseLeftButtonDown . Questo è fatto in questo modo:

 EventManager.RegisterClassHandler(typeof(ListBoxItem), ListBoxItem.MouseLeftButtonDownEvent, new RoutedEventHandler(this.MouseLeftButtonDownClassHandler)); private void OnMouseLeftButtonDown(object sender, RoutedEventArgs e) { } 

I gestori di class vengono chiamati prima di qualsiasi altro gestore di eventi, ma vengono chiamati per tutti i controlli del tipo specificato nell’intera applicazione. Quindi, se hai due ListBoxes , allora ogni volta che viene fatto clic su qualsiasi ListBoxItem in uno di essi, verrà chiamato questo gestore di eventi.

Per quanto riguarda la seconda domanda, il modo migliore per sapere quale tipo di gestore di eventi è necessario per un determinato evento e per visualizzare l’elenco di eventi disponibili per un determinato controllo è utilizzare la documentazione MSDN. Ad esempio, l’elenco di tutti gli eventi gestiti da ListBoxItem è disponibile all’indirizzo http://msdn.microsoft.com/en-us/library/system.windows.controls.listboxitem_events.aspx . Se fai clic sul link per un evento, include il tipo di gestore eventi per quell’evento.

Penso che la prima risposta di Andy sull’uso di PreviewMouseLeftButtonDown sia la strada da percorrere per questo. In XAML sembrerebbe questo:

      

C’è anche un altro modo: per gestire PreviewMouseDown evento PreviewMouseDown e verificare se è stato triggersto dall’elemento dell’elenco:

In XAML:

  

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

È stato ispirato da questa risposta, ma usa listbox per nome, propongo di usare l’argomento mittente per evitare dipendenze non necessarie.

C’è un altro modo per ottenere l’evento MouseDown in ListBox. È ansible aggiungere il gestore eventi per gli eventi contrassegnati come gestiti utilizzando la firma handledEventsToo del metodo AddHandler :

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

Il terzo parametro sopra è handledEventsToo da handledEventsToo che garantisce che questo gestore venga invocato, indipendentemente dal fatto che sia già contrassegnato come Handled (che ListBoxItem esegue in ListBox).
Vedi Marcatura degli eventi instradati come gestiti e Gestione delle classi per la spiegazione.
Ad esempio, vedi Come albind all’evento MouseDown su ListBox .

È ansible utilizzare l’argomento SelectionChangedEventArgs dell’evento SelectionChanged per trovare l’elemento da aggiungere o rimuovere tramite AddedItems e RemovedItems, in genere solo l’ultimo clic su, o in caso contrario, quindi esaminare l’ultimo elemento che è il count-1.

Puoi utilizzare Event="MouseLeftButtonUp"
A differenza di "PreviewLeftButtonDown" , riceverà anche il ListBoxItem.