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!
Awesome! Feel free to download the source code for this example and check it out for yourself!
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.