You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF中添加椭圆控件抛出指定视觉元素已存在异常如何解决?

解决WPF中重复添加同一Ellipse实例到Grid引发的异常问题

我有一个空白多米诺骨牌,尝试通过以下Arrange方法为Grid控件填充圆点,但执行grid.Children.Add(e)时抛出**"Specified visual is already a child of another visual or root of a CompositionTarget"**异常,已知原因是同一个Ellipse实例被重复添加到Grid中,求解决方案。

原Arrange方法代码

private void Arrange(Grid grid, byte dots)
{

    Ellipse e = new Ellipse
    {
        Fill = new SolidColorBrush(Colors.Black)
    };

    Border b = new Border
    {
        Background = new SolidColorBrush(Colors.Black),
        Margin = new Thickness(0, 5, 0, 5),
        CornerRadius = new CornerRadius(2.5)
    };

    //BoneView.Layout.Children.Add(b);
    Grid.SetColumn(b, 1);

    if (dots == 0)
        return;

    if (dots == 1)
    {
        grid.Children.Add(e);
        Grid.SetColumn(e, 1);
        Grid.SetRow(e, 1);
        return;
    }

    if (dots == 2)
    {
        List<Ellipse> ellipses = new List<Ellipse>();
        for (int i = 0; i < dots; i++)
        {
            ellipses.Add(e);
            grid.Children.Add(ellipses[i]);
        }


        Grid.SetColumn(ellipses[1], 2);
        Grid.SetRow(ellipses[1], 2);
        return;
    }

    if (dots == 3)
    {
        List<Ellipse> ellipses = new List<Ellipse>();
        for (int i = 0; i < dots; i++)
        {
            ellipses.Add(e);
            grid.Children.Add(ellipses[i]);
        }


        Grid.SetColumn(ellipses[1], 2);
        Grid.SetRow(ellipses[1], 2);

        Grid.SetColumn(ellipses[2], 1);
        Grid.SetRow(ellipses[2], 1);
        return;
    }

    if (dots == 4)
    {
        List<Ellipse> ellipses = new List<Ellipse>();
        for (int i = 0; i < dots; i++)
        {
            ellipses.Add(e);
            grid.Children.Add(ellipses[i]);
        }


        Grid.SetColumn(ellipses[1], 2);
        Grid.SetRow(ellipses[1], 2);

        Grid.SetColumn(ellipses[2], 2);
        Grid.SetRow(ellipses[2], 0);

        Grid.SetColumn(ellipses[3], 0);
        Grid.SetRow(ellipses[3], 2);
        return;
    }

    if (dots == 5)
    {
        List<Ellipse> ellipses = new List<Ellipse>();
        for (int i = 0; i < dots; i++)
        {
            ellipses.Add(e);
            grid.Children.Add(ellipses[i]);
        }


        Grid.SetColumn(ellipses[1], 2);
        Grid.SetRow(ellipses[1], 2);

        Grid.SetColumn(ellipses[2], 2);
        Grid.SetRow(ellipses[2], 0);

        Grid.SetColumn(ellipses[3], 0);
        Grid.SetRow(ellipses[3], 2);

        Grid.SetColumn(ellipses[4], 1);
        Grid.SetRow(ellipses[4], 1);
        return;
    }

    if (dots == 6)
    {
        List<Ellipse> ellipses = new List<Ellipse>();
        for (int i = 0; i < dots; i++)
        {
            ellipses.Add(e);
            grid.Children.Add(ellipses[i]);
        }

        Grid.SetColumn(ellipses[1], 2);
        Grid.SetRow(ellipses[1], 2);

        Grid.SetColumn(ellipses[2], 2);
        Grid.SetRow(ellipses[2], 0);

        Grid.SetColumn(ellipses[3], 0);
        Grid.SetRow(ellipses[3], 2);

        Grid.SetColumn(ellipses[4], 1);
        Grid.SetRow(ellipses[4], 0);

        Grid.SetColumn(ellipses[5], 1);
        Grid.SetRow(ellipses[5], 2);
        return;
    }
}

多米诺骨牌XAML布局

<Border Background="AntiqueWhite"
        CornerRadius="7"
        >

    <Grid Name="Layout">
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition Width="5"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>

        <Grid Grid.Column="0" x:Name="Left">
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>

        </Grid>

        <Grid Grid.Column="2" x:Name="Right">
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>

        </Grid>

    </Grid>

</Border>

问题根源

你在代码中只创建了一个Ellipse实例e,后续循环里反复将这个实例添加到Grid的子元素集合中。WPF的视觉元素属于独占式父容器,同一个元素不能同时被多个父容器持有,也不能重复添加到同一个父容器,因此触发异常。

解决方案

为每个圆点创建独立的Ellipse实例,同时简化冗余的代码逻辑:

修复后的代码

private void Arrange(Grid grid, byte dots)
{
    // 创建中间分隔线(按需启用添加到Layout的代码)
    Border b = new Border
    {
        Background = new SolidColorBrush(Colors.Black),
        Margin = new Thickness(0, 5, 0, 5),
        CornerRadius = new CornerRadius(2.5)
    };
    Grid.SetColumn(b, 1);
    // BoneView.Layout.Children.Add(b);

    if (dots == 0)
        return;

    // 预定义不同点数对应的圆点位置(行索引, 列索引)
    var dotPositionMap = new Dictionary<byte, List<(int Row, int Col)>>
    {
        {1, new List<(int, int)> {(1, 1)}},
        {2, new List<(int, int)> {(0, 0), (2, 2)}},
        {3, new List<(int, int)> {(0, 0), (2, 2), (1, 1)}},
        {4, new List<(int, int)> {(0, 0), (2, 2), (0, 2), (2, 0)}},
        {5, new List<(int, int)> {(0, 0), (2, 2), (0, 2), (2, 0), (1, 1)}},
        {6, new List<(int, int)> {(0, 0), (2, 2), (0, 2), (2, 0), (0, 1), (2, 1)}}
    };

    // 遍历位置,创建新Ellipse并添加到Grid
    foreach (var (row, col) in dotPositionMap[dots])
    {
        Ellipse dot = CreateDot();
        grid.Children.Add(dot);
        Grid.SetRow(dot, row);
        Grid.SetColumn(dot, col);
    }
}

// 封装创建圆点的方法,每次调用生成新实例
private Ellipse CreateDot()
{
    return new Ellipse
    {
        Fill = new SolidColorBrush(Colors.Black),
        Width = 12, // 可根据布局调整大小
        Height = 12,
        Margin = new Thickness(2) // 可选:添加间距避免圆点贴边
    };
}

修复说明

  1. 独立实例创建:通过CreateDot方法每次生成全新的Ellipse对象,彻底避免重复添加同一实例的问题。
  2. 逻辑简化:用字典存储不同点数对应的圆点坐标,替代原有大量if-else分支,代码可读性和可维护性大幅提升。
  3. 样式统一:圆点的样式(颜色、大小、间距)集中在CreateDot方法中,后续修改只需调整这一处。

内容的提问来源于stack exchange,提问作者Cover Basha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 20:14:57