Attempting to drag between RadTreeView and RadListBox

4 posts, 0 answers
  1. Michael
    Michael avatar
    19 posts
    Member since:
    Aug 2014

    Posted 04 Dec 2014 Link to this post

    Hey all.

    So I'm in the middle of evaluating the RadTreeView control, and so far, it leaps ahead of other controls I've evaluated. I'm exploring the Drag/Drop functionality at the moment, but am really struggling, as I've not been able to find a consistent approach to tackle the problem in the online documentation.

    I've basically got a RadTreeView and a RadListBox, each of their viewmodels have an ObservableCollection of HierachicalData. I can drag within the control, and between like controls (RadListBox to RadListBox), but can't get it working between the two.

    I've attached my solution - when dragging from the TreeView, you can see the drop indicator on the ListBox, but drop is disabled.

    My tree view looks like this :
    <telerik:RadTreeView x:Name="TreeView" Grid.Row="1"
        ItemsSource="{Binding Items}" ItemTemplate="{StaticResource ParentTemplate}"
        SelectionMode="Multiple" SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
        IsDragDropEnabled="True" AllowDrop="False" >
        <telerik:RadTreeView.ItemContainerStyle>
            <Style TargetType="telerik:RadTreeViewItem">
                <Setter Property="IsSelected" Value="{Binding Path=Select, Mode=TwoWay}" />
                <Setter Property="IsExpanded" Value="{Binding Path=Expand, Mode=TwoWay}"></Setter>
            </Style >
        </telerik:RadTreeView.ItemContainerStyle>
    </telerik:RadTreeView>
    .. with the following VM ...
    public class TelerikTreeViewModel : ReactiveScreen
        {
            private ObservableCollection<HierachicalData> _items;
            private HierachicalData _selectedItem;
     
            public TelerikTreeViewModel()
            {
                DisplayName = "Telerik Tree";
                Items = new ObservableCollection<HierachicalData>
                {
                    new HierachicalData
                    {
                        Name = "Parent", Expand = true, Select = true,
                        Children = new ObservableCollection<HierachicalData>
                        {
                            new HierachicalData {Name = "Child 1"},
                            new HierachicalData {Name = "Child 2", Select = true}
                        }
                    },
                    new HierachicalData
                    {
                        Name = "Parent 2",Expand = true,
                        Children = new ObservableCollection<HierachicalData>
                        {
                            new HierachicalData {Name = "Child 12", Select= true},
                            new HierachicalData {Name = "Child 22"}
                        }
                    }
                };
            }
     
            public ObservableCollection<HierachicalData> Items
            {
                get { return _items; }
                set { this.RaiseAndSetIfChanged(ref _items, value); }
            }
     
            public HierachicalData SelectedItem
            {
                get { return _selectedItem; }
                set { this.RaiseAndSetIfChanged(ref _selectedItem, value); }
            }
        }
     
        public class HierachicalData : ReactiveObject
        {
            private string _name;
            private ObservableCollection<HierachicalData> _children;
            private bool _isSelected;
            private bool _expand;
     
            public HierachicalData()
            {
                 
            }
     
            public string Name
            {
                get { return _name; }
                set { this.RaiseAndSetIfChanged(ref _name, value); }
            }
     
            public ObservableCollection<HierachicalData> Children
            {
                get { return _children; }
                set { this.RaiseAndSetIfChanged(ref _children, value); }
            }
     
            public bool Select
            {
                get { return _isSelected; }
                set
                {
                    this.RaiseAndSetIfChanged(ref _isSelected, value);
                }
            }
     
            public bool Expand
            {
                get { return _expand; }
                set { this.RaiseAndSetIfChanged(ref _expand, value); }
            }
        }

    And my RadListBox looks like this
    <Style x:Key="DraggableListBoxItem" TargetType="telerik:RadListBoxItem">
                <Setter Property="telerik:DragDropManager.AllowCapturedDrag" Value="True"/>
                <Setter Property="telerik:DragDropManager.AllowDrag" Value="True" />
                <Setter Property="telerik:DragDropManager.TouchDragTrigger" Value="TapAndHold"/>
            </Style>
     
    <telerik:RadListBox x:Name="ListBox" ItemsSource="{Binding Items}"
                 ItemTemplate="{StaticResource ListBoxItemDataTemplate}"
                 ItemContainerStyle="{StaticResource DraggableListBoxItem}"
                 >
            <telerik:RadListBox.DragDropBehavior>
                <telerik:ListBoxDragDropBehavior/>
            </telerik:RadListBox.DragDropBehavior>
            <telerik:RadListBox.DragVisualProvider>
                <telerik:ScreenshotDragVisualProvider />
            </telerik:RadListBox.DragVisualProvider>
            <telerik:RadListBox.DropVisualProvider>
                <telerik:LinearDropVisualProvider />
            </telerik:RadListBox.DropVisualProvider>
        </telerik:RadListBox>

    With the following VM :
    public class DataItemDropViewModel : ReactiveScreen
        {
            public DataItemDropViewModel()
            {
                Items = new ObservableCollection<HierachicalData>
                {
                    new HierachicalData{Name = "Hello"},
                    new HierachicalData{Name = "Hello2"},
                    new HierachicalData{Name = "Hello3"},
                };
            }
     
            private ObservableCollection<HierachicalData> _items;
            public ObservableCollection<HierachicalData> Items
            {
                get { return _items; }
                set { this.RaiseAndSetIfChanged(ref _items, value); }
            }
        }


    These exist in seperate user controls, with their own viewmodels. There is no code behind as I'm attempting to leverage as much of the existing framework as possiblle. I'm using the following version of the Telerik dlls 2014.2.729.45
  2. Kalin
    Admin
    Kalin avatar
    1209 posts

    Posted 09 Dec 2014 Link to this post

    Hi Michael,

    Thank you for contacting us.

    Looks like you have missed to attach the sample project you are referring to. Can you please attach it again?

    However it looks like you would also need to implement a DataConverter which manually extracts the DataContext of the dragged TreeViewItem. For an example on how to implement such a DataConverter please check the following article from our online help documentation:
    http://www.telerik.com/help/wpf/radlistbox-features-dragdrop-scheduleview.html

    I'm looking forward to hearing from you.

    Regards,
    Kalin
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  3. UI for WPF is Visual Studio 2017 Ready
  4. Michael
    Michael avatar
    19 posts
    Member since:
    Aug 2014

    Posted 09 Dec 2014 Link to this post

    Seems we can't upload zip files, so I've shared a link here :

    http://1drv.ms/1Iwia2K

    It's a RadListBox and a RadTreeView - each using the same datatypes (hence my not implementing a converter).
  5. Kalin
    Admin
    Kalin avatar
    1209 posts

    Posted 12 Dec 2014 Link to this post

    Hello Michael,

    I carefully investigated the provided project. In order to get the drop on the ListBox to work correctly you would need to implement a custom DataConverter as the ListBox and the TreeView use different Payloads. So the converter should look as shown below:

    class ListBoxDataConverter : DataConverter
    {
        public override object ConvertTo(object data, string format)
        {
            var draggedItems = DragDropPayloadManager.GetDataFromObject(data, "TreeViewDragDropOptions") as TreeViewDragDropOptions;
     
            return draggedItems.DraggedItems;
        }
     
        public override string[] GetConvertToFormats()
        {
            return new string[] { typeof(TreeViewDragDropOptions).FullName, typeof(HierachicalData).FullName };
        }
    }

    And attach it to the ListBox:

    <telerik:RadListBox x:Name="ListBox" ItemsSource="{Binding Items}"
                        ItemTemplate="{StaticResource ListBoxItemDataTemplate}">
        <telerik:RadListBox.DragVisualProvider>
            <telerik:ScreenshotDragVisualProvider />
        </telerik:RadListBox.DragVisualProvider>
        <telerik:RadListBox.DragDropBehavior>
            <telerik:ListBoxDragDropBehavior />
        </telerik:RadListBox.DragDropBehavior>
        <telerik:RadListBox.DataConverter>
            <local:ListBoxDataConverter />
        </telerik:RadListBox.DataConverter>
    </telerik:RadListBox>

    However the drop indicator will still show that the drop is not allowed as it comes from the default drag drop behavior of the TreeView. For such a scenarios you have to implement a custom TreeViewDragDropBehavior as shown in this online demo (this way you will be able to change the indicator as needed):
    http://demos.telerik.com/silverlight/#DragAndDrop/TreeToGrid

    Alternatively you could just hide the indicator by setting the IsDragTooltipEnabled property of the TreeView to True.

    Hope this helps.

    Regards,
    Kalin
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
Back to Top