DeusAduro
DeusAduro

Reputation: 6066

Layering Multiple Canvases in WPF

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.

polygon editor image

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

Answers (1)

myermian
myermian

Reputation: 32515

Might I suggest an alternative instead?

  • Create an ItemsControl which utilizes the Canvas panel as it's drawing surface.
  • Bind the ItemsControl.ItemsSource to a collection of custom objects which contain coordinate information.
  • Use a DataTemplate to control how each item is visually represented on the canvas. Alternatively, you could use multiple DataTemplates 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:

  • ItemsControl - Collection of items
  • DataTemplate - How each item is visually represented
  • Panel - How each visual representation is laid out.

Upvotes: 6

Related Questions