http://SilverlightDesktop.net

Silverlight Desktop - Implementing "Drag and Drop"

SilverlightDesktop.net allows you to drag elements from one module and drop them into another module. This is a task that is not easily done in any other web technology.

The dragging and dropping between modules is possible with modules that could be created by two different module developers who have no knowledge of each other. An example would be grabbing an email address from the contacts module and dropping it onto the email module and sending an email.

Overview of the Drag and Drop functionality

To Export:

To Import:

Example Code - Export

The WhoAmI module implements drop functionality by creating a method called AddDelegates that accepts an instance of the core SilverlightDesktop project page as a parameter:

        public void AddDelegates(SilverlightDesktop.Page objParentPage)
        {
            ParentPage = objParentPage;

            // Add delegates to the parent to allow it to handle the drag and drop
            FrameworkElement objFrameworkElementFirstName = (FrameworkElement)this.txtFirstName;
            objFrameworkElementFirstName.MouseLeftButtonDown +=
                new MouseButtonEventHandler(ParentPage.objFrameworkElement_MouseLeftButtonDown);

            FrameworkElement objFrameworkElementLastName = (FrameworkElement)this.txtLastName;
            objFrameworkElementLastName.MouseLeftButtonDown +=
                new MouseButtonEventHandler(ParentPage.objFrameworkElement_MouseLeftButtonDown);

            FrameworkElement objFrameworkElementEmail = (FrameworkElement)this.txtEmail;
            objFrameworkElementEmail.MouseLeftButtonDown +=
                new MouseButtonEventHandler(ParentPage.objFrameworkElement_MouseLeftButtonDown);
        } 
The code also includes the words "[draggable]" to the Tag property of each element:
<TextBlock Text="" TextWrapping="Wrap" Canvas.Top="24.537" Canvas.Left="10.854" x:Name="txtFirstName" RenderTransformOrigin="0.5,0.5" Height="Auto" Width="Auto" 
Tag="[draggable]" MouseEnter="Text_MouseEnter" MouseLeave="Text_MouseLeave">
The SilverlightDesktop.net main window attempts to attach the delegates so it will intercept the drag of the element:
// Try to call the AddDelegates method on the module being loaded
// However, the module may not have the AddDelegates method
try
{
    // Create a parameters array
    object[] parameters = new object[1];
    // Add the element that is being dragged to the array
    parameters.SetValue(this, 0);
    objUserControl.GetType().InvokeMember("AddDelegates",
        BindingFlags.InvokeMethod, null, objUserControl, parameters);
}
catch
{
    // The module does not implement the AddDelegates method
}
When an element with that Tag is detected, the element is removed from the Canvas it is currently on and placed on the root canvas of the application while it is being dragged.
// Remove the element from it's control and move it to the parent
// if it's Tag contains the words [draggable]
if (objFrameworkElement.Tag.ToString().Contains("[draggable]"))
{
    OriginalParentPanel = objFrameworkElement.Parent as Panel;
    OriginalStartingDragPoint = e.GetPosition(OriginalParentPanel);
    OriginalParentPanel.Children.Remove(objFrameworkElement);

    this.LayoutRoot.Children.Add(objFrameworkElement);
    MoveToTop(objFrameworkElement);
    UpdateElementPosition(objFrameworkElement, e.GetPosition(this.LayoutRoot));
}

Example Code - Import

To import content the developer simply makes an interface called "ImportContent" and then implements that interface. The developer can write whatever logic they want to import any content their module will recognize. In this example from the Notepad module, the Notepad module's Import method simply looks for any text and adds it to it's Textbox:

public bool ImportContent(FrameworkElement objFrameworkElement)
{
    // This import method will only import text content contained
    // in TextBlocks that are placed on a Canvas

    StringBuilder StringBuilder = new StringBuilder();
    TextBlock objTextBlock = objFrameworkElement as TextBlock;

    // If the element being imported is not a TextBlock return false
    if (objTextBlock == null)
    {
        return false;
    }

    try
    {
        // Add the contents of the TextBlock to the output
        StringBuilder.Append(String.Format(" {0}", objTextBlock.Text));
    }
    catch
    {
        return false;
    }

    // Was content in the output ?
    if (StringBuilder.Length > 0)
    {
        // Add output to the Textbox display
        this.txtContents.Text = String.Format("{0} {1}", this.txtContents.Text, StringBuilder.ToString());
        return true;
    }
    else
    {
        return false;
    }
}

The framework will allow a module developer to export ANY content, TextBlocks, Animation, Pictures, Video, Audio ect. The module developer implementing the "import" part can simply iterate through the objects being passed and decide what content he/she wants to recognize and import.