Wpf 同一应用程序中的拖放按钮引发异常

Wpf 同一应用程序中的拖放按钮引发异常,wpf,drag-and-drop,Wpf,Drag And Drop,我有一个画布,其中包含一个按钮,我想能够拖放到另一个画布。我想把按钮复制到另一个画布上。以下是我正在使用的代码: XAML: <Window> <Grid> <Canvas Height="300" Width="500" Background="Gray"> <Canvas Name="cnvToolB

我有一个画布,其中包含一个按钮,我想能够拖放到另一个画布。我想把按钮复制到另一个画布上。以下是我正在使用的代码:

XAML:

<Window>
    <Grid>
        <Canvas
            Height="300"
            Width="500"
            Background="Gray">
            <Canvas
                Name="cnvToolBox"
                Canvas.Left="10"
                Canvas.Top="10"
                Background="AliceBlue"
                Width="100"
                Height="200">
                <Button
                    Content="Drag Me!"
                    PreviewMouseLeftButtonDown="Button_PreviewMouseLeftButtonDown"
                    PreviewMouseMove="Button_PreviewMouseMove"></Button>
            </Canvas>
            <Rectangle 
                Canvas.Left="119"
                Canvas.Top="9"
                Width="102"
                Height="202"
                StrokeDashArray="0.5 1.0 0.3" 
                Stroke="Black" 
                StrokeThickness="2"/>
            <Canvas    
                Name="cnvButtonDropZone"
                Canvas.Left="120"
                Canvas.Top="10"
                Width="100"
                Height="200"
                Background="LightGreen"
                AllowDrop="True"
                DragEnter="Canvas_DragEnter"
                Drop="Canvas_Drop">
            </Canvas>
        </Canvas>
    </Grid> 
</Window>
在将按钮添加到画布时,当我放下按钮时,会出现以下异常:

指定的元素已经是另一个元素的逻辑子元素。先把它断开

我只是想学习如何拖放控件,但并不确定错误的含义和解决方法。我不知道我错在哪里。欢迎提出任何建议


谢谢

该按钮归其父cnvToolBox所有。在将其添加到画布之前,需要将其从cnvToolBox中删除

            cnvToolBox.Children.Remove(button);
            var canvas = sender as Canvas;
            canvas.Children.Add(button);
这会将按钮从工具箱移动到画布。如果确实要克隆项目,请执行以下操作:

        if (e.Data.GetDataPresent("myFormat"))
        {
            var contentControl = (ContentControl)e.Data.GetData("myFormat");

            var constructorInfo = contentControl.GetType().GetConstructor(new Type[] {});
            if (constructorInfo != null)
            {
                var newElement = (UIElement)constructorInfo.Invoke(new object[]{});

                var newContentControl = newElement as ContentControl;
                if(newContentControl != null)
                {
                    newContentControl.Content = contentControl.Content;
                }

                ((Panel)sender).Children.Add(newElement);
            }
        }

该按钮归其父cnvToolBox所有。在将其添加到画布之前,需要将其从cnvToolBox中删除

            cnvToolBox.Children.Remove(button);
            var canvas = sender as Canvas;
            canvas.Children.Add(button);
这会将按钮从工具箱移动到画布。如果确实要克隆项目,请执行以下操作:

        if (e.Data.GetDataPresent("myFormat"))
        {
            var contentControl = (ContentControl)e.Data.GetData("myFormat");

            var constructorInfo = contentControl.GetType().GetConstructor(new Type[] {});
            if (constructorInfo != null)
            {
                var newElement = (UIElement)constructorInfo.Invoke(new object[]{});

                var newContentControl = newElement as ContentControl;
                if(newContentControl != null)
                {
                    newContentControl.Content = contentControl.Content;
                }

                ((Panel)sender).Children.Add(newElement);
            }
        }

这是因为
按钮
已经有一个与之关联的父项;上一个
画布

Canvas.Children.Remove(button);
您可以将按钮的父级设置为空;这将从逻辑关系中删除它

button.Parent = null;
然后,您可以将该按钮添加到另一个
画布
,就像您在代码隐藏中所做的那样

如果愿意,您还可以直接从
子对象
属性中删除
按钮
,然后将其相应地添加到新的
画布中

Canvas.Children.Remove(button);

这是因为
按钮
已经有一个与之关联的父项;上一个
画布

Canvas.Children.Remove(button);
您可以将按钮的父级设置为空;这将从逻辑关系中删除它

button.Parent = null;
然后,您可以将该按钮添加到另一个
画布
,就像您在代码隐藏中所做的那样

如果愿意,您还可以直接从
子对象
属性中删除
按钮
,然后将其相应地添加到新的
画布中

Canvas.Children.Remove(button);

我将画布(这是一个面板)更改为StackPanel,以便可以添加多个项目。此外,我不会使用“Button Button=sender as Button”之类的语句,除非您在之后立即测试null。如果您知道它必须是一个按钮,请将其转换为按钮。我将画布(这是一个面板)更改为StackPanel,以便可以添加多个项目。此外,我不会使用类似“Button Button=sender as Button”的语句,除非您在之后立即测试空值。如果你知道它必须是一个按钮,就把它转换成一个按钮。