在 WPF 中分层多个画布
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19041356/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Layering Multiple Canvases in WPF
提问by DeusAduro
So I am quite new to WPF and thought that as a learning experience I would implement a simple level editor in WPF. The purpose of the editor is 2-fold. First I want to be able to define arbitrary oriented bounding boxes as the "solid" area in the level. I then want to be able to place, resize, skew images.
所以我对 WPF 很陌生,并认为作为一种学习经验,我将在 WPF 中实现一个简单的关卡编辑器。编辑器的目的有两个。首先,我希望能够将任意定向的边界框定义为关卡中的“实体”区域。然后我希望能够放置、调整大小、倾斜图像。


I have implemented the ability to draw oriented bounding boxes using a Canvas (See image above). The Canvas and a toolbar are within a dock panel. I am now planning to implement the image capabilities. What I thought to do is create another Canvas layer (perhaps many) for each layer of images. The reason for doing so is that I can easily restrict selection and visibility of each layer. However I am not sure how to properly layer multiple canvas controls. Certainly the DockPanel container I am currently using doesn't let me have multiple controls on top of one another. I thought to embed my Canvas layers within another canvas but I am no sure how to properly set this up (note that the setup should be dynamic in code as I would like to allow users to add more layers as necessary).
我已经实现了使用 Canvas 绘制定向边界框的能力(见上图)。画布和工具栏位于停靠面板内。我现在正计划实施图像功能。我想做的是为每一层图像创建另一个 Canvas 层(可能很多)。这样做的原因是我可以轻松限制每一层的选择和可见性。但是我不确定如何正确地将多个画布控件分层。当然,我目前使用的 DockPanel 容器不允许我在另一个之上拥有多个控件。我想将我的 Canvas 图层嵌入另一个画布中,但我不确定如何正确设置它(请注意,设置在代码中应该是动态的,因为我希望允许用户根据需要添加更多图层)。
The ideal end result would be an arbitrary number of layers that have a transparent background (so we can see the layers behind) and which can be easily hidden. There would also only be 1 layer at a time receiving the user input.
理想的最终结果是具有透明背景的任意数量的层(因此我们可以看到后面的层)并且可以轻松隐藏。一次也只有 1 层接收用户输入。
So my question is, is their a more appropriate approach rather than layering canvases? If layering of canvases is a good method could someone provide links/example code for how this can be setup. What is the optimal container for multiple stacked controls (note the child canvas size should match the parent container).
所以我的问题是,它们是比将画布分层更合适的方法吗?如果画布分层是一个好方法,有人可以提供链接/示例代码来说明如何设置。多个堆叠控件的最佳容器是什么(注意子画布大小应与父容器匹配)。
Cheers!
干杯!
回答by m-y
Might I suggest an alternative instead?
我可以建议一个替代方案吗?
- Create an
ItemsControlwhich utilizes theCanvaspanel as it's drawing surface. - Bind the
ItemsControl.ItemsSourceto a collection of custom objects which contain coordinate information. - Use a
DataTemplateto control how each item is visually represented on the canvas. Alternatively, you could use multipleDataTemplates and use aDataTemplateSelectorto choose which one to apply conditionally.
- 创建一个
ItemsControl利用Canvas面板作为绘图表面的对象。 - 将 绑定
ItemsControl.ItemsSource到包含坐标信息的自定义对象集合。 - 使用 a
DataTemplate来控制每个项目在画布上的视觉呈现方式。或者,您可以使用多个DataTemplates 并使用 aDataTemplateSelector来选择有条件地应用哪个。
XAML:
XAML:
<ItemsControl ItemsSource="{Binding Path=MyObjectList}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Rectangle Canvas.Left="{Binding Path=X}" Canvas.Top="{Binding Path=Y}"
Canvas.ZIndex="{Binding Path=Z}" ... />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
C#:
C#:
public class MyObject
{
public double X { get; set; }
public double Y { get; set; }
public int Z { get; set; }
// Additional proeprties...
}
This is probably a better alternative than stacking a bunch of canvas panels on top of each other.
这可能是比将一堆帆布面板堆叠在一起更好的选择。
An excerpt from a very good resource:
摘自一个非常好的资源:
Let's just recap a couple of things before we get started… In ‘C' is for Collection, we learned that an ItemsControl surfaces a collection of items in a very predictable way (namely, as a CollectionView). Then in ‘D' is for DataTemplate, we learned that an item within the collection can be any CLR object and the visual representation of the item is defined using a template of visual elements (called a DataTemplate).
The next question that logically arises is, “where do we put these visuals?” More specifically, once the data template for an item has been inflated, where should its visuals be positioned? To answer this question, we will now examine how “layout” is handled for items within an ItemsControl.
在开始之前,让我们先回顾一下几件事……在“C”中,“C”代表集合,我们了解到 ItemsControl 以一种非常可预测的方式(即作为 CollectionView)显示项目集合。然后在“D”中用于 DataTemplate,我们了解到集合中的项目可以是任何 CLR 对象,并且项目的视觉表示是使用视觉元素模板(称为 DataTemplate)定义的。
下一个逻辑上出现的问题是,“我们把这些视觉效果放在哪里?” 更具体地说,一旦项目的数据模板膨胀,它的视觉效果应该放在哪里?为了回答这个问题,我们现在将研究如何为 ItemsControl 中的项目处理“布局”。
Basically:
基本上:
- ItemsControl - Collection of items
- DataTemplate - How each item is visually represented
- Panel - How each visual representation is laid out.
- ItemsControl - 项目集合
- DataTemplate - 如何在视觉上表示每个项目
- 面板 - 每个视觉表示的布局方式。

