WPF: ItemsControl Drag Drop Behavior


** updated this post for Blend 3 RC release

In my previous post, I talked about adding Drag and Drop functionality into controls that implement ItemsControl via a Decorator pattern. In that DragDrop Decorator, I have created a Drag Adorner to create a visual effect of the actual item you are dragging. In this post I have added a new functionality where you can see an Insert Adorner that shows you the position you are attempting to add the item to. Since a picture tells a thousand words….

DragDrop

With the release of a new feature called Behaviors seen in Mix 09, I have ported over my code into a Behavior. To create a behavior, you need to subclass the Behavior or Behavior<T> class in the Microsoft.Expression.Interactivity namespace. You can find this DLL when you install Expression Blend 3 in C:\Program Files\Microsoft Expression\Blend 3 Preview\Libraries\WPF folder.

When you subclass, you can override the OnAttached method to initialize your behavior, and you can access the control you added the behavior to via the this.AssoicatedObject. If you subclassed using the generic Behavior<T>, the AssociatedObject property will be returned to you of Type T, very nice! This is a cut down version of my subclassed behavior, just for illustration.

public class ItemsControlDragDropBehavior : Behavior<ItemsControl>
{
    protected override void OnAttached()
    {
        this.AssociatedObject.AllowDrop = true;
        this.AssociatedObject.PreviewMouseLeftButtonDown +=
            new MouseButtonEventHandler(itemsControl_PreviewMouseLeftButtonDown);
        this.AssociatedObject.PreviewMouseMove +=
            new MouseEventHandler(itemsControl_PreviewMouseMove);
        this.AssociatedObject.PreviewMouseLeftButtonUp +=
            new MouseButtonEventHandler(itemsControl_PreviewMouseLeftButtonUp);
        this.AssociatedObject.PreviewDrop += new DragEventHandler(itemsControl_PreviewDrop);
        this.AssociatedObject.PreviewQueryContinueDrag +=
            new QueryContinueDragEventHandler(itemsControl_PreviewQueryContinueDrag);
        this.AssociatedObject.PreviewDragEnter +=
            new DragEventHandler(itemsControl_PreviewDragEnter);
        this.AssociatedObject.PreviewDragOver +=
            new DragEventHandler(itemsControl_PreviewDragOver);
        this.AssociatedObject.DragLeave += new DragEventHandler(itemsControl_DragLeave);
    }

    // more code here....
}

In Xaml, you ‘add’ a behavior like so.

<ListView Margin="10" ItemTemplate="{StaticResource listViewItemTemplate}">
 <Interaction:Interaction.Behaviors>
     <DragDrop:ItemsControlDragDropBehavior ItemType="{x:Type this:Product}"
                     DataTemplate="{StaticResource listViewItemTemplate}" />
 </Interaction:Interaction.Behaviors>
</ListView>

The behavior expects the Type of item you are going to be using for your ItemsControl via the ItemType property, which can be a business object, or a primitive type. This is used to ensure that the ItemsControl only accept a DragDrop of the right type.  The behavior also expects you to define a DataTemplate, and this data template is being used by the Drag Adorner to render the appropriate ‘look’. This is an added flexibility which allows you to define a data template that is different from the data template you used in your ItemsControl’s ItemTemplate.

I won’t be going through the code of the Drag and Insert Adorners, do download the code to have a look. Also feel free to create your own custom Drag and Insert Adorners. If you want the ability to use different Adorners at runtime, you can create an Interface for each and perhaps use a Factory pattern or Dependency Injection to instantiate different Adorners. If you need suggestions or assistance to implement this, leave a comment or send me an email, I’ll be happy to help.

To get a copy of the code for this behavior, go to my contribution page at Expression Gallery. (updated this sample to work with Blend 3 RC)

Alternatively, you can download the Decorator version of this sample.

Share this post:
Advertisements
Posted in WPF. Tags: . 11 Comments »

11 Responses to “WPF: ItemsControl Drag Drop Behavior”

  1. WPF: Editable Behavior for Labels « Code Blitz Says:

    […] WPF: ItemsControl Drag Drop Behavior […]

  2. WPF: DragDrop Decorator for ItemsControl « Code Blitz Says:

    […] WPF: ItemsControl Drag Drop Behavior […]

  3. WPF: Drag Drop Adorner « Code Blitz Says:

    […] WPF: ItemsControl Drag Drop Behavior […]

  4. Raul Rangel Says:

    Does this behavior support dragging to sub nodes in a tree ? I can only get it to drag to root nodes.

    Thanks!

  5. Vaughan Knight Says:

    Just thought I’d post a comment here rather than leave my experience with the code unknown.

    First up, nice work.

    Secondly, I often have a lot of subclassed objects in lists. The behaviour wasn’t working with the subclassed objects. By setting ItemType to MyParentClass, instances of classes inheriting (MyChildClass1, MyChildClass2) did not work.

    A quick change to DragStarted by adding !_data.GetType().IsSubclassOf(ItemType)) to the conditional fixed the issue for me.

    But this behaviour may or may not be desirable from time to time. For example you may want different templates based on the class. So although my change fixes my issue, it would be nice to be able to do it cleanly by complimenting ItemType with an AllowInheritedTypes flag (or something better).

    Thanks again, it’s such a clean easy implementation.

  6. Sin Jeong-hun Says:

    Hello. Thank you for the code. Though the sample code does not exactly fit my needs, it almost does. I think I will modify the code and use it in our company’s program. It’s not a program sold separately but it comes with a big software as a miscellaneous tool. I am not paid for the program.
    I looked for the license text, but there wasn’t any. Could you give me the license text?
    Thank you.

    • Ed Foh Says:

      Hi there

      thanks for the comment. I don’t have any license text, in fact this is the first time someone is asking me for one. 🙂

      anyways feel free to use the code. I post this out for everyone to use. However do test it thoroughly, to make sure that it’s working for you.

  7. sullifornia Says:

    This is great work. Thank you for sharing!

    I have question though: any idea how I could allow drag/dropping an item from the list onto another in order to merge them? Even if that means losing the insertion feature.

    Thank you.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: