NoesisGUI

Rendering shapes

github Tutorial Data

In this tutorial we are going to learn how to use Shapes and Brushes.

Shape elements are used for drawing vector graphics. A Shape has a Fill property, for the background color, and a Stroke property, for the outline color. Both properties are of type Brush. With the StrokeWidth property you can control the thickness of the outline.

NOTE

Shape.Stroke being a Brush rather than a Pen is an unfortunate inconsistency that is present in WPF. We decided to follow the same API in NoesisGUI. Internally, a Pen is indeed used to create the outline of the Shape. But rather than exposing the Pen directly, Shape defines Stroke as a Brush and exposes additional properties to tweak the settings of the internal Pen: StrokeStartLineCap, StrokeEndLineCap, StrokeThickness, and so on.

Brushes

Stroke and Fill properties need to be set to a valid Brush:

  • Solid: to fill the target area with a single color. It has a simple Color property. Because of the type converter that converts string like "Blue" or "#FFFFFFFF" into SolidColorBrushes, they are indistinguishable from their underlying Color in XAML.
  • Linear gradient: to fill an area with a gradient defined by colors at specific points along an imaginary line segment, with linear interpolation between those points.
  • Radial gradient works like LinearGradientBrush, except it has a single starting point with each GradientStop emanating from it in the shape of an ellipse.
  • Image: An image brush paints an area with a bitmap. The ImageSource property is meant to hold the bitmap content. There is a chapter dedicated to ImageBrushes in the Images Tutorial.

Shapes

NoesisGUI supports the following basic shapes:

  • Rectangle: for rectangles or squares with or without rounded corners
ShapesTutorialImg3.jpg
<StackPanel
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    VerticalAlignment="Center">

    <Rectangle Width="200" Height="100"
      Fill="Orange" Stroke="Black" StrokeThickness="10" Margin="4" />
    <Rectangle Width="200" Height="100" RadiusX="10" RadiusY="30"
      Fill="Orange" Stroke="Black" StrokeThickness="10" Margin="4" />
    <Rectangle Width="200" Height="100" RadiusX="30" RadiusY="10"
      Fill="Orange" Stroke="Black" StrokeThickness="10" Margin="4" />
    <Rectangle Width="200" Height="100" RadiusX="100" RadiusY="50"
      Fill="Orange" Stroke="Black" StrokeThickness="10" Margin="4" />

</StackPanel>
spacer.png
  • Ellipse: for drawing ovals or circles
ShapesTutorialImg4.jpg
<StackPanel
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    VerticalAlignment="Center">

    <Ellipse Width="200" Height="100"
      Fill="Orange" Stroke="Black" StrokeThickness="10" Margin="4" />
    <Ellipse Width="100" Height="200"
      Fill="Orange" Stroke="Black" StrokeThickness="10" Margin="4" />

</StackPanel>
spacer.png
  • Line: for segments connecting two points
ShapesTutorialImg5.jpg
<StackPanel
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    VerticalAlignment="Center">

    <Line X1="100" Y1="50" X2="400" Y2="200" Stroke="Orange"
      StrokeThickness="10" Margin="4" />
    <Line X1="100" Y1="0" X2="400" Y2="0" Stroke="Orange"
      StrokeThickness="10" Margin="4" />
    <Line X1="100" Y1="150" X2="400" Y2="0" Stroke="Orange"
      StrokeThickness="10" Margin="4" />

</StackPanel>
spacer.png
  • Path: for complex shapes
ShapesTutorialImg6.jpg
<StackPanel
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    VerticalAlignment="Center">

    <Path Fill="Orange" Stroke="Black" StrokeThickness="10"
      Data="M 80,200 A 100,50 45 1 0 100,50 Z" />

</StackPanel>
spacer.png

Shapes are typically placed inside a Canvas because it supports absolute positioning of its child objects. The following example illustrates some of the basic shapes:

<Canvas
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    Height="300" Width="300" Background="LightGray">

  <Line X1="30" Y1="30" X2="130" Y2="130" Stroke="Black" StrokeThickness="8"
      StrokeStartLineCap="Round" StrokeEndLineCap="Round"/>

  <Ellipse Canvas.Top="25" Canvas.Left="160" Height="120" Width="120"
      StrokeThickness="4" Stroke="Black">
    <Ellipse.Fill>
      <RadialGradientBrush GradientOrigin="0.75,0.25">
        <GradientStop Color="Yellow" Offset="0.0" />
        <GradientStop Color="Orange" Offset="0.5" />
        <GradientStop Color="Red" Offset="1.0" />
      </RadialGradientBrush>
    </Ellipse.Fill>
  </Ellipse>

  <Rectangle Canvas.Left="45" Canvas.Top="250" Height="150" Width="80" RadiusX="9" RadiusY="9"
      Fill="LightBlue" StrokeThickness="2" Stroke="Green" StrokeDashArray="3,1">
    <Rectangle.RenderTransform>
      <RotateTransform Angle="-80" />
    </Rectangle.RenderTransform>
  </Rectangle>

</Canvas>
ShapesTutorialImg1.jpg

Apart from the details already commented above there are the following interesting details in this example:

  • The start and end stroking caps are being changed through the StrokeStartLineCap and StrokeEndLineCap properties.
  • Stroke dashing is set through the StrokeDashArray property.
  • Elements can define their position inside the Canvas through attached properties or changing the RenderTrasform property.
spacer.png

Paths are more complex shapes used to draw figures expressed in a special path markup syntax, a mini-language for making compact code. More information about this language can be found in the SVG specification. Inkscape is an amazing tool for converting from SVG files to XAML path format.

<Canvas
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    Height="440" Width="385">

  <Path Fill="#FFF2F000" Stroke="#FF000000" StrokeThickness="9"
      Data="m 608.07798 229.66418 c -88.45345 78.6253 -223.89753 70.658 -302.52283 -17.79545
        -78.62529 -88.45345 -70.65799 -223.897534 17.79546 -302.522828 86.89794 -77.242622
        219.53868 -71.098432 298.92375 13.846751 L 465.71429 69.505043 z">
    <Path.RenderTransform>
      <TranslateTransform X="-245.7143" Y="150.8571"/>
    </Path.RenderTransform>
  </Path>

  <Ellipse Height="45" Width="45" Fill="#FF000000">
    <Ellipse.RenderTransform>
      <TranslateTransform X="201" Y="110"/>
    </Ellipse.RenderTransform>
  </Ellipse>

</Canvas>
ShapesTutorialImg2.jpg

NOTE

In Inkscape, to generate content that is compatible with NoesisGUI we must activate the Silverlight compatibility mode. This mode generates more efficient and compact content. The line in the file inkscape/share/extensions/svg2xaml.xsl must change from:

<xsl:param name="silverlight_compatible" select="2" />

to

<xsl:param name="silverlight_compatible" select="1" />
© 2017 Noesis Technologies