2010-03-30 16 views
25

WPF ListBox no tiene un evento de DoubleClick, al menos no tan lejos como puedo decir. ¿Hay alguna solución para este problema que me permita hacer doble clic en un elemento para que un controlador de eventos haga algo con él? Gracias por tu ayuda.WPF ListBoxItem haga doble clic en?

+4

Compruebe hacia fuera esta pregunta: ¿http://stackoverflow.com/questions/821564/double-click-a-list-item – Eclipse

Respuesta

4

Siempre puede anular la plantilla de control ListItem y manejar el evento de doble clic dentro de la plantilla, por ejemplo, en un borde invisible que contiene el contenido normal de ListBox.

This article shows you how to use a ControlTemplate with a ListBoxItem. Más allá de eso, simplemente agregue el controlador al elemento más externo de su plantilla de control.

Si tiene Expression Blend, puede usarlo para extraer la plantilla de control existente para que la modifique, de modo que no tenga que trabajar tanto para asegurarse de que el nuevo cuadro de lista se comporte igual que el anterior.

+0

encontrado una solución que funciona mejor - ver más abajo. Dejo la respuesta aceptada tal como está, simplemente porque aprecio la ayuda de Ben en este tema. –

31

Resulta que hay un evento MouseDoubleClick para el ListBox. Agregué este evento a mi ListBox e hice que el controlador de eventos procesara mi tarea, copiando el elemento seleccionado a otro ListBox. Entonces, cada vez que hago doble clic en un elemento, se copia.

+1

Esto es realmente útil. Yo no estaba usando plantillas de datos para mi lista (sólo quería mostrar algún texto), y esto me ahorra tener que envolver mi texto en un control de plantilla –

+7

Cabe señalar que los 'desencadena el evento ListBox.MouseDoubleClicked' cuando el ratón se hace doble clic en cualquier lugar dentro del control. IE: esto incluye clics dobles que no están en ningún 'ListBoxItem'. –

+1

@ChrisKerekes Tienes razón. Como referencia, creo que esto se puede resolver usando 'if (listBox.SelectedIndex == -1) return;'. – Marlos

13

Si está utilizando el enlace de datos, a continuación, este problema es muy fácil de resolver

<ListBox.ItemTemplate> 
    <DataTemplate> 
     <TextBlock Text="{Binding ObjectName}" 
      MouseDown="TextBlock_MouseDown"/> 
    </DataTemplate> 
</ListBox.ItemTemplate>  

Luego, en su código detrás, compruebe si hay un doble clic de la siguiente manera

private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e) 
{ 
    if (e.ClickCount>=2) 
    { 
     .... 
    } 
} 

Si el artículo se hace doble clic no se seleccionó antes del doble clic, entonces no aparecerá seleccionado en el controlador de eventos. Su lógica dentro de ese controlador necesita tener esto en cuenta

+2

Tenga en cuenta que con esta solución, si hace clic dentro de ListBoxItem pero fuera del bloque de texto (en caso de relleno/margen), el evento no se disparará. Esto puede o no ser deseable. – Clay

+0

^Para evitar esto, simplemente dale al TextBlock un 'Background', como' Transparent', y luego puedes hacer doble clic en cualquier lugar dentro de los límites de 'TextBlock'. –

+0

Gracias, esta es una solución mucho mejor para mí que el evento incorporado MouseDoubleClick de ListBox, ya que limita el doble clic a los elementos reales sin hackeo extendido. – germanSharper

3

He usado la respuesta anterior de David (que comienza con 'Resulta que hay un evento MouseDoubleClick para el ListBox.') Para generar una solución que se basa en su enfoque, pero se implementa con un comportamiento adjunto.

No digo que no deba tener ningún código porque sé que hay situaciones en las que no debe evitarse a cualquier precio. Sin embargo, este es otro ejemplo más de cómo puede convertir una solución basada en eventos en una solución compatible con MVVM que funciona mediante la conversión de enlace de eventos a comandos.

Esta mi código de comportamiento adjunto:

using System.Windows; 
using System.Windows.Controls.Primitives; 
using System.Windows.Input; 

