This is a migrated thread and some comments may be shown as answers.

Customize Drag Drop Visual

3 Answers 706 Views
TreeView
This is a migrated thread and some comments may be shown as answers.
Reilly
Top achievements
Rank 1
Veteran
Reilly asked on 12 Feb 2021, 04:58 PM

I am using the "UI for WPF Q1 2016" release, WPF, .NET Framework 4.6.1, Windows 10 and C#.

I am trying to implement drag and drop within a single RadTreeView. The default drag visual has a great structure, but has some problems for me. (The background of the drag item is dark and I can't read the dragged item's name, and the drop tooltip seems to be calling ToString() on my viewmodel, and that is not the text that I want.)

Researching, the page "Customize the TreeViewDragVisual" (https://docs.telerik.com/devtools/wpf/controls/radtreeview/how-to/customize-treeviewdragvisual)
tells me to derive from RadTreeView and to modify the template. But I am using NoXaml binaries and this page indicates that I must set the control template in app.xaml. Therefore it will apply to all RadTreeViews, and this doesn't seem like what I want to do.

Then I find the forum post on modifying the tooltip (https://www.telerik.com/forums/treeview---how-to-modify-the-drag-drop-drag-tooltip-target-part)
which points me at the DragDropManager. The manager has a "Set Drag Visual" topic (https://docs.telerik.com/devtools/wpf/controls/dragdropmanager/how-to/dragdrompmanager-howto-set-drag-visual) which says to handle DragDropManager.AddDragInitializeHandler and create a new drag visual in
the handler. This seems better than modifying app.xaml.

Also DragDropManager has the topic "Customizing the DragVisual" (https://docs.telerik.com/devtools/wpf/controls/dragdropmanager/behaviors/customizingdragvisual) which talks about implementing IDragVisualProvider. But the example is for ListBox and I'm using a RadTreeView.

So I'm all kinds of confused.

First, I need to fix the drag visual. I like the Drop Preview Line, the Drag Preview, and the Drag Tooltip parts. I need to change the Drag Preview and the Drag Tooltip.

Then I need to handle the "drop", which I think is done by attaching my own handler to DragDropManager.Drop event.

Thanks for any help.

-John.


3 Answers, 1 is accepted

Sort by
0
Dilyan Traykov
Telerik team
answered on 17 Feb 2021, 09:09 AM

Hello John,

The recommended approach, in this case, would be to indeed create a custom RadTreeView and handle the events provided by the DragDropManager.

If you do not wish to create an implicit style for the TreeViewDragVisual you can set a key for it in the App.xaml file and then set the style explicitly in the DragInitialize handler:

        private void OnDragInitialize(object sender, DragInitializeEventArgs args)
        {
            var treeDragVisual = args.DragVisual as TreeViewDragVisual;
            treeDragVisual.Style = App.Current.Resources["CustomDragVisual"] as Style;
        }
In the style you can change the appearance of the visual as desired.

As for updating the tooltip of the drop location, you can handle the DragOver event in a similar fashion:

        public void OnDragOver(object sender, Telerik.Windows.DragDrop.DragEventArgs args)
        {
            var options = DragDropPayloadManager.GetDataFromObject(args.Data, TreeViewDragDropOptions.Key) as TreeViewDragDropOptions;
            
            var treeDragVisual = options.DragVisual as TreeViewDragVisual;

            // replace this with the text you want to display in the tooltip
            treeDragVisual.DropTarget = options.DropTargetItem.ToString();

            // override DropTargetTemplate if required
            // treeDragVisual.DropTargetTemplate = App.Current.Resources["DropTargetTemplate"] as DataTemplate;
        }
You can see that I get ahold of the TreeViewDragVisual and can then set its DropTarget and DropTargetTemplate properties.

Finally, you can also handle the Drop event as per your requirement:

        public void OnDrop(object sender, Telerik.Windows.DragDrop.DragEventArgs args)
        {
            var options = DragDropPayloadManager.GetDataFromObject(args.Data, TreeViewDragDropOptions.Key) as TreeViewDragDropOptions;
            var treeDragVisual = options.DragVisual as TreeViewDragVisual;

            // handle drop as desired
        }

For your convenience, I've prepared a small sample project which demonstrates how to set this up. Please have a look and let me know if you find it helpful.

Regards,
Dilyan Traykov
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

0
Reilly
Top achievements
Rank 1
Veteran
answered on 04 Mar 2021, 03:34 PM

Hi Dilyan,

This works for me. Thanks for the example.

I only have one question. Why did you derive a CustomTreeView class from the RadTreeView? Why didn't you just put the RadTreeView in the Example.xaml and then put the implementation in the Example.xaml.cs? That architecture works, because that's what I did. I thought that was the whole purpose of the DragDropManager.

Is it because you couldn't do the Style in app.xaml unless you derived the control?

Thanks again.

-John.

0
Dilyan Traykov
Telerik team
answered on 05 Mar 2021, 02:01 PM

Hi John,

I proposed this approach so that you can reuse this custom logic in multiple RadTreeView instances without duplicating code.

If you will only use a single RadTreeView instance, you can, of course, proceed with the architecture you've already set up.

I hope this clarifies your concerns. If any other questions arise, do not hesitate to contact me again.

Regards,
Dilyan Traykov
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

Danny
Top achievements
Rank 1
Iron
commented on 28 May 2025, 02:43 PM

Hi Telerik support,

Even it's an older post, I come to you with a kindly request for putting me on the right path.

I want to try  drag and drop functionality between 2 RadTreeviews (no MVVM template)

The trees are defined in XAML using a Hierarchical Template binded with a hierarchical data structure of folders and files (as ObservableCollections of objects “File”, “Folder” and “Item”, each of them having a “Name”, a“Path” and for “Folder” an ObservableCollection of Items (could be Files or Folders) (like the post at https://stackoverflow.com/questions/6415037/populate-treeview-from-list-of-file-paths-in-wpf). So far so good: the trees are populated and displayed as expected.

The DragVisual shows correctly the draggedItem Name (in my case the name of the dragged File or Folder), but not the targetItem (target Folder or target File) Name. Instead the Name it’s displayed the class name of the targetItem.

I tried to override DropTargetTemplate, but I don’t know how to bind the TextBlock inside this template to my Collections (either Folders, or Files) as I did for displaying the trees (see below)

        <HierarchicalDataTemplate DataType="{x:Type local:Folder}" ItemsSource="{Binding Items}">
            <StackPanel Orientation="Horizontal">
                <Image x:Name="img" Width="16" Height="16" Source="Images/folder_closed.png" />
                <TextBlock Text="{Binding Name}" Margin="5,0,0,0"/>
            </StackPanel>
            <HierarchicalDataTemplate.Triggers>
                <DataTrigger Binding="{Binding IsExpanded, RelativeSource={RelativeSource AncestorType={x:Type telerik:RadTreeViewItem}}}" Value="True">
                    <Setter TargetName="img" Property="Source" Value="Images/folder-openaa.png"/>
                </DataTrigger>

            </HierarchicalDataTemplate.Triggers>
        </HierarchicalDataTemplate>
        <DataTemplate DataType="{x:Type local:File}" >
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"></ColumnDefinition>
                    <ColumnDefinition Width="10*"></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <Image Source="{Binding Path=Source}" Width="16" Height="16"></Image>
                <TextBlock Text="{Binding Name}" Grid.Column="1"></TextBlock>
            </Grid>
        </DataTemplate>
    </telerik:RadTreeView.Resources>
Thak you in advance for any suggestion,

Danny Costa

Tags
TreeView
Asked by
Reilly
Top achievements
Rank 1
Veteran
Answers by
Dilyan Traykov
Telerik team
Reilly
Top achievements
Rank 1
Veteran
Share this question
or