views:

64

answers:

2

I have a ListBox and want the selection-mode to be extended. Also I want have to implement drag and drop functionality. The problem now is, that if the mouse is clicked on a selected item, it will be immediately be selected as single selection instead of waiting to the mouse-up-event for doing this.

Due to this behaviour, start dragging multiple items is for the user quasi impossible because always he clicks on the selection to start dragging, the selection changes to the item that is under the mouse and starts the drag-operation with this item.

Is there a good workaround for this problem or does even exists an official solution?

+1  A: 

The easiest workaround i can think of would be to change the ListBoxItem to select on MouseUp not Down like so and change the ContainerGenerator to serve your custom ListBoxItems:

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

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

You might need some MouseLeave/LeftButtonDown logic if you want to prevent different items selecting when moving through the List while holding the mouse button down.

MrDosu
+1 Nice solution. However I'm a litte anxious because I don't know if invoking another event from within an invocation-method may lead to problems in future versions of the FCL.
HCL
There might be some crafting to do when the EventArgs are expected to be different (like button state), but seeing the handler of the event is just called I couldnt think of a breaking change scenario.
MrDosu
+1  A: 

Here's what I've done. In your DragDrop code, subscribe to the PreviewMouseLeftButtonDown. If the item you are already clicking on is selected, then set e.Handled to true.

In my sample below, I identify a part of the list box item as a drag grip (with bumps) so that I can distinguish between the item and a drag surface. I just had to get the list box item data template and the drag and drop behavior to agree on a name of the drag grip element.

The PreviewMouseLeftButtonDown from my work in progress:

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;
    }
}
Geoff Cox
+1 Yes, in the end, I have solved it in a similar way. Thanks for the answer. However I already have accepted MrDosu's answer. But I would recommend your way to other persons who want to solve the same problem.
HCL