Reputation: 6066
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.
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).
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.
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!
Upvotes: 2
Views: 9727
Reputation: 32515
Might I suggest an alternative instead?
ItemsControl
which utilizes the Canvas
panel as it's drawing surface.ItemsControl.ItemsSource
to a collection of custom objects which contain coordinate information.DataTemplate
to control how each item is visually represented on the canvas. Alternatively, you could use multiple DataTemplate
s and use a DataTemplateSelector
to choose which one to apply conditionally.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#:
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.
Basically:
Upvotes: 6