void ShowPreview(SharpTreeViewItem item, DropPlace place)
        {
            previewNodeView = item.NodeView;
            previewPlace    = place;

            if (place == DropPlace.Inside)
            {
                previewNodeView.TextBackground = SystemColors.HighlightBrush;
                previewNodeView.Foreground     = SystemColors.HighlightTextBrush;
            }
            else
            {
                if (insertMarker == null)
                {
                    var adornerLayer = AdornerLayer.GetAdornerLayer(this);
                    var adorner      = new GeneralAdorner(this);
                    insertMarker  = new InsertMarker();
                    adorner.Child = insertMarker;
                    adornerLayer.Add(adorner);
                }

                insertMarker.Visibility = Visibility.Visible;

                var p1 = previewNodeView.TransformToVisual(this).Transform(new Point());
                var p  = new Point(p1.X + previewNodeView.CalculateIndent() + 4.5, p1.Y - 3);

                if (place == DropPlace.After)
                {
                    p.Y += previewNodeView.ActualHeight;
                }

                insertMarker.Margin = new Thickness(p.X, p.Y, 0, 0);

                SharpTreeNodeView secondNodeView = null;
                var index = flattener.IndexOf(item.Node);

                if (place == DropPlace.Before)
                {
                    if (index > 0)
                    {
                        secondNodeView = (ItemContainerGenerator.ContainerFromIndex(index - 1) as SharpTreeViewItem).NodeView;
                    }
                }
                else if (index + 1 < flattener.Count)
                {
                    secondNodeView = (ItemContainerGenerator.ContainerFromIndex(index + 1) as SharpTreeViewItem).NodeView;
                }

                var w = p1.X + previewNodeView.ActualWidth - p.X;

                if (secondNodeView != null)
                {
                    var p2 = secondNodeView.TransformToVisual(this).Transform(new Point());
                    w = Math.Max(w, p2.X + secondNodeView.ActualWidth - p.X);
                }

                insertMarker.Width = w + 10;
            }
        }
        List <DropTarget> BuildDropTargets(SharpTreeViewItem item, DragEventArgs e)
        {
            var result = new List <DropTarget>();
            var node   = item.Node;

            if (AllowDropOrder)
            {
                TryAddDropTarget(result, item, DropPlace.Before, e);
            }

            TryAddDropTarget(result, item, DropPlace.Inside, e);

            if (AllowDropOrder)
            {
                if (node.IsExpanded && node.Children.Count > 0)
                {
                    var firstChildItem = ItemContainerGenerator.ContainerFromItem(node.Children[0]) as SharpTreeViewItem;
                    TryAddDropTarget(result, firstChildItem, DropPlace.Before, e);
                }
                else
                {
                    TryAddDropTarget(result, item, DropPlace.After, e);
                }
            }

            var h  = item.ActualHeight;
            var y1 = 0.2 * h;
            var y2 = h / 2;
            var y3 = h - y1;

            if (result.Count == 2)
            {
                if (result[0].Place == DropPlace.Inside &&
                    result[1].Place != DropPlace.Inside)
                {
                    result[0].Y = y3;
                }
                else if (result[0].Place != DropPlace.Inside &&
                         result[1].Place == DropPlace.Inside)
                {
                    result[0].Y = y1;
                }
                else
                {
                    result[0].Y = y2;
                }
            }
            else if (result.Count == 3)
            {
                result[0].Y = y1;
                result[1].Y = y3;
            }
            if (result.Count > 0)
            {
                result[result.Count - 1].Y = h;
            }
            return(result);
        }
        internal void HandleDragOver(SharpTreeViewItem item, DragEventArgs e)
        {
            HidePreview();

            var target = GetDropTarget(item, e);

            if (target != null)
            {
                e.Handled = true;
                ShowPreview(target.Item, target.Place);
            }
        }
        protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
        {
            base.PrepareContainerForItemOverride(element, item);
            SharpTreeViewItem container = element as SharpTreeViewItem;

            container.ParentTreeView = this;
            // Make sure that the line renderer takes into account the new bound data
            if (container.NodeView != null)
            {
                container.NodeView.LinesRenderer.InvalidateVisual();
            }
        }
        DropTarget GetDropTarget(SharpTreeViewItem item, DragEventArgs e)
        {
            var dropTargets = BuildDropTargets(item, e);
            var y           = e.GetPosition(item).Y;

            foreach (var target in dropTargets)
            {
                if (target.Y >= y)
                {
                    return(target);
                }
            }
            return(null);
        }
        internal void HandleDrop(SharpTreeViewItem item, DragEventArgs e)
        {
            try {
                HidePreview();

                var target = GetDropTarget(item, e);
                if (target != null)
                {
                    e.Handled = true;
                    target.Node.InternalDrop(e, target.Index);
                }
            } catch (Exception ex) {
                Debug.WriteLine(ex.ToString());
                throw;
            }
        }
        void TryAddDropTarget(List <DropTarget> targets, SharpTreeViewItem item, DropPlace place, DragEventArgs e)
        {
            SharpTreeNode node;
            int           index;

            GetNodeAndIndex(item, place, out node, out index);

            if (node != null)
            {
                e.Effects = DragDropEffects.None;
                if (node.CanDrop(e, index))
                {
                    DropTarget target = new DropTarget()
                    {
                        Item  = item,
                        Place = place,
                        Node  = node,
                        Index = index
                    };
                    targets.Add(target);
                }
            }
        }
        void TryAddDropTarget(List<DropTarget> targets, SharpTreeViewItem item, DropPlace place, DragEventArgs e)
        {
            SharpTreeNode node;
            int index;

            GetNodeAndIndex(item, place, out node, out index);

            if (node != null) {
                e.Effects = DragDropEffects.None;
                if (node.CanDrop(e, index)) {
                    DropTarget target = new DropTarget() {
                        Item = item,
                        Place = place,
                        Node = node,
                        Index = index
                    };
                    targets.Add(target);
                }
            }
        }
        void ShowPreview(SharpTreeViewItem item, DropPlace place)
        {
            previewNodeView = item.NodeView;
            previewPlace = place;

            if (place == DropPlace.Inside) {
                previewNodeView.TextBackground = SystemColors.HighlightBrush;
                previewNodeView.Foreground = SystemColors.HighlightTextBrush;
            }
            else {
                if (insertMarker == null) {
                    var adornerLayer = AdornerLayer.GetAdornerLayer(this);
                    var adorner = new GeneralAdorner(this);
                    insertMarker = new InsertMarker();
                    adorner.Child = insertMarker;
                    adornerLayer.Add(adorner);
                }

                insertMarker.Visibility = Visibility.Visible;

                var p1 = previewNodeView.TransformToVisual(this).Transform(new Point());
                var p = new Point(p1.X + previewNodeView.CalculateIndent() + 4.5, p1.Y - 3);

                if (place == DropPlace.After) {
                    p.Y += previewNodeView.ActualHeight;
                }

                insertMarker.Margin = new Thickness(p.X, p.Y, 0, 0);

                SharpTreeNodeView secondNodeView = null;
                var index = flattener.IndexOf(item.Node);

                if (place == DropPlace.Before) {
                    if (index > 0) {
                        secondNodeView = (ItemContainerGenerator.ContainerFromIndex(index - 1) as SharpTreeViewItem).NodeView;
                    }
                }
                else if (index + 1 < flattener.Count) {
                    secondNodeView = (ItemContainerGenerator.ContainerFromIndex(index + 1) as SharpTreeViewItem).NodeView;
                }

                var w = p1.X + previewNodeView.ActualWidth - p.X;

                if (secondNodeView != null) {
                    var p2 = secondNodeView.TransformToVisual(this).Transform(new Point());
                    w = Math.Max(w, p2.X + secondNodeView.ActualWidth - p.X);
                }

                insertMarker.Width = w + 10;
            }
        }
        void GetNodeAndIndex(SharpTreeViewItem item, DropPlace place, out SharpTreeNode node, out int index)
        {
            node = null;
            index = 0;

            if (place == DropPlace.Inside) {
                node = item.Node;
                index = node.Children.Count;
            }
            else if (place == DropPlace.Before) {
                if (item.Node.Parent != null) {
                    node = item.Node.Parent;
                    index = node.Children.IndexOf(item.Node);
                }
            }
            else {
                if (item.Node.Parent != null) {
                    node = item.Node.Parent;
                    index = node.Children.IndexOf(item.Node) + 1;
                }
            }
        }
 DropTarget GetDropTarget(SharpTreeViewItem item, DragEventArgs e)
 {
     var dropTargets = BuildDropTargets(item, e);
     var y = e.GetPosition(item).Y;
     foreach (var target in dropTargets) {
         if (target.Y >= y) {
             return target;
         }
     }
     return null;
 }
        List<DropTarget> BuildDropTargets(SharpTreeViewItem item, DragEventArgs e)
        {
            var result = new List<DropTarget>();
            var node = item.Node;

            if (AllowDropOrder) {
                TryAddDropTarget(result, item, DropPlace.Before, e);
            }

            TryAddDropTarget(result, item, DropPlace.Inside, e);

            if (AllowDropOrder) {
                if (node.IsExpanded && node.Children.Count > 0) {
                    var firstChildItem = ItemContainerGenerator.ContainerFromItem(node.Children[0]) as SharpTreeViewItem;
                    TryAddDropTarget(result, firstChildItem, DropPlace.Before, e);
                }
                else {
                    TryAddDropTarget(result, item, DropPlace.After, e);
                }
            }

            var h = item.ActualHeight;
            var y1 = 0.2 * h;
            var y2 = h / 2;
            var y3 = h - y1;

            if (result.Count == 2) {
                if (result[0].Place == DropPlace.Inside &&
                    result[1].Place != DropPlace.Inside) {
                    result[0].Y = y3;
                }
                else if (result[0].Place != DropPlace.Inside &&
                         result[1].Place == DropPlace.Inside) {
                    result[0].Y = y1;
                }
                else {
                    result[0].Y = y2;
                }
            }
            else if (result.Count == 3) {
                result[0].Y = y1;
                result[1].Y = y3;
            }
            if (result.Count > 0) {
                result[result.Count - 1].Y = h;
            }
            return result;
        }
        internal void HandleDrop(SharpTreeViewItem item, DragEventArgs e)
        {
            try {
                HidePreview();

                var target = GetDropTarget(item, e);
                if (target != null) {
                    e.Handled = true;
                    target.Node.InternalDrop(e, target.Index);
                }
            } catch (Exception ex) {
                Debug.WriteLine(ex.ToString());
                throw;
            }
        }
        internal void HandleDragOver(SharpTreeViewItem item, DragEventArgs e)
        {
            HidePreview();

            var target = GetDropTarget(item, e);
            if (target != null) {
                e.Handled = true;
                ShowPreview(target.Item, target.Place);
            }
        }
 internal void HandleDragLeave(SharpTreeViewItem item, DragEventArgs e)
 {
     HidePreview();
     e.Handled = true;
 }
 internal void HandleDragEnter(SharpTreeViewItem item, DragEventArgs e)
 {
     HandleDragOver(item, e);
 }
        protected override void OnKeyDown(KeyEventArgs e)
        {
            SharpTreeViewItem container = e.OriginalSource as SharpTreeViewItem;

            switch (e.Key)
            {
            case Key.Left:
                if (container != null && ItemsControl.ItemsControlFromItemContainer(container) == this)
                {
                    if (container.Node.IsExpanded)
                    {
                        container.Node.IsExpanded = false;
                    }
                    else if (container.Node.Parent != null)
                    {
                        this.FocusNode(container.Node.Parent);
                    }
                    e.Handled = true;
                }
                break;

            case Key.Right:
                if (container != null && ItemsControl.ItemsControlFromItemContainer(container) == this)
                {
                    if (!container.Node.IsExpanded && container.Node.ShowExpander)
                    {
                        container.Node.IsExpanded = true;
                    }
                    else if (container.Node.Children.Count > 0)
                    {
                        // jump to first child:
                        container.MoveFocus(new TraversalRequest(FocusNavigationDirection.Down));
                    }
                    e.Handled = true;
                }
                break;

            case Key.Return:
            case Key.Space:
                if (container != null && Keyboard.Modifiers == ModifierKeys.None && this.SelectedItems.Count == 1 && this.SelectedItem == container.Node)
                {
                    container.Node.ActivateItem(e);
                }
                break;

            case Key.Add:
                if (container != null && ItemsControl.ItemsControlFromItemContainer(container) == this)
                {
                    container.Node.IsExpanded = true;
                    e.Handled = true;
                }
                break;

            case Key.Subtract:
                if (container != null && ItemsControl.ItemsControlFromItemContainer(container) == this)
                {
                    container.Node.IsExpanded = false;
                    e.Handled = true;
                }
                break;

            case Key.Multiply:
                if (container != null && ItemsControl.ItemsControlFromItemContainer(container) == this)
                {
                    container.Node.IsExpanded = true;
                    ExpandRecursively(container.Node);
                    e.Handled = true;
                }
                break;
            }
            if (!e.Handled)
            {
                base.OnKeyDown(e);
            }
        }
 internal void HandleDragEnter(SharpTreeViewItem item, DragEventArgs e)
 {
     HandleDragOver(item, e);
 }
 internal void HandleDragLeave(SharpTreeViewItem item, DragEventArgs e)
 {
     HidePreview();
     e.Handled = true;
 }