2010-09-22 26 views
6

Tengo un ListBox y quiero que se extienda el modo de selección. También quiero implementar la funcionalidad de arrastrar y soltar. El problema ahora es que si se presiona el mouse en un elemento seleccionado, se seleccionará inmediatamente como selección única en lugar de esperar al evento de mouse-up para hacer esto.WPF arrastre y suelte de un ListBox que tiene SelectionMode = Extended

Debido a este comportamiento, empezar a arrastrar varios elementos es casi imposible para el usuario porque siempre hace clic en la selección para comenzar a arrastrar, la selección cambia al elemento que está debajo del mouse e inicia la operación de arrastre con este elemento .

¿Existe una buena solución para este problema o incluso existe una solución oficial?

+0

vuelve a aceptar una respuesta diferente más adelante. así que si te gusta la otra respuesta mejor, acéptalo. – Rohit

+0

Recomiendo usar el siguiente enlace. Funciona muy bien. http://stackoverflow.com/a/23151248 – Youngjae

Respuesta

8

Esto es lo que hice. En su código DragDrop, suscríbase al PreviewMouseLeftButtonDown. Si el elemento que ya está haciendo clic está seleccionado, configure e.Handled en verdadero.

En mi ejemplo a continuación, identifico una parte del elemento del cuadro de lista como un control de arrastre (con protuberancias) para poder distinguir entre el elemento y una superficie de arrastre. Solo tenía que obtener la plantilla de datos del elemento del cuadro de lista y el comportamiento de arrastrar y soltar para acordar el nombre del elemento de arrastre.

El PreviewMouseLeftButtonDown de mi trabajo en progreso:

private void ItemsControl_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
{ 
    dragStartPoint = e.GetPosition(null); 

    ItemsControl itemsControl = this.AssociatedObject as ItemsControl; 
    if (itemsControl != null) 
    { 
     this.sourceItemContainer = itemsControl.ContainerFromElement((Visual)e.OriginalSource) as FrameworkElement; 
    } 

    // If this is an multiple or extended selection list box, and on a drag grip, then ensure the item being hit is selected 
    // This prevents the ItemsControl from using this MouseDown to change selection, except over a selected item's drag grip.    
    if ((this.IsMultipleSelectionListBox() == true) && (this.IsOriginalSourceDragGrip(e) != false) && (this.IsSourceListBoxItemSelected() == true)) 
    { 
     e.Handled = true; 
    } 
} 
+0

+1 Sí, al final, lo he resuelto de una manera similar. Gracias por la respuesta. Sin embargo, ya acepté la respuesta de MrDosu. Pero recomendaría su camino a otras personas que quieran resolver el mismo problema. – HCL

2

La solución más fácil que se me ocurre sería cambiar la ListBoxItem para seleccionar el MouseUp no hacia abajo como tal y cambiar el ContainerGenerator para servir a sus ListBoxItems personalizados:

public class CustomListBoxItem : ListBoxItem 
{ 
    protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) 
    { 
     //do nothing 
    } 

    protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) 
    { 
     base.OnMouseLeftButtonDown(e); 
    } 
} 

Es posible que tenga alguna lógica MouseLeave/LeftButtonDown si desea evitar la selección de diferentes elementos al pasar por la Lista mientras mantiene presionado el botón del mouse.

+0

+1 Buena solución. Sin embargo, estoy un poco ansioso porque no sé si invocar otro evento desde un método de invocación puede provocar problemas en versiones futuras de la FCL. – HCL

+0

Puede haber algo de artesanía para hacer cuando se espera que los EventArgs sean diferentes (como el estado del botón), pero al ver que se llama al controlador del evento no pude pensar en un escenario de cambio de ruptura. – MrDosu

+0

Lamentablemente, esto es demasiado simplista, porque en ciertos casos hay actividad de selección en el mouse hacia abajo. El comportamiento correcto es que seleccionar (o ampliar una selección) de un elemento no seleccionado se produce con el mouse hacia abajo (no se produce ningún cambio si ya está seleccionado), mientras que la eliminación de elementos ya seleccionados solo se produce con el mouse hacia arriba, y solo si no hay un cursor apreciable movimiento ocurrido. – CuriousKea

0

Uso PreviewMouseLeftButtonDown para agregar los elementos seleccionados para la operación de arrastre.

Cuestiones relacionadas