【发布时间】:2014-03-19 23:11:36
【问题描述】:
我得到了一个包含图像及其左侧/顶部位置的列表,我将其添加到画布中。但是,我希望能够将相同的图像(相同的来源)添加到画布,没有任何问题。
当我只使用以下代码时:
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");
当相同的 Image(-source) 已经出现在画布上时(具有不同的左/上位置和名称),我得到以下异常:
ArgumentException: Specified Visual is already a child of another Visual or the root of a CompositionTarget.
所以我知道我不允许将相同的 UIElement(在我的情况下为 Image)添加到相同的 Canvas。
我将代码修改为:
// 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");
这解决了错误,但现在我遇到了一个新问题。我确实在画布上获得了两个图像,但是已经存在的图像将其位置(左侧和顶部)重置为 0,0(与新的相同)添加了图像),当我进行 Console.Write-test 时,我还注意到画布上的两个图像的名称现在是相同的。
克隆使第一个图像的名称、左侧、顶部(可能还有其他内容)与第二个图像(“克隆”)相同的克隆有什么问题?
提前感谢您的回复。
编辑:在 Clemens 的建议下,我将我的 xaml 更改为:
<Canvas Name="MyCanvas" Background="LimeGreen"/>
收件人:
<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 ImagesSource 而不是 Image Image。
但我还不能测试它,因为它给出了一堆错误。例如,我在 ViewModel 的构造函数中使用 Canvas 作为参数,但现在不知道如何访问它,因为它位于 ItemsControl 中。 而且我在 MouseEvent 函数中也遇到了一些错误,我使用 img.Parent 来获取 Canvas (不再使用上面的代码)和 canvas.Children 来获取所有图像,包括它们的 ZIndex (这也是'不再工作了)。
EDIT2 / 解决方案:
撤消上面的编辑后,因为我的其他糟糕的代码部分导致了很多错误,除了我保存在列表中的 ImageSource 而不是 Image 本身,结果证明它现在可以工作了。
【问题讨论】:
-
你应该以不同的方式做整个事情。使用带有 Canvas 作为 ItemsPanel 和 ItemContainerStyle 的 ItemsControl,绑定每个图像项的 Left 和 Top 属性。
-
我注意到您在发布的代码中使用了
cloneImage和cloneImg。是错字吗? -
@Vanlalhriata 是的,这是一个错字。固定。
-
@Clemens 你能给出一个代码示例吗?我对 C# WPF 有点陌生。根据您的建议,我对迄今为止的尝试进行了编辑。
标签: c# wpf canvas clone argumentexception