拖放WPF TreeView问题

时间:2018-07-05 13:16:39

标签: c# wpf drag-and-drop treeview

我在TreeView中的WPF中拖放存在问题。 拖放的作品,但不是我想要的。

我的自定义类是PhonesFromStudents

public class PhonesFromStudents
{ 
    public string Name { get; set; }

    public List<string> Phones { get; set; } 
}

构造函数:

 internal MainWindow(List<PhonesFromStudents> list)
    {

        InitializeComponent();
        this.ListStudents = list;
        this.DataContext = this;
    }

这是我的拖放代码:

private void treeView_MouseMove(object sender, MouseEventArgs e)
    {
        try
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                Point currentPosition = e.GetPosition(tv_source);

                if ((Math.Abs(currentPosition.X - _lastMouseDown.X) > 10.0) ||
                    (Math.Abs(currentPosition.Y - _lastMouseDown.Y) > 10.0))
                {

                    draggedItem = (TreeViewItem)(TreeViewItem)sender;
                    if (draggedItem != null)
                    {
                        DragDropEffects finalDropEffect = DragDrop.DoDragDrop(tv_source, tv_source.SelectedValue, DragDropEffects.Move);
                        //Checking target is not null and item is dragging(moving)
                        if ((finalDropEffect == DragDropEffects.Move) && (_target != null))
                        {
                            // A Move drop was accepted
                            if (!draggedItem.Header.ToString().Equals(_target.Header.ToString()))
                            {
                                CopyItem(draggedItem, _target);
                                _target = null;
                                draggedItem = null;
                            }

                        }
                    }
                }
            }
        }
        catch (Exception)
        {
        }
    }
    private void treeView_DragOver(object sender, DragEventArgs e)
    {
        try
        {

            Point currentPosition = e.GetPosition(tv_source);


            if ((Math.Abs(currentPosition.X - _lastMouseDown.X) > 10.0) ||
                (Math.Abs(currentPosition.Y - _lastMouseDown.Y) > 10.0))
            {
                // Verify that this is a valid drop and then store the drop target
                TreeViewItem item = GetNearestContainer(e.OriginalSource as UIElement);
                if (CheckDropTarget(draggedItem, item))
                {
                    e.Effects = DragDropEffects.Move;
                }
                else
                {
                    e.Effects = DragDropEffects.None;
                }
            }
            e.Handled = true;
        }
        catch (Exception)
        {
        }
    }
    private void treeView_Drop(object sender, DragEventArgs e)
    {
        try
        {
            e.Effects = DragDropEffects.None;
            e.Handled = true;

            // Verify that this is a valid drop and then store the drop target
            TreeViewItem TargetItem = GetNearestContainer(e.OriginalSource as UIElement);

            if (TargetItem != null && draggedItem != null)
            {
                _target = TargetItem;
                e.Effects = DragDropEffects.Move;

            }
        }
        catch (Exception)
        {
        }



    }
    private bool CheckDropTarget(TreeViewItem _sourceItem, TreeViewItem _targetItem)
    {
        //Check whether the target item is meeting your condition
        bool _isEqual = false;
        if (!_sourceItem.Header.ToString().Equals(_targetItem.Header.ToString()))
        {
            _isEqual = true;
        }
        return _isEqual;

    }
    private void CopyItem(TreeViewItem _sourceItem, TreeViewItem _targetItem)
    {

        //Asking user wether he want to drop the dragged TreeViewItem here or not
        if (MessageBox.Show("Would you like to drop " + _sourceItem.Header.ToString() + " into " + _targetItem.Header.ToString() + "", "", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
        {
            try
            {
                //adding dragged TreeViewItem in target TreeViewItem
                addChild(_sourceItem, _targetItem);

                //finding Parent TreeViewItem of dragged TreeViewItem 
                TreeViewItem ParentItem = FindVisualParent<TreeViewItem>(_sourceItem);
                // if parent is null then remove from TreeView else remove from Parent TreeViewItem
                if (ParentItem == null)
                {
                    tv_source.Items.Remove(_sourceItem);
                }
                else
                {
                    ParentItem.Items.Remove(_sourceItem);
                }
            }
            catch
            {

            }
        }

    }
    public void addChild(TreeViewItem _sourceItem, TreeViewItem _targetItem)
    {
        // add item in target TreeViewItem 
        TreeViewItem item1 = new TreeViewItem();
        item1.Header = _sourceItem.Header;
        _targetItem.Items.Add(item1);
        foreach (TreeViewItem item in _sourceItem.Items)
        {
            addChild(item, item1);
        }
    }
    static TObject FindVisualParent<TObject>(UIElement child) where TObject : UIElement
    {
        if (child == null)
        {
            return null;
        }

        UIElement parent = VisualTreeHelper.GetParent(child) as UIElement;

        while (parent != null)
        {
            TObject found = parent as TObject;
            if (found != null)
            {
                return found;
            }
            else
            {
                parent = VisualTreeHelper.GetParent(parent) as UIElement;
            }
        }

        return null;
    }
    private TreeViewItem GetNearestContainer(UIElement element)
    {
        // Walk up the element tree to the nearest tree view item.
        TreeViewItem container = element as TreeViewItem;
        while ((container == null) && (element != null))
        {
            element = VisualTreeHelper.GetParent(element) as UIElement;
            container = element as TreeViewItem;
        }
        return container;
    }

我的XAML:

<TreeView x:Name="tv_source" AllowDrop="True" Grid.Row="2" Grid.Column="1" Margin="0,5" HorizontalAlignment="Stretch" ItemsSource="{Binding list}" Background="White" BorderBrush="{x:Null}">
        <TreeView.ItemContainerStyle>
            <Style TargetType="{x:Type TreeViewItem}">
                <!-- We have to select the item which is right-clicked on -->
                <!--<EventSetter Event="TreeViewItem.PreviewMouseRightButtonDown" Handler="TreeViewItem_PreviewMouseRightButtonDown"/>-->
                <EventSetter Event="PreviewDragOver" Handler="treeView_DragOver"/>
                <EventSetter Event="PreviewDrop" Handler="treeView_Drop"/>
                <EventSetter Event="TreeViewItem.MouseMove" Handler="treeView_MouseMove"/>
            </Style>

        </TreeView.ItemContainerStyle>
        <TreeView.Resources>
            <HierarchicalDataTemplate DataType="{x:Type local:PhonesFromStudents}" ItemsSource="{Binding Phones}">
                <TextBlock Text="{Binding Name}" AllowDrop="True"  />
            </HierarchicalDataTemplate>
        </TreeView.Resources>
    </TreeView>

我的问题是,它只会在孩子身上添加一个孩子,而不是在父母身上,这对我不利。

示例:

Thomas
|_____iPhone8
|_____iPhone6

Lucas
|_____iPhone4s
|_____S8

如果我将“ iPhone8”移至“ Lucas”,则无法使用,仅当我将iPhone8移至“ iPhone4s”或“ S8”时,该功能才起作用。

我想要什么:

Thomas
|_____iPhone8
|_____iPhone6
|_____S8

Lucas
|_____iPhone4s

我有什么

  Thomas
   |_____iPhone8
   |_____iPhone6
         |_____S8

   Lucas
   |_____iPhone4s

0 个答案:

没有答案