WPF – Designing Canvas based 2D Controls

I have been playing with Expression Design a little bit, and am quite excited about the designability options it allows. It's really sweet how quickly one can create vector content in it, which can be turned into interactive controls, with shared code-based behaviors attached to each shape. One process I have been exploring is the ideal way to modify my content as I go along, as I tweak graphics in iterations.

My favourite approach thus far is to export Designer content as a ResourceDictionary, which can be loaded(or potentially reload without compilation) on the fly, without having to make any changes to the xaml exported by Expression. This means you can painlessly tune 2D designs, export them and they just load up, without any supporting code changes needed once the pipeline is in place. 


Here's how I go at it:

1.   Create shapes, and give each shape object a distinctive name. Sorry about the lame programmer art.

Expression Designer with Objects

2.   Export XAML to Resource Dictionary Form. Group by Objects, Path output type as drawing brush.

3.   Reference the Resource Dictionary, and populate each each object into your control by iterating through the dictionary. For flexible, custom layout, I prefer to extract the geometries for use as Paths in a Canvas, and prepare a User control out of that. You may prefer to recieve your content in a more general form, ie - directly as a drawingbrush. Below is the sample app using the canvas with the loaded dictionary content, along with textboxes overlayed with the object names, and mouseover-driven bitmap effects. The source code for use in a standard WPF project is attached.

4.   For extra credit, we apply that canvas onto an interactive 3D surface as per the Codeplex WPF 3D Tools bits. And here, life gets interesting, as we can have interactive 2D content on a 3D surface, which we can change on the fly in Expression Designer!


Essential Details from attached code:

//Load the Resource from your exported xaml - Your uri path will differ
Resources.Source = new Uri("pack://application:,,,/CanvasControl;component/ResourceSet.xaml");

        //Here I produce a canvas generated from our exported resource
        private Canvas MakeCanvas()
            Canvas c=new Canvas();
            //You can extract the bounds of the individual elements, or operate with a fixed size here
            c.Width = 443;
            c.Height = 355;
            foreach (DictionaryEntry de in Resources)
                DrawingBrush db = (de.Value as DrawingBrush);
                if (db != null)
                    DrawingGroup dg = (db.Drawing as DrawingGroup);
                    if (dg != null)
                        GeometryDrawing gd = (dg.Children[0] as GeometryDrawing);
                        if (gd != null)
                            Path path = new Path();
                            path.Name = (string)de.Key;

                            //Directly assign the pertinent properties of interest
                            path.Data = gd.Geometry;
                            path.Stroke = gd.Pen.Brush;
                            path.StrokeThickness = gd.Pen.Thickness;
                            path.Fill = gd.Brush;

            return c;


Comments (0)

Skip to main content