#240 – Shape vs. DrawingVisual

We’ve seen two ways to render custom 2D geometries–by inheriting from DrawingVisual and hosting in an UIElement or by inheriting from Shape and instancing your object directly in XAML.

You might wonder which of these methods to use for drawing custom 2D objects.

Shape is at a higher level of abstraction than DrawingVisualShape provides the following functionality, beyond what you get with DrawingVisual:

  • Derives from FrameworkElement, so you can include your subclass directly into a logical tree as a child of a Panel
  • Takes care of things like the Pen used to render the geometry (Stroke and StrokeThickness) and the Brush used to fill the interior of the geometry

Below is an example of including several instances of a custom Shape and specifying different stroke/fill properties for each instance.

	<StackPanel Orientation="Horizontal">
		<local:MyWeirdShape Stroke="Black" StrokeThickness="2" Fill="Orange"/>
		<local:MyWeirdShape Stroke="Red" StrokeThickness="1" Fill="DimGray"/>
		<local:MyWeirdShape Stroke="Blue" StrokeThickness="10" Fill="White"/>
	</StackPanel>

#239 – Creating a Custom Shape by Overriding the Shape Class

If you need a specialized shape that you can’t use any of the Shape subclasses to draw, you can create your own custom class that inherits from Shape.

You define the shape to be drawn by overriding the Shape.DefiningGeometry property.  In the get accessor, you create and return an instance of a Geometry.  In the example below, we create a new Geometry and then use the StreamGeometryContext to draw the geometry.

    public class MyWeirdShape : Shape
    {
        protected override Geometry DefiningGeometry
        {
            get { return GenerateMyWeirdGeometry(); }
        }

        private Geometry GenerateMyWeirdGeometry()
        {
            StreamGeometry geom = new StreamGeometry();
            using (StreamGeometryContext gc = geom.Open())
            {
                // isFilled = false, isClosed = true
                gc.BeginFigure(new Point(50.0, 50.0), false, true);
                gc.ArcTo(new Point(75.0, 75.0), new Size(10.0, 20.0), 0.0, false, SweepDirection.Clockwise, true, true);
                gc.ArcTo(new Point(100.0, 100.0), new Size(10.0, 20.0), 0.0, false, SweepDirection.Clockwise, true, true);
            }

            return geom;
        }
    }

Using the new object in XAML:

	<StackPanel>
		<local:MyWeirdShape Height="150" Width="150" Stroke="Black" StrokeThickness="2"/>
	</StackPanel>

Follow

Get every new post delivered to your Inbox.

Join 233 other followers