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

Current treeview node drag drop example?

4 Answers 234 Views
TreeView
This is a migrated thread and some comments may be shown as answers.
Jonathan
Top achievements
Rank 1
Jonathan asked on 17 Sep 2014, 11:01 AM
Is there an up to date example of the current radtreeview node drag/drop functionality?

Examples and discussions I've found so far appear to refer to obsolete functionality, and while a simple xaml test works, events don't seem to trigger as expected.

In particular what are the relevant drop preview and event handlers and how do you get source and target nodes from the event arguments?

Tia,

Jonathan

4 Answers, 1 is accepted

Sort by
0
Jonathan
Top achievements
Rank 1
answered on 17 Sep 2014, 04:35 PM
I wrote my own example but for some reason it doesn't update the treeview control after a move (although the underlying structure is updated correctly)...

        x:Class="treedragdrop.MainWindow"
        xmlns:local="clr-namespace:treedragdrop"
        xmlns:System="clr-namespace:System;assembly=mscorlib"
 
        mc:Ignorable="d"
        d:DataContext="{d:DesignInstance IsDesignTimeCreatable=True, Type={x:Type local:MainWindow}}"
 
        Title="MainWindow"
        Height="600"
        Width="800">
 
    <Window.Resources>
 
        <HierarchicalDataTemplate DataType="{x:Type local:Person}"
                                  ItemsSource="{Binding Path=Subjects}"  >
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding Path=Name}"/>
            </StackPanel>
            <HierarchicalDataTemplate.ItemContainerStyle>
                <Style TargetType="telerik:RadTreeViewItem">
                    <Setter Property="HorizontalAlignment" Value="Stretch"/>
                </Style>
            </HierarchicalDataTemplate.ItemContainerStyle>
        </HierarchicalDataTemplate>
    </Window.Resources>
 
    <Grid>
        <telerik:RadTreeView Name="tvRealm"
                             Margin="5"
                             SelectionMode="Single"
                             IsDragDropEnabled="True"
                             telerik:TreeViewSettings.DragDropExecutionMode="New"
                             ItemsSource="{Binding Realm, Mode=OneWay, NotifyOnSourceUpdated=True}">
        </telerik:RadTreeView>
    </Grid>
</Window>


using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
 
using Telerik.Windows.Controls;
using Telerik.Windows.Controls.TreeView;
using Telerik.Windows.DragDrop;
 
