C # WPF ArgumentException: The specified Visual is already a child of another Visual or CompositionTarget root

I have a list with images and their left / top locations, which I add to the canvas. However, I want to be able to add the same images (same source) to the Canvas, without any problems.

When I just use the following code:

Image img = ImagesList[i].Image; // ImagesList is a list of MyClass (containing Image Image; double Left; double Top)
img.Name = "img" + i; // where i is the nr in the list
Canvas.SetLeft(img, ImagesList[i].Left); // Left default = 0
Canvas.SetTop(img, ImagesList[i].Top); // Top default = 0
MyCanvas.Children.Add(img);
OnPropertyChanged("MyCanvas");

when the same Image (-source) is already present on the Canvas (with a different left / top location and name), I get the following exception:

ArgumentException: Specified Visual is already a child of another Visual or the root of a CompositionTarget.

So, I know that I am not allowed to add the same UIElement (in my case Image) to the same Canvas.

I changed my code to:

// If the Image already exists on the Canvas, we need to make a clone of the image
if (MyCanvas.Children.Contains(img)) {
    Image cloneImg = new Image();
    cloneImg.Source = img.Source;
    cloneImg.Name = img.Name;
    Canvas.SetLeft(cloneImg, Left);
    Canvas.SetTop(cloneImg, Top);
    MyCanvas.Children.Add(cloneImg);
}
else
    MyCanvas.Children.Add(img);
OnPropertyChanged("MyCanvas");

, . , ( ) reset 0,0 ( , ), Console.Write-test, , .

, , Left, Top (, , ) , ( "Clone" )?

.


EDIT: xaml :

<Canvas Name="MyCanvas" Background="LimeGreen"/>

To:

<ItemsControl ItemsSource="{Binding MyField.ImagesList}"> <!-- MyField is the class where I have my list -->
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas Name="FieldCanvas" Background="LimeGreen" IsItemsHost="True"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
        <ItemsControl.ItemContainerStyle>
            <Style TargetType="ContentPresenter">
                <Setter Property="Canvas.Left" Value="{Binding Left}"/>
                <Setter Property="Canvas.Top" Value="{Binding Top}"/>
            </Style>
        </ItemsControl.ItemContainerStyle>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Image Source="{Binding ImageSource}" AllowDrop="True" PreviewMouseLeftButtonDown="Image_PreviewMouseLeftButtonDown" PreviewMouseMove="Image_PreviewMouseMove" PreviewMouseLeftButtonUp="Image_PreviewMouseLeftButtonUp"/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

"ImagesList" BitmapImage Images Image Image.

, . Canvas ViewModel, , , , ItemsControl. MouseEvent, img.Parent, Canvas ( ) canvas.Children, , ZIndex ( isn ).


EDIT2/:

Edit , - , , ImageSource, , , .

+3
2

ItemsControl, Canvas ItemsPanel ItemContainerStyle, Canvas.Left Canvas.Top .

:

public class ImageItem
{
    public string Source { get; set; }
    public double Left { get; set; }
    public double Top { get; set; }
}

public class ViewModel
{
    public ViewModel()
    {
        ImageItems = new ObservableCollection<ImageItem>();
    }

    public ObservableCollection<ImageItem> ImageItems { get; private set; }
}

XAML ItemsControl , . , ItemsSource ImageItems ViewModel.

<ItemsControl ItemsSource="{Binding ImageItems}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas IsItemsHost="True"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
        <ItemsControl.ItemContainerStyle>
            <Style TargetType="ContentPresenter">
                <Setter Property="Canvas.Left" Value="{Binding Path=Left}"/>
                <Setter Property="Canvas.Top" Value="{Binding Path=Top}"/>
            </Style>
        </ItemsControl.ItemContainerStyle>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Image Source="{Binding Path=Source}"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

- MainWindow:

var vm = new ViewModel();
DataContext = vm;

vm.ImageItems.Add(
    new ImageItem
    {
        Source = @"C:\Users\Public\Pictures\Sample Pictures\Koala.jpg",
        Left = 100,
        Top = 50
    });
vm.ImageItems.Add(
    new ImageItem
    {
        Source = @"C:\Users\Public\Pictures\Sample Pictures\Desert.jpg",
        Left = 200,
        Top = 100
    });
+3

, , Clemens, BitmapImage ImageSource Image Image , .

, , . , ( ) , , , , BitmapImage ImageSource, , .

- , Clemens, WPF . .

: "" ImageSource . (), .

0

All Articles