Understanding infragistics Drag & Drop framework

Looking at the current Warewolf design features, we have a drag and drop feature that is very straight forward, and has this look and feel of a basic control. Our goal is to make Warewolf look as awesome as it works; therefore we need to start implementing new UI features that will make a user feel excited while using Warewolf.

In this blog I will share our implementation of using the Infragistics Drag & Drop Framework. Not every person cares about UI, as long as the functionality work; but I would not enjoy working on a system that does not visually call my attention. In this blog I will share our implementation to using the Infragistics Drag & Drop Framework. If you have read the documentation on the Infragistics website, you would see that it’s pretty straight forward and should be easy to implement.

The Infragistics Drag & Drop Framework

The XAML implementation is pretty straight forward, which allows for many options as you would expect from a drag & drop framework. I am only going to explain the events that we use in Warewolf, but if you require more information on how to use all the events, simply read up on the documentation on the Infragistics website.

<ig:DragDropManager.DragSource>
	<ig:DragSource IsDraggable="True"
		DragChannels="1"
		DragStart="DragSource_DragStart"
		DragOver="DragSource_DragOver"
		DragLeave="DragSource_DragLeave"
		Drop="DragSource_Drop" />
</ig:DragDropManager.DragSource>
 
<ig:DragDropManager.DropTarget>
	<ig:DropTarget  IsDropTarget="True" DragChannels="1" />
</ig:DragDropManager.DropTarget>

Implementing the Infragistics Drag & Drop events

We use a XamDataTree to display our Sources/Connectors and from here we need to allow the user to be able to move resources to other existing paths. Let’s look at how we implement the Infragistics Drag & Drop Framework into Warewolf. An important detail to remember is to make sure to set the drag content to IsDraggable=”True” and the drop content to IsDropTarget=”True”, as many developers make that simple mistake. One thing I picked up is that I could not easily find information on the properties “DragChannels & DropChannels”. When Drag & Drop occurs across different UserControls, these two property values need to match each other in order to allow the Drag & Drop features to work.

DragSource_OnDragStart

Starting with the OnDragStart method, we need to determine what the Original DragSource is and read the DataContext as a XamDataTreeNodeDataContext. The OnDragStart is not an essential part, but more for getting and storing the Original drag object.

void DragSource_OnDragStart(object sender, DragDropStartEventArgs e)
{
	var frameworkElement = e.OriginalDragSource as FrameworkElement;
	if (frameworkElement != null)
{
		var context = frameworkElement.DataContext as XamDataTreeNodeDataContext;
		if (context != null)
		{
			var dataContext = context.Data as ViewModel;
			if (dataContext != null)
			{
				var dragData = new DataObject();
				dragData.SetData(format, dataContext);
				dragData.SetData(dataContext);
				_dragData = dragData;
			}
		}
	}
}
DragSource_OnDragOver

Next, we look at the OnDragOver method using DragSource and DropTarget Types. Using the drop object, we read the data as our ViewModel as our destination object. The drag over method is used to determine if a drop is allowed, to which the style can be changed based on the allowed option. You need to make sure that your naming conventions are correct and match that of the UI in order to be able to change the style.

void DragSource_OnDragOver(object sender, DragDropMoveEventArgs e)
{
	var drop = Utilities.GetAncestorFromType(e.DropTarget, typeof(XamDataTreeNodeControl), false) as XamDataTreeNodeControl;
	var drag = Utilities.GetAncestorFromType(e.DragSource, typeof(XamDataTreeNodeControl), false) as XamDataTreeNodeControl;
 
	if (drag != null && (drop != null && drag.Node.Manager.ParentNode != null && drop.Node.Manager.ParentNode != null))
	{
		var destination = drop.Node.Data as DropViewModel;
 
		if (destination != null && (drag.Node.Data.GetType() == drop.Node.Data.GetType()))
		{
			if (e.GetPosition(e.DropTarget).Y < drop.ActualHeight / 2)
			{
				((Grid)Utilities.GetDescendantFromName(drop, "DropBeforeElement")).Visibility = Visibility.Visible;
				((Grid)Utilities.GetDescendantFromName(drop, "DropAfterElement")).Visibility = Visibility.Collapsed;
			}
			else
			{
				((Grid)Utilities.GetDescendantFromName(drop, "DropAfterElement")).Visibility = Visibility.Visible;
				((Grid)Utilities.GetDescendantFromName(drop, "DropBeforeElement")).Visibility = Visibility.Collapsed;
			}
		}
	}
}
DragSource_OnDragLeave

Drag Leave is the option to cancel what you are dragging and dropping to. OnDragLeave occurs when the drop area is not recognized as a matching Framework that allows a drop function to happen. In our case, we simply want to get the drop target control and reset the style to not show the Drag & Drop features.

void DragSource_OnDragLeave(object sender, DragDropEventArgs e)
{
	var drop = Utilities.GetAncestorFromType(e.DropTarget, typeof(XamDataTreeNodeControl), false) as XamDataTreeNodeControl;
	Reset(drop);
}
 
private void Reset(XamDataTreeNodeControl drop)
{
	if (drop != null)
	{
		((Grid)Utilities.GetDescendantFromName(drop, "DropBeforeElement")).Visibility = Visibility.Collapsed;
		((Grid)Utilities.GetDescendantFromName(drop, "DropAfterElement")).Visibility = Visibility.Collapsed;
	}
}
DragSource_OnDrop

The OnDrop method does the actual move of resources. Again we need to get the Drag & Drop types, and then read the source and destination ViewModels before attempting to move the resource. There is a lot of checking that can take place in the OnDrop, but that would rely on what checks are necessary.

void DragSource_OnDrop(object sender, DropEventArgs e)
{
	var drop = Utilities.GetAncestorFromType(e.DropTarget, typeof(XamDataTreeNodeControl), false) as XamDataTreeNodeControl;
	var drag = Utilities.GetAncestorFromType(e.DragSource, typeof(XamDataTreeNodeControl), false) as XamDataTreeNodeControl;
 
	if (drag != null && (drop != null && drag.Node.Manager.ParentNode != null && drop.Node.Manager.ParentNode != null))
{
		var destination = drop.Node.Data as DropViewModel;
		var source = drag.Node.Data as DragViewModel;
		if (source != null && destination != null)
		{
			source.Move(destination);
		}
		Reset(drop);
	}
}

Conclusion

The Infragistics Drag & Drop Framework has many possibilities, but as a developer you need to be prepared to grind your teeth a few times to get it to work to your specification. The end result is well worth the struggle and makes for a pretty cool look and feel to using Warewolf.

We’d love your feedback on our implementation of using the Drag & Drop Framework, check out how we’ve done it in the GitHub repository, or post in the comments section below.

 

FacebookTwitterLinkedInGoogle+RedditEmail

Leave A Comment?