namespace treedragdrop
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private ObservableCollection<Person> _realm = new ObservableCollection<Person>();
 
        public MainWindow()
        {
            InitializeComponent();
 
            Person _king = new Person("The King", Rank.King);
            Person _baron1 = new Person("Baron 1", Rank.Baron);
            Person _baron2 = new Person("Baron 2", Rank.Baron);
            Person _overseer1 = new Person("Overseer 1", Rank.Overseer);
            Person _overseer2 = new Person("Overseer 2", Rank.Overseer);
            Person _overseer3 = new Person("Overseer 3", Rank.Overseer);
            Person _overseer4 = new Person("Overseer 4", Rank.Overseer);
            Person _serf1 = new Person("Serf 1", Rank.Serf);
            Person _serf2 = new Person("Serf 2", Rank.Serf);
            Person _serf3 = new Person("Serf 3", Rank.Serf);
            Person _serf4 = new Person("Serf 4", Rank.Serf);
            Person _serf5 = new Person("Serf 5", Rank.Serf);
            Person _serf6 = new Person("Serf 6", Rank.Serf);
            Person _serf7 = new Person("Serf 7", Rank.Serf);
            Person _serf8 = new Person("Serf 8", Rank.Serf);
 
            _realm.Add(_king);
 
            _king.AddSubject(_baron1);
            _king.AddSubject(_baron2);
 
            _baron1.AddSubject(_overseer1);
            _baron1.AddSubject(_overseer2);
            _baron2.AddSubject(_overseer3);
            _baron2.AddSubject(_overseer4);
 
            _overseer1.AddSubject(_serf1);
            _overseer1.AddSubject(_serf2);
            _overseer2.AddSubject(_serf3);
            _overseer2.AddSubject(_serf4);
            _overseer3.AddSubject(_serf5);
            _overseer3.AddSubject(_serf6);
            _overseer4.AddSubject(_serf7);
            _overseer4.AddSubject(_serf8);
 
            DataContext = this;
 
            Loaded += MainWindow_Loaded;
        }
 
        void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            DragDropManager.AddDragInitializeHandler(tvRealm, OnDragInitialize, true);
            DragDropManager.AddDragOverHandler(tvRealm, OnDragOver, true);
            DragDropManager.AddDropHandler(tvRealm, OnDrop, true);
            DragDropManager.AddPreviewDropHandler(tvRealm, OnPreviewDrop, true);
 
            tvRealm.ExpandAll();
        }
 
        public ObservableCollection<Person> Realm
        {
            get { return _realm; }
        }
 
        private void OnDragInitialize(object sender, DragInitializeEventArgs e)
        {
            RadTreeViewItem item = e.OriginalSource as RadTreeViewItem;
            object data = item.Item;
            e.AllowedEffects = DragDropEffects.Move;
        }
 
        private void OnDragOver(object sender, Telerik.Windows.DragDrop.DragEventArgs args)
        {
            var options = DragDropPayloadManager.GetDataFromObject(args.Data, TreeViewDragDropOptions.Key) as TreeViewDragDropOptions;
 
            Person _source = options.DragSourceItem.Item as Person;
            Person _target = options.DropTargetItem.Item as Person;
            Person _ruler = (_target.Rank != Rank.Serf) ? _target : _target.Ruler;
 
            if (_source.CanMoveTo(_ruler))
                args.Effects = DragDropEffects.Move;
            else
                args.Effects = DragDropEffects.None;
        }
 
        private void OnDrop(object sender, Telerik.Windows.DragDrop.DragEventArgs args)
        {
            TreeViewDragDropOptions options = DragDropPayloadManager.GetDataFromObject(args.Data, TreeViewDragDropOptions.Key) as TreeViewDragDropOptions;
 
            if (options != null)
            {
                Person _source = options.DragSourceItem.Item as Person;
                Person _target = options.DropTargetItem.Item as Person;
                Person _ruler = (_target.Rank != Rank.Serf) ? _target : _target.Ruler;
 
                _source.SetRuler(_ruler);
            }
        }
 
        private void OnPreviewDrop(object sender, Telerik.Windows.DragDrop.DragEventArgs args)
        {
            var options = DragDropPayloadManager.GetDataFromObject(args.Data, TreeViewDragDropOptions.Key) as TreeViewDragDropOptions;
 
            Person _source = options.DragSourceItem.Item as Person;
            Person _target = options.DropTargetItem.Item as Person;
            Person _ruler = (_target.Rank != Rank.Serf) ? _target : _target.Ruler;
 
            if (_source.CanMoveTo(_ruler))
                options.DropAction = DropAction.Move;
            else
                options.DropAction = DropAction.None;
        }
    }
 
    public class Person
    {
        private string _name;
        private Rank _rank;
        private Person _ruler;
        private List<Person> _subjects;
 
        public Person(string name, Rank rank)
        {
            _name = name;
            _rank = rank;
            _ruler = null;
            _subjects = new List<Person>();
        }
 
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
 
        public Rank Rank
        {
            get { return _rank; }
        }
 
        public Person Ruler
        {
            get { return _ruler; }
        }
 
        public List<Person> Subjects
        {
            get { return _subjects; }
        }
 
        public bool CanMoveTo(Person ruler)
        {
            bool _result;
 
            switch (this._rank)
            {
                case Rank.Baron:
                    switch (ruler.Rank)
                    {
                        case Rank.King:
                            _result = true;
                            break;
 
                        case Rank.Baron:
                        case Rank.Overseer:
                        case Rank.Serf:
                        default:
                            _result = false;
                            break;
                    }
                    break;
 
                case Rank.Overseer:
                    switch (ruler.Rank)
                    {
                        case Rank.King:
                        case Rank.Baron:
                            _result = true;
                            break;
 
                        case Rank.Overseer:
                        case Rank.Serf:
                        default:
                            _result = false;
                            break;
                    }
                    break;
 
                case Rank.Serf:
                    switch (ruler.Rank)
                    {
                        case Rank.King:
                        case Rank.Baron:
                        case Rank.Overseer:
                            _result = true;
                            break;
 
                        case Rank.Serf:
                        default:
                            _result = false;
                            break;
                    }
                    break;
 
                case Rank.King:
                default:
                    _result = false;
                    break;
            }
 
            return _result;
        }
 
        public bool SetRank(Rank rank, Person ruler)
        {
            bool _result;
 
            switch (this._rank)
            {
                case Rank.Baron:
                    switch (rank)
                    {
                        case Rank.Overseer:
                            _result = true;
                            break;
 
                        case Rank.Serf:
                            _result = (this._subjects.Count == 0);
                            break;
 
                        case Rank.King:
                        case Rank.Baron:
                        default:
                            _result = false;
                            break;
                    }
                    break;
 
                case Rank.Overseer:
                    switch (rank)
                    {
                        case Rank.Baron:
                            _result = true;
                            break;
 
                        case Rank.Serf:
                            _result = (this._subjects.Count == 0);
                            break;
 
                        case Rank.King:
                        case Rank.Overseer:
                        default:
                            _result = false;
                            break;
                    }
                    break;
 
                case Rank.Serf:
                    switch (rank)
                    {
                        case Rank.Baron:
                        case Rank.Overseer:
                            _result = true;
                            break;
 
                        case Rank.King:
                        case Rank.Serf:
                        default:
                            _result = false;
                            break;
                    }
                    break;
 
                case Rank.King:
                default:
                    _result = false;
                    break;
            }
 
            if (_result)
            {
                switch (rank)
                {
                    case Rank.Baron:
                        switch (ruler.Rank)
                        {
                            case Rank.King:
                                _result = true;
                                break;
 
                            case Rank.Baron:
                            case Rank.Overseer:
                            case Rank.Serf:
                            default:
                                _result = false;
                                break;
                        }
                        break;
 
                    case Rank.Overseer:
                        switch (ruler.Rank)
                        {
                            case Rank.King:
                            case Rank.Baron:
                                _result = true;
                                break;
 
                            case Rank.Overseer:
                            case Rank.Serf:
                            default:
                                _result = false;
                                break;
                        }
                        break;
 
                    case Rank.Serf:
                        switch (ruler.Rank)
                        {
                            case Rank.King:
                            case Rank.Baron:
                            case Rank.Overseer:
                                _result = true;
                                break;
 
                            case Rank.Serf:
                            default:
                                _result = false;
                                break;
                        }
                        break;
 
                    case Rank.King:
                    default:
                        _result = false;
                        break;
                }
            }
 
            if (_result)
            {
                _rank = rank;
                _ruler = ruler;
            }
 
            return _result;
        }
 
        public bool SetRuler(Person ruler)
        {
            bool _result = false;
 
            if (CanMoveTo(ruler))
            {
                Person _oldruler = this._ruler;
 
                if (_oldruler != null)
                    _oldruler.Subjects.Remove(this);
 
                _ruler = ruler;
                _result = true;
            }
 
            return _result;
        }
 
        public bool AddSubject(Person subject)
        {
            bool _result;
 
            switch (this._rank)
            {
                case Rank.King:
                    switch (subject.Rank)
                    {
                        case Rank.Baron:
                        case Rank.Overseer:
                        case Rank.Serf:
                            _result = true;
                            break;
 
                        case Rank.King:
                        default:
                            _result = false;
                            break;
                    }
                    break;
 
                case Rank.Baron:
                    switch (subject.Rank)
                    {
                        case Rank.Overseer:
                        case Rank.Serf:
                            _result = true;
                            break;
 
                        case Rank.King:
                        case Rank.Baron:
                        default:
                            _result = false;
                            break;
                    }
                    break;
 
                case Rank.Overseer:
                    switch (subject.Rank)
                    {
                        case Rank.Serf:
                            _result = true;
                            break;
 
                        case Rank.King:
                        case Rank.Baron:
                        case Rank.Overseer:
                        default:
                            _result = false;
                            break;
                    }
                    break;
 
                case Rank.Serf:
                default:
                    _result = false;
                    break;
            }
 
            if (_result)
                if (subject.SetRuler(this))
                    _subjects.Add(subject);
 
            return _result;
        }
 
        public override string ToString()
        {
            return _name;
        }
 
        public string Header
        {
            get { return _name; }
            set { _name = value; }
        }
 
        public List<Person> Items
        {
            get { return _subjects; }
            set { _subjects = value; }
        }
    }
 
    public enum Rank
    {
        King,
        Baron,
        Overseer,
        Serf
    }
}
0
Martin Ivanov
Telerik team
answered on 18 Sep 2014, 01:50 PM
Hello Jonathan,

