Google Search

Monday, April 6, 2009

Creating customizable WPF drop-down menus (4,5)


Step 4: Responding to drag hovering


Important Note:
In this part of the tutorial, we implement the draggable menu items that are static, and still in the menu, rather then the one being dragged. Keep that in mind, this is important.

We want our menus open whenever an item is dragged over them. The simplest solution would be to override the OnDragEnter method, and set the IsSubmenuOpen property to true.
This will work for now, but we will have to change that later, when we get to the drop-handling part.
Anyway, for now:
protected override void OnDragEnter(DragEventArgs e)
{
    IsSubmenuOpen = true;
    e.Handled = true;
}

Step 5: Handling drops


First we must accept drops. Lets implement the constructor:
public DraggableMenuItem()
{
    AllowDrop = true;
}

This code snippet set our draggable menu item to accept drops. Without this, it wouldn't be possible to drop anything on it, so we wouldn't be able to customize our menu.
Next we need to catch the drop operation, and perform the item movement logic. Of course we shall override and implement OnDrop. Note that we will need to extract the item being dragged from the DragEventArgs, and if it is a DraggableMenuItem, remove it from its current position, and place it just before the drop target:
protected override void OnDrop(DragEventArgs e)
{
    DraggableMenuItem draggedItem = (DraggableMenuItem)e.Data.GetData(typeof(DraggableMenuItem));
    DraggableMenuItem parentMenuItem = Parent as DraggableMenuItem;
    Menu parentMenu = Parent as Menu;
    ItemsControl itemsControl = Parent as ItemsControl;
    if (draggedItem != null && (parentMenuItem != null || parentMenu != null)) 
    {
        int i = itemsControl.Items.IndexOf(this);
        ItemsControl draggedItemParent = draggedItem.Parent as ItemsControl;
        if (draggedItemParent != null) 
        {
            draggedItemParent.Items.Remove(draggedItem);
        }
        itemsControl.Items.Insert(i, draggedItem);
        e.Handled = true;
    }
    base.OnDrop(e);
}

First attempt to test it all


Generally, while things don't look as nice as they can be, and might still be somewhat buggy, it looks like things should work.
Testing it reveals that dropping items on the menu bar level does work. However, dropping things on open sub-menus doesn't!
I will review the reason for that on the next post.

No comments:

Post a Comment