Sunday 15 December 2013

Adding Drag and drop behaviour to ItemsControls Part 2

     It's been some time since I last posted something, and the drag and drop behaviour tutorial completion was sitting all this time on a back burner. It is high time to finish it. I'd like to start with a slight refactoring of the code I posted previously for IsDropSource property change callbacks, and another piece of code for IsDragTarget property change callback.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// Adds passed ItemsControl to the drag sources collecton
private static void IsDragSourceUpdated(DependencyObject dp,
    DependencyPropertyChangedEventArgs args)
{
    var isDragSourceEnabled = (bool)args.NewValue;
    var dragSource = dp as ItemsControl;
               
    if (isDragSourceEnabled)
    {
        Add(dragSources, dragSource);
        dragSource.PreviewMouseMove += OnMouseMove;
        dragSource.PreviewMouseLeftButtonDown += OnLeftButtonDown;
    }
    else
    {
        Remove(dragSources, dragSource);
        dragSource.PreviewMouseMove -= OnMouseMove;
        dragSource.PreviewMouseLeftButtonDown -= OnLeftButtonDown;
    }
}

// Adds passed ItemsControl to the drop targets collection
private static void IsDropTargetUpdated(DependencyObject dp,
    DependencyPropertyChangedEventArgs args)
{
    var isDropTargetEnabled = (bool)args.NewValue;
    var dropTarget = dp as ItemsControl;

    dropTarget.AllowDrop = isDropTargetEnabled;            

    if (isDropTargetEnabled)
    {
        Add(dropTargets, dropTarget);
        dropTarget.Drop += Drop;
    }
    else
    {
        Remove(dropTargets, dropTarget);
        dropTarget.Drop -= Drop;
    }         
}

The code initializes the ItemsControl adorned with those properties in xaml as a new drag source or drop target. For that to be possible it adds the control to particular collections and adds required events. Beside the obvious mouse move and drop events we need to remember about servicing the Loaded and Unloaded events to add or remove the control from the drag and drop when the View is being either opened or closed.
Part of the above execution is further contained in following Add and Remove methods:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// Adds item control to a group
// (this item control will only be allowed to participate in d&d in this particular gorup)
private static void Add(Dictionary<String, List<ItemsControl>> dictionary, object sender)
{
    InitializeDragDropCollections();

    var dp = sender as DependencyObject;
    var itemsControl = sender as ItemsControl;
    var groupName = GetGroupName(dp);

    var foundGroup = dictionary.FirstOrDefault(p => p.Key == groupName);
    if (!foundGroup.Value.Contains(itemsControl))
        dictionary[groupName].Add(itemsControl);

    itemsControl.Unloaded += dropTarget_Unloaded;
    itemsControl.Loaded += dropTarget_Loaded;
}

// Removes item control from group
private static void Remove(Dictionary<String, List<ItemsControl>> dictionary, object sender)
{
    var dp = sender as DependencyObject;
    var itemsControl = sender as ItemsControl;
    var groupName = GetGroupName(dp);

    var foundGroup = dictionary.FirstOrDefault(p => p.Key == groupName);
    if (foundGroup.Value.Contains(itemsControl))
        dictionary[groupName].Remove(itemsControl);

    itemsControl.Unloaded -= dropTarget_Unloaded;
    itemsControl.Loaded -= dropTarget_Loaded;
}

       We make sure both collections are initialized and an empty "global" drag and drop group is added to both by using the InitializeDragDropCollections method:'s

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// Intizialize drag drop collections
private static void InitializeDragDropCollections()
{
    if (dragSources == null)
        dragSources = new Dictionary<string, List<ItemsControl>>();
    if (dropTargets == null)
        dropTargets = new Dictionary<string, List<ItemsControl>>();

    if(!dragSources.Any(p => p.Key == ""))
        dragSources.Add("", new List<ItemsControl>());
    if (!dropTargets.Any(p => p.Key == ""))
    dropTargets.Add("", new List<ItemsControl>());
}

That's it for now, I'll finish the tutorial quite soon by adding the rest of events and methods. Along with the link to the whole class.

No comments:

Post a Comment