Thank you for the code snippet.

I am not sure that I understand what you mean by that the treeview doesn't update after a move. Can you please clarify what did you mean?

However, I noticed few things that can lead to incorrect behavior. First, I recommend you to use ObservableCollection<T> instead of List<T>, for all collection from your view models that are bound in the visual tree. This way the tree will be notified for the changes in its underlying collections and its UI will be redrawn correctly. 

Also, there is a SetRuler() method used in the Drop event handler, that removes the old ruler and set a new one. When you drag and drop a ruler the SetRuler removes the dragged item from the Subjects collection of the old ruler, but the item is never added in the old ruler. Probably this is the reason behind the reported issue. Moreover, if you drop the dragged item on its initial position you can skip the execution of the SetRuler() method because the ruler will be the same.

public bool SetRuler(Person ruler)
{
    if (ruler == this._ruler) { return false; }
 
    bool _result = false;
 
    if (CanMoveTo(ruler))
    {
        Person _oldruler = this._ruler;
 
             // The code for removing this item from the Subjects collection of the ruler was deleted because the default drag drop logic of the tree automatically will remove the item and add it in the Subjects collection of the target ruler
         
        _ruler = ruler;
 
        _result = true;
    }
 
    return _result;
}

You can also take a look at the Drag  and Drop section of the RadTreeView help documentation and our Drag and Drop demo. In addition I attached a small project with your code. Please give it a try and let me know if it works as expected.

