指定的元素已经是另一个元素的逻辑子元素.先断开它.在用户控制中 [英] Specified element is already the logical child of another element. Disconnect it first. in User Control

查看:23
本文介绍了指定的元素已经是另一个元素的逻辑子元素.先断开它.在用户控制中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个用户控件:

[ContentProperty("Items")]
[DefaultProperty("Items")]
public partial class PanelControl : UserControl
{
    public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register("Orientation", typeof(Orientation), typeof(PanelControl), new FrameworkPropertyMetadata(Orientation.Horizontal, new PropertyChangedCallback(OnOrientationChanged)));
    public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register("Items", typeof(ObservableCollection<UIElement>), typeof(PanelControl), new FrameworkPropertyMetadata(new ObservableCollection<UIElement>(), new PropertyChangedCallback(OnItemsChanged)));
    public static readonly DependencyProperty SizeProperty = DependencyProperty.RegisterAttached("Size", typeof(double), typeof(PanelControl), new FrameworkPropertyMetadata(1.0, new PropertyChangedCallback(OnSizeChanged)), new ValidateValueCallback(IsSizeValid));

    public Orientation Orientation
    {
        get
        {
            return (Orientation)GetValue(OrientationProperty);
        }
        set
        {
            SetValue(OrientationProperty, value);
        }
    }

    public ObservableCollection<UIElement> Items
    {
        get
        {
            return (ObservableCollection<UIElement>)GetValue(ItemsProperty);
        }
        set
        {
            SetValue(ItemsProperty, value);
        }
    }

    public static void SetSize(UIElement element, double size)
    {
        element.SetValue(SizeProperty, size);
    }
    public static double GetSize(UIElement element)
    {
        return (double)element.GetValue(SizeProperty);
    }

    private static void OnOrientationChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
    {
        /*MessageBox.Show("orientation");*/
        ((PanelControl)dependencyObject).ClearAndBuildGrid();
    }

    private static void OnItemsChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
    {
        /*MessageBox.Show("items");*/
        ((PanelControl)dependencyObject).ClearAndBuildGrid();
        if(args.OldValue != null)
            ((ObservableCollection<UIElement>)args.OldValue).CollectionChanged -= ((PanelControl)dependencyObject).OnItemsCollectionChanged;
        if (args.NewValue != null)
            ((ObservableCollection<UIElement>)args.NewValue).CollectionChanged += ((PanelControl)dependencyObject).OnItemsCollectionChanged;

    }

    private void OnItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs args)
    {
        /*MessageBox.Show("collection");*/
        ClearAndBuildGrid();
    }

    private static void OnSizeChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
    {
        ((PanelControl)dependencyObject).ClearAndBuildGrid();
        /*MessageBox.Show("size");*/
    }
    private static bool IsSizeValid(object value)
    {
        return (double)value < 0 ? false : true;
    }

    private void ClearAndBuildGrid()
    {
        MainGrid.Children.Clear();
        MainGrid.RowDefinitions.Clear();
        MainGrid.ColumnDefinitions.Clear();
        /*MessageBox.Show(MainGrid.Children.Count.ToString());*/
        for (int i = 0; i < Items.Count; i++)
        {
            if (Orientation == Orientation.Horizontal)
            {
                MainGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = SizeToGridLength(GetSize(Items[i])) });
                Grid.SetColumn(Items[i], i * 2);
                if (i != Items.Count - 1)
                {
                    MainGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(5) });
                    GridSplitter splitter = new GridSplitter() { ResizeDirection = GridResizeDirection.Columns, HorizontalAlignment = HorizontalAlignment.Stretch };
                    Grid.SetColumn(splitter, i * 2 + 1);
                    MainGrid.Children.Add(splitter);
                }
            }
            else
            {
                MainGrid.RowDefinitions.Add(new RowDefinition() { Height = SizeToGridLength(GetSize(Items[i])) });
                Grid.SetRow(Items[i], i * 2);
                if (i != Items.Count - 1)
                {
                    MainGrid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(5) });
                    GridSplitter splitter = new GridSplitter() { ResizeDirection = GridResizeDirection.Rows, VerticalAlignment = VerticalAlignment.Stretch };
                    Grid.SetRow(splitter, i * 2 + 1);
                    MainGrid.Children.Add(splitter);
                }
            }
            MainGrid.Children.Add(Items[i]);
        }
    }

    private GridLength SizeToGridLength(double size)
    {
        return new GridLength(size, GridUnitType.Star);
    }

    public PanelControl()
    {
        InitializeComponent();
        Items.CollectionChanged += OnItemsCollectionChanged;
    }
}

我在这里使用它:

<p:PanelControl>
    <Button />
    <Button />
    <Button />
</p:PanelControl>

当我启动应用程序时它运行良好,但在设计器中我在 xaml 中的第一个按钮下划线并出现错误指定的元素已经是另一个元素的逻辑子元素.首先断开它."感谢您的帮助,抱歉我的英语不好.

When i start application it works good, but in designer I have underlined first button in xaml and error "Specified element is already the logical child of another element. Disconnect it first." Thanks for help, sorry for my bad English.

推荐答案

不确定设计师的情况,但这会修复"它.

Not sure what is going on with the designer but this will 'fix' it.

换行:

MainGrid.Children.Add(Items[i]);

致:

var parent = VisualTreeHelper.GetParent(Items[i]) as Grid;
if (parent != null)
    parent.Children.Remove(Items[i]);
MainGrid.Children.Add(Items[i]);

这篇关于指定的元素已经是另一个元素的逻辑子元素.先断开它.在用户控制中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