/// <summary> 
/// Class implements a <seealso cref="Selector"/> double click 
/// to command binding attached behaviour. 
/// </summary> 
public class DoubleClickSelectorItem 
{ 
    #region fields 
    public static readonly DependencyProperty DoubleClickItemCommandProperty = 
     DependencyProperty.RegisterAttached("DoubleClickItemCommand", 
              typeof(ICommand), 
              typeof(DoubleClickSelectorItem), 
              new PropertyMetadata(null, 
              DoubleClickSelectorItem.OnDoubleClickItemCommand)); 
    #endregion fields 

    #region constructor 
    /// <summary> 
    /// Class constructor 
    /// </summary> 
    public DoubleClickSelectorItem() 
    { 

    } 
    #endregion constructor 

    #region properties 
    #endregion properties 

    #region methods 
    #region attached dependency property methods 
    public static ICommand GetDoubleClickItemCommand(DependencyObject obj) 
    { 
    return (ICommand)obj.GetValue(DoubleClickItemCommandProperty); 
    } 

    public static void SetDoubleClickItemCommand(DependencyObject obj, ICommand value) 
    { 
    obj.SetValue(DoubleClickItemCommandProperty, value); 
    } 
    #endregion attached dependency property methods 

    private static void OnDoubleClickItemCommand(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
    var uiElement = d as Selector; 

    // Remove the handler if it exist to avoid memory leaks 
    if (uiElement != null) 
     uiElement.MouseDoubleClick -= UIElement_MouseDoubleClick; 

    var command = e.NewValue as ICommand; 
    if (command != null) 
    { 
     // the property is attached so we attach the Drop event handler 
     uiElement.MouseDoubleClick += UIElement_MouseDoubleClick; 
    } 
    } 

    private static void UIElement_MouseDoubleClick(object sender, MouseButtonEventArgs e) 
    { 
    var uiElement = sender as Selector; 

    // Sanity check just in case this was somehow send by something else 
    if (uiElement == null) 
     return; 

    // Is there a selected item that was double clicked? 
    if (uiElement.SelectedIndex == -1) 
     return; 

    ICommand doubleclickCommand = DoubleClickSelectorItem.GetDoubleClickItemCommand(uiElement); 

    // There may not be a command bound to this after all 
    if (doubleclickCommand == null) 
     return; 

    // Check whether this attached behaviour is bound to a RoutedCommand 
    if (doubleclickCommand is RoutedCommand) 
    { 
     // Execute the routed command 
     (doubleclickCommand as RoutedCommand).Execute(uiElement.SelectedItem, uiElement); 
    } 
    else 
    { 
     // Execute the Command as bound delegate 
     doubleclickCommand.Execute(uiElement.SelectedItem); 
    }    
    } 
    #endregion methods 
} 

uso en XAML:

<ListBox ItemsSource="{Binding CurrentItems}" 
     behav:DoubleClickSelectorItem.DoubleClickItemCommand="{Binding Path=NavigateDownCommand}" 
     /> 
19

Es posible enlazar comandos con parámetros a ListBoxItem s sin necesidad de utilizar de código subyacente o comportamientos adjuntos, simplemente usando InputBindings con MouseBinding, como se muestra anteriormente en this answer.

Ejemplo ListBox con MouseBinding para LeftDoubleClick:

<ListBox ItemsSource="{Binding MyDataSource}"> 
    <ListBox.ItemTemplate> 
     <DataTemplate> 
      <TextBlock Text="{Binding MySourceItemName}"> 
       <TextBlock.InputBindings> 
        <MouseBinding MouseAction="LeftDoubleClick" 
            Command="{Binding DataContext.MyCommand, RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}" 
            CommandParameter="{Binding MySourceItemId}" /> 
       </TextBlock.InputBindings> 
      </TextBlock> 
     </DataTemplate> 
    </ListBox.ItemTemplate> 
</ListBox> 

Si el comando se define de la misma DataContext como el ItemsSource de la ListBox, que puede estar unido mediante el uso de la RelativeSource de unión como se incluye en el ejemplo.

+2

Esa es la mejor solución. Intenté EventToCommand antes de lo cual no funcionó. InputBindings funciona perfectamente. Los uso en StackPanel dentro de la plantilla de datos listbox. – BlueM

+0

Buena solución significativa. – AnjumSKhan

+0

Con mucho, la solución más sensata y robusta aquí. –

Cuestiones relacionadas