Regards,
Martin
Telerik
 
Check out Telerik Analytics, the service which allows developers to discover app usage patterns, analyze user data, log exceptions, solve problems and profile application performance at run time. Watch the videos and start improving your app based on facts, not hunches.
 
0
Jonathan
Top achievements
Rank 1
answered on 22 Sep 2014, 02:45 PM
That's great, thanks for your hard work :)

Next challenge is to drag new elements from a palette (another treeview), this seems to work but when I want to refresh the palette to restore dragged items my DropCompleted handler doesn't seem to get invoked... code is below, probably I'm doing something dumb...

Jonathan

<Window x:Class="treeviewrealm.MainWindow"
        xmlns:System="clr-namespace:System;assembly=mscorlib"
        xmlns:local="clr-namespace:treeviewrealm"
 
        mc:Ignorable="d"
        d:DataContext="{d:DesignInstance IsDesignTimeCreatable=True, Type={x:Type local:MainWindow}}"
 
        Title="MainWindow"
        Height="600"
        Width="800">
 
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="200"/>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
 
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
         
        <telerik:RadTreeView Name="tvPeople"
                             Margin="5"
                             BorderBrush="Black"
                             BorderThickness="0.5"
                             SelectionMode="Single"
                             IsDragDropEnabled="True"
                             telerik:TreeViewSettings.DragDropExecutionMode="New"
                             ItemsSource="{Binding People, Mode=OneWay, NotifyOnSourceUpdated=True}"/>
 
        <telerik:RadTreeView Name="tvRealm"
                             Margin="5"
                             Grid.Column="1"
                             SelectionMode="Single"
                             IsDragDropEnabled="True"
                             telerik:TreeViewSettings.DragDropExecutionMode="New"
                             ItemsSource="{Binding Realm, Mode=OneWay, NotifyOnSourceUpdated=True}">
            <telerik:RadTreeView.Resources>
                <HierarchicalDataTemplate DataType="{x:Type local:Person}"
                                  ItemsSource="{Binding Path=Subjects}"  >
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding Path=Name}"/>
                    </StackPanel>
                    <HierarchicalDataTemplate.ItemContainerStyle>
                        <Style TargetType="telerik:RadTreeViewItem">
                            <Setter Property="HorizontalAlignment" Value="Stretch"/>
                        </Style>
                    </HierarchicalDataTemplate.ItemContainerStyle>
                </HierarchicalDataTemplate>
            </telerik:RadTreeView.Resources>
        </telerik:RadTreeView>
 
        <telerik:RadTreeView Name="tvClone"
                             Background="LightGray"
                             Grid.Column="2"
                             Margin="5"
                             SelectionMode="Single"
                             IsDragDropEnabled="False"
                             telerik:TreeViewSettings.DragDropExecutionMode="New"
                             ItemsSource="{Binding Realm, Mode=OneWay, NotifyOnSourceUpdated=True}"
                             IsDragPreviewEnabled="False"
                             IsDragTooltipEnabled="False"
                             IsDropPreviewLineEnabled="False">
            <telerik:RadTreeView.Resources>
                <HierarchicalDataTemplate DataType="{x:Type local:Person}"
                                  ItemsSource="{Binding Path=Subjects}"  >
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding Path=FullName}"/>
                    </StackPanel>
                    <HierarchicalDataTemplate.ItemContainerStyle>
                        <Style TargetType="telerik:RadTreeViewItem">
                            <Setter Property="HorizontalAlignment" Value="Stretch"/>
                        </Style>
                    </HierarchicalDataTemplate.ItemContainerStyle>
                </HierarchicalDataTemplate>
            </telerik:RadTreeView.Resources>
        </telerik:RadTreeView>
 
        <TextBlock Margin="5" Grid.Row="1" Text="{Binding Status, Mode=OneWay, NotifyOnSourceUpdated=True}" HorizontalAlignment="Stretch" VerticalAlignment="Center" />
    </Grid>
</Window>

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Telerik.Windows.Controls;
using Telerik.Windows.Controls.TreeView;
using Telerik.Windows.DragDrop;
 
namespace treeviewrealm
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        private ObservableCollection<Person> _realm = new ObservableCollection<Person>();
        private ObservableCollection<Person> _people = new ObservableCollection<Person>();
 
        public MainWindow()
        {
            InitializeComponent();
 
            Person _king = new Person("The King", Rank.King);
            Person _baron1 = new Person("Baron 1", Rank.Baron);
            Person _baron2 = new Person("Baron 2", Rank.Baron);
            Person _overseer1 = new Person("Overseer 1", Rank.Overseer);
            Person _overseer2 = new Person("Overseer 2", Rank.Overseer);
            Person _overseer3 = new Person("Overseer 3", Rank.Overseer);
            Person _overseer4 = new Person("Overseer 4", Rank.Overseer);
            Person _serf1 = new Person("Serf 1", Rank.Serf);
            Person _serf2 = new Person("Serf 2", Rank.Serf);
            Person _serf3 = new Person("Serf 3", Rank.Serf);
            Person _serf4 = new Person("Serf 4", Rank.Serf);
            Person _serf5 = new Person("Serf 5", Rank.Serf);
            Person _serf6 = new Person("Serf 6", Rank.Serf);
            Person _serf7 = new Person("Serf 7", Rank.Serf);
            Person _serf8 = new Person("Serf 8", Rank.Serf);
 
            _realm.Add(_king);
 
            _king.AddSubject(_baron1);
            _king.AddSubject(_baron2);
 
            _baron1.AddSubject(_overseer1);
            _baron1.AddSubject(_overseer2);
            _baron2.AddSubject(_overseer3);
            _baron2.AddSubject(_overseer4);
 
            _overseer1.AddSubject(_serf1);
            _overseer1.AddSubject(_serf2);
            _overseer2.AddSubject(_serf3);
            _overseer2.AddSubject(_serf4);
            _overseer3.AddSubject(_serf5);
            _overseer3.AddSubject(_serf6);
            _overseer4.AddSubject(_serf7);
            _overseer4.AddSubject(_serf8);
 
            ResetPeople();
 
            DataContext = this;
 
            Loaded += MainWindow_Loaded;
        }
 
        void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            DragDropManager.AddDragOverHandler(tvRealm, OnRealmDragOver, true);
            DragDropManager.AddPreviewDropHandler(tvRealm, OnRealmPreviewDrop, true);
            DragDropManager.AddDropHandler(tvRealm, OnRealmDrop, true);
            DragDropManager.AddDragDropCompletedHandler(tvRealm, OnRealmDropCompleted);
 
            DragDropManager.AddDragOverHandler(tvPeople, OnPeopleDragOver, true);
            DragDropManager.AddDragDropCompletedHandler(tvPeople, OnPeopleDropCompleted);
 
            tvRealm.ExpandAll();
            tvClone.ExpandAll();
        }
 
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }
 
        public ObservableCollection<Person> Realm
        {
            get { return _realm; }
        }
 
        public ObservableCollection<Person> People
        {
            get { return _people; }
        }
 
        private string _status = string.Empty;
        public string Status
        {
            get { return _status; }
            set
            {
                _status = value;
                OnPropertyChanged("Status");
            }
        }
 
        private void OnPeopleDragOver(object sender, Telerik.Windows.DragDrop.DragEventArgs e)
        {
            var options = DragDropPayloadManager.GetDataFromObject(e.Data, TreeViewDragDropOptions.Key) as TreeViewDragDropOptions;
            options.DropAction = DropAction.None;
        }
 
        private void OnPeopleDropCompleted(object sender, DragDropCompletedEventArgs e)
        {
            ResetPeople();
        }
 
        private void OnRealmDragOver(object sender, Telerik.Windows.DragDrop.DragEventArgs args)
        {
            var options = DragDropPayloadManager.GetDataFromObject(args.Data, TreeViewDragDropOptions.Key) as TreeViewDragDropOptions;
 
            if (options != null)
            {
                Person _source = options.DragSourceItem.Item as Person;
                Person _target = options.DropTargetItem.Item as Person;
 
                Status = options.DropAction.ToString() + " " + options.DropPosition.ToString() + " " + _target.Name;
 
                if (options.DropPosition == DropPosition.Before | options.DropPosition == DropPosition.After)
                    _target = _target.Ruler;
 
                if (!_source.CanMoveTo(_target))
                    options.DropAction = DropAction.None;
                else
                    options.DropAction = DropAction.Move;
            }
        }
 
        private void OnRealmPreviewDrop(object sender, Telerik.Windows.DragDrop.DragEventArgs args)
        {
            var options = DragDropPayloadManager.GetDataFromObject(args.Data, TreeViewDragDropOptions.Key) as TreeViewDragDropOptions;
 
            if (options != null)
            {
                Person _source = options.DragSourceItem.Item as Person;
                Person _target = options.DropTargetItem.Item as Person;
 
                if (options.DropPosition == DropPosition.Before | options.DropPosition == DropPosition.After)
                    _target = _target.Ruler;
 
                if (!_source.CanMoveTo(_target))
                    options.DropAction = DropAction.None;
                else
                    options.DropAction = DropAction.Move;
            }
        }
 
        private void OnRealmDrop(object sender, Telerik.Windows.DragDrop.DragEventArgs args)
        {
            TreeViewDragDropOptions options = DragDropPayloadManager.GetDataFromObject(args.Data, TreeViewDragDropOptions.Key) as TreeViewDragDropOptions;
 
            if (options != null)
            {
                Person _source = options.DragSourceItem.Item as Person;
                Person _target = options.DropTargetItem.Item as Person;
 
                bool _new = (_source.Ruler != null);
 
                if (options.DropPosition == DropPosition.Before | options.DropPosition == DropPosition.After)
                    _source.SetRuler(_target.Ruler);
                else
                    _source.SetRuler(_target);
 
                if (_new)
                    _target.AddSubject(_source);
 
                OnPropertyChanged("Realm");
 
                ResetPeople();
            }
        }
 
        private void OnRealmDropCompleted(object sender, DragDropCompletedEventArgs e)
        {
            ResetPeople();
        }
 
        private void ResetPeople()
        {
            if (!_people.Any(a => a.Rank == Rank.King))
                _people.Add(new Person("Baron", Rank.King));
 
            if (!_people.Any(a => a.Rank == Rank.Baron))
                _people.Add(new Person("King", Rank.Baron));
 
            if (!_people.Any(a => a.Rank == Rank.Overseer))
                _people.Add(new Person("Overseer", Rank.Overseer));
 
            if (!_people.Any(a => a.Rank == Rank.Serf))
                _people.Add(new Person("Serf", Rank.Serf));
 
            OnPropertyChanged("People");
        }
    }
 
    public class Person
    {
        private string _name;
        private Rank _rank;
        private Person _ruler;
        private ObservableCollection<Person> _subjects;
 
        public Person(string name, Rank rank)
        {
            _name = name;
            _rank = rank;
            _ruler = null;
            _subjects = new ObservableCollection<Person>();
        }
 
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
 
        public string FullName
        {
            get { return _name + " {" + ((_ruler != null) ? _ruler.Name : "None") + "}"; }
        }
 
        public Rank Rank
        {
            get { return _rank; }
        }
 
        public Person Ruler
        {
            get { return _ruler; }
        }
 
        public ObservableCollection<Person> Subjects
        {
            get { return _subjects; }
        }
 
        public bool CanMoveTo(Person newruler)
        {
            bool _result = false;
 
            if (this != newruler)
            {
                switch (this._rank)
                {
                    case Rank.Baron:
                        switch (newruler.Rank)
                        {
                            case Rank.King:
                                _result = true;
                                break;
 
                            case Rank.Baron:
                            case Rank.Overseer:
                            case Rank.Serf:
                            default:
                                break;
                        }
                        break;
 
                    case Rank.Overseer:
                        switch (newruler.Rank)
                        {
                            case Rank.King:
                            case Rank.Baron:
                                _result = true;
                                break;
 
                            case Rank.Overseer:
                            case Rank.Serf:
                            default:
                                break;
                        }
                        break;
 
                    case Rank.Serf:
                        switch (newruler.Rank)
                        {
                            case Rank.King:
                            case Rank.Baron:
                            case Rank.Overseer:
                                _result = true;
                                break;
 
                            case Rank.Serf:
                            default:
                                break;
                        }
                        break;
 
                    case Rank.King:
                    default:
                        break;
                }
            }
 
            return _result;
        }
 
        public bool SetRank(Rank rank, Person ruler)
        {
            bool _result;
 
            switch (this._rank)
            {
                case Rank.Baron:
                    switch (rank)
                    {
                        case Rank.Overseer:
                            _result = true;
                            break;
 
                        case Rank.Serf:
                            _result = (this._subjects.Count == 0);
                            break;
 
                        case Rank.King:
                        case Rank.Baron:
                        default:
                            _result = false;
                            break;
                    }
                    break;
 
                case Rank.Overseer:
                    switch (rank)
                    {
                        case Rank.Baron:
                            _result = true;
                            break;
 
                        case Rank.Serf:
                            _result = (this._subjects.Count == 0);
                            break;
 
                        case Rank.King:
                        case Rank.Overseer:
                        default:
                            _result = false;
                            break;
                    }
                    break;
 
                case Rank.Serf:
                    switch (rank)
                    {
                        case Rank.Baron:
                        case Rank.Overseer:
                            _result = true;
                            break;
 
                        case Rank.King:
                        case Rank.Serf:
                        default:
                            _result = false;
                            break;
                    }
                    break;
 
                case Rank.King:
                default:
                    _result = false;
                    break;
            }
 
            if (_result)
            {
                switch (rank)
                {
                    case Rank.Baron:
                        switch (ruler.Rank)
                        {
                            case Rank.King:
                                _result = true;
                                break;
 
                            case Rank.Baron:
                            case Rank.Overseer:
                            case Rank.Serf:
                            default:
                                _result = false;
                                break;
                        }
                        break;
 
                    case Rank.Overseer:
                        switch (ruler.Rank)
                        {
                            case Rank.King:
                            case Rank.Baron:
                                _result = true;
                                break;
 
                            case Rank.Overseer:
                            case Rank.Serf:
                            default:
                                _result = false;
                                break;
                        }
                        break;
 
                    case Rank.Serf:
                        switch (ruler.Rank)
                        {
                            case Rank.King:
                            case Rank.Baron:
                            case Rank.Overseer:
                                _result = true;
                                break;
 
                            case Rank.Serf:
                            default:
                                _result = false;
                                break;
                        }
                        break;
 
                    case Rank.King:
                    default:
                        _result = false;
                        break;
                }
            }
 
            if (_result)
            {
                _rank = rank;
                _ruler = ruler;
            }
 
            return _result;
        }
 
        public void ResetPerson()
        {
            _ruler = null;
        }
 
        public bool SetRuler(Person ruler)
        {
            if (ruler == this._ruler) { return false; }
 
            bool _result = false;
 
            if (CanMoveTo(ruler))
            {
                _ruler = ruler;
                _result = true;
            }
 
            return _result;
        }
 
        public bool AddSubject(Person subject)
        {
            bool _result;
 
            switch (this._rank)
            {
                case Rank.King:
                    switch (subject.Rank)
                    {
                        case Rank.Baron:
                        case Rank.Overseer:
                        case Rank.Serf:
                            _result = true;
                            break;
 
                        case Rank.King:
                        default:
                            _result = false;
                            break;
                    }
                    break;
 
                case Rank.Baron:
                    switch (subject.Rank)
                    {
                        case Rank.Overseer:
                        case Rank.Serf:
                            _result = true;
                            break;
 
                        case Rank.King:
                        case Rank.Baron:
                        default:
                            _result = false;
                            break;
                    }
                    break;
 
                case Rank.Overseer:
                    switch (subject.Rank)
                    {
                        case Rank.Serf:
                            _result = true;
                            break;
 
                        case Rank.King:
                        case Rank.Baron:
                        case Rank.Overseer:
                        default:
                            _result = false;
                            break;
                    }
                    break;
 
                case Rank.Serf:
                default:
                    _result = false;
                    break;
            }
 
            if (_result)
                if (subject.SetRuler(this))
                    _subjects.Add(subject);
 
            return _result;
        }
 
        public override string ToString()
        {
            return FullName;
        }
 
        public string Header
        {
            get { return _name; }
            set { _name = value; }
        }
 
        public ObservableCollection<Person> Items
        {
            get { return _subjects; }
            set { _subjects = value; }
        }
    }
 
    public enum Rank
    {
        King,
        Baron,
        Overseer,
        Serf
    }
}

0
Martin Ivanov
Telerik team
answered on 23 Sep 2014, 08:59 AM
Hi Jonathan,

The DragDropCompleted event is not invoked because it is handled in the default drag and drop logic of RadTreeView. In order to resolve this you can set the handledEventsToo parameter of the DragDropManager.AddDragDropCompletedHandler() method.

DragDropManager.AddDragDropCompletedHandler(tvPeople, OnPeopleDropCompleted, true);

However, I can suggest you another approach that I think could be more suitable for you then re-adding people in the first tree with the ResetPeople() method. Basically, if the drag source tree is different than the drop target tree you can set the TreeViewDragDropOptions' DropAction to Copy.

Here is an example:
private void OnRealmDragOver(object sender, Telerik.Windows.DragDrop.DragEventArgs args)
{
    var options = DragDropPayloadManager.GetDataFromObject(args.Data, TreeViewDragDropOptions.Key) as TreeViewDragDropOptions;
 
    if (options != null)
    {
        Person _source = options.DragSourceItem.Item as Person;
        Person _target = options.DropTargetItem.Item as Person;
 
        Status = options.DropAction.ToString() + " " + options.DropPosition.ToString() + " " + _target.Name;
 
        if (options.DropPosition == DropPosition.Before | options.DropPosition == DropPosition.After)
            _target = _target.Ruler;
 
        if (!_source.CanMoveTo(_target))
            options.DropAction = DropAction.None;
            // If the drop target tree is different than the drag source tree
        else if (options.DragSourceItem.ParentTreeView != (sender as RadTreeView)) 
        {
            options.DropAction = DropAction.Copy;
        }
        else
        {
            options.DropAction = DropAction.Move;
        }
    }
}

Please give this approach a try and let me know if it works as expected. In addition you can take a look at the Implement Drag and Drop between RadTreeViews and Implement Copy Drag help articles.

Regards,
Martin
Telerik
 
Check out Telerik Analytics, the service which allows developers to discover app usage patterns, analyze user data, log exceptions, solve problems and profile application performance at run time. Watch the videos and start improving your app based on facts, not hunches.
 
Tags
TreeView
Asked by
Jonathan
Top achievements
Rank 1
Answers by
Jonathan
Top achievements
Rank 1
Martin Ivanov
Telerik team
Share this question
or