Every once in a while a customer will come to us and ask about a particular piece of functionality in one of the RadControls for Silverlight or RadControls for WPF that isn't covered in the demos, documentation, or videos. Just this week, one of the fans on our Telerik Facebook page did just that - specifically asking whether you could use a certain type of layout panel for the drag cue of RadDragAndDropManager.  Normally in a case like this, I want to say "Yeah, it's just a DataTemplate in Silverlight/WPF, so you could do almost anything there!"

But we're developers, and code speaks a thousand words (with intellisense!).

So what does it take to use different UI elements with RadDragAndDropManager?  For starters, since the developers did such a great job on the documentation, start with the following article to get your basic setup in place:

Getting Started with RadDragAndDropManager

We only make a few changes in the code I will provide you with, specifically that I'm doing six ListBox implementations (which means six ObservableCollections on the backend), along with replacing the ApplicationInfo class and all instances of it with this DragItemClass:

public class DragItemClass
{
    public int id { get; set; }
    public string stringvalue { get; set; }
    public SolidColorBrush colorbrush { get; set; }
    public DateTime datevalue { get; set; }
    public string templatevalue { get; set; }
    public DragItemClass()
    {
    }
}

 

Once that is set and you've gotten the boilerplate RadDragAndDropManager code setup from the help file above, we can start on some customizations!

The first thing we want to do is define some fake data to go into these.  I worked up 12 different items with different values, here are two example ones that we'll use to help with the explanation and other code that follows:

private void MakeSomeItems()
{
    dragItemsOne.Add(new DragItemClass() { id = 1, stringvalue = "Star Trek",
        datevalue = DateTime.Today, 
        colorbrush = new SolidColorBrush(Colors.Blue), 
        templatevalue = "zStackPanelTemplate" });
  
    dragItemsTwo.Add(new DragItemClass() { id = 2, stringvalue = "Ronin"
        datevalue = DateTime.Today.AddMonths(-1),
        colorbrush = new SolidColorBrush(Colors.Red), 
        templatevalue = "zCanvasTemplate" });
}

 

As you can see, the ObservableCollections are being populated with our DragItemClass instances, but there is a fun and curious value that I included there - the templatevalue.  This is actually the name of resources that we have defined in our UserControl.Resources for our Drag Cue templates.  This means that we can then modify the OnDragQuery method, specifically having the cue.ContentTemplate line instead pull the templatevalue from our items and using that as the resource key for our DataTemplate:

private void OnDragQuery(object sender, DragDropQueryEventArgs e)
{
    ListBoxItem lbi = e.Options.Source as ListBoxItem;
    ListBox lb = ItemsControl.ItemsControlFromItemContainer(lbi) as ListBox;
    if (e.Options.Status == DragStatus.DragQuery && lb != null)
    {
        e.Options.Payload = lb.SelectedItem;
        ContentControl cue = new ContentControl();
        cue.ContentTemplate = this.Resources[(lbi.DataContext as DragItemClass).templatevalue] as DataTemplate;
        cue.Content = lb.SelectedItem;
        e.Options.DragCue = cue;
        e.Options.ArrowCue = RadDragAndDropManager.GenerateArrowCue();
    }
  
    e.QueryResult = true;
}

 

See that?  Only one line changed.  But where are the DataTemplates coming from?  I defined those in the page where the six ListBoxes live.  Here they are for reference - and note, we are using all sorts of templates here, from StackPanel to Canvas to a RadCalendar instance - you can put virtually anything into a DataTemplate and use it for your Drag Cue.  The architecture of the control allows for this versatility!

<DataTemplate x:Name="zStackPanelTemplate">
    <StackPanel>
        <TextBlock Text="{Binding stringvalue}" />
    </StackPanel>
</DataTemplate>
<DataTemplate x:Name="zCanvasTemplate">
    <Canvas Width="60"
            Height="40"
            Background="{Binding colorbrush}">
        <TextBlock Text="{Binding stringvalue}" />
    </Canvas>
</DataTemplate>
<DataTemplate x:Name="zGridTemplate">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <TextBlock Text="{Binding id}" />
        <TextBlock Grid.Row="1"
                    Text="{Binding stringvalue}" />
    </Grid>
</DataTemplate>
<DataTemplate x:Name="zRectangleTemplate">
    <Rectangle Width="40"
                Height="40"
                Fill="{Binding colorbrush}" />
</DataTemplate>
<DataTemplate x:Name="zTextTemplate">
    <TextBlock Text="{Binding stringvalue}" />
</DataTemplate>
<DataTemplate x:Name="zCalendarTemplate">
    <telerik:RadCalendar SelectedDate="{Binding datevalue}" />
</DataTemplate>

 

And your end result?  A rich and versatile drag and drop experience with the ability to use virtually anything as a Drag Cue, and it even works on my touchscreen Lenovo laptop!

Drag and Drop Image

Awesome!  Feel free to download the source code for this example and check it out for yourself!


About the Author

Evan Hutnick

works as a Developer Evangelist for Telerik specializing in Silverlight and WPF in addition to being a Microsoft MVP for Silverlight. After years as a development enthusiast in .Net technologies, he has been able to excel in XAML development helping to provide samples and expertise in these cutting edge technologies. You can find him on Twitter @EvanHutnick.

Comments

Comments are disabled in preview mode.