Codesnippet, A simple custom hexagon shape for WPF/Silverlight
Recently I’ve been trying to learn more about WPF, since WinForms is getting really old now. As a small exercise I was trying to create a custom Shape
, so I created a new class, derived it from Shape
and started following this tutorial untill I found out that you can’t override the DefiningGeometry
method in Silverlight.
After some searching I found this MSDN Blog article, where in Silverlight a custom shape is created by extending from Path
(well I wouldn’t have thought of that).
After a bit of tweaking I adapted the class to display a Hexagon instead of a Triangle:
namespace MyProject.Shapes
{
public class Hexagon : Path
{
public Hexagon()
{
CreateDataPath(0, 0);
}
private void CreateDataPath(double width, double height)
{
height -= this.StrokeThickness;
width -= this.StrokeThickness;
//Prevent layout loop
if(lastWidth == width && lastHeight == height)
return;
lastWidth = width;
lastHeight = height;
PathGeometry geometry = new PathGeometry();
figure = new PathFigure();
//See for figure info http://etc.usf.edu/clipart/50200/50219/50219_area_hexagon_lg.gif
figure.StartPoint = new Point(0.25 * width, 0);
AddPoint(0.75 * width, 0);
AddPoint(width, 0.5 * height);
AddPoint(0.75 * width, height);
AddPoint(0.25 * width, height);
AddPoint(0, 0.5 * height);
figure.IsClosed = true;
geometry.Figures.Add(figure);
this.Data = geometry;
}
private void AddPoint(double x, double y)
{
LineSegment segment = new LineSegment();
segment.Point = new Point(x + 0.5 * StrokeThickness,
y + 0.5 * StrokeThickness);
figure.Segments.Add(segment);
}
protected override Size MeasureOverride(Size availableSize)
{
return availableSize;
}
protected override Size ArrangeOverride(Size finalSize)
{
CreateDataPath(finalSize.Width, finalSize.Height);
return finalSize;
}
#region FieldsAndProperties
private double lastWidth = 0;
private double lastHeight = 0;
private PathFigure figure;
#endregion
}
You can use a ‘shape’ like this in XAML:
<UserControl x:Class="FantasyCartographer.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:Shapes="clr-namespace:MyNameSpace.Shapes"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<Canvas Height="161" HorizontalAlignment="Left" Margin="27,32,0,0" Name="canvas1" VerticalAlignment="Top" Width="254">
<Shapes:Hexagon Canvas.Left="0" Canvas.Top="0" Height="154" x:Name="hexagon1" Stroke="Black" StrokeThickness="3" Width="188" Fill="Red" />
</Canvas>
</Grid>
</UserControl>
Tip: don’t forget to define an xmlns
namespace mapping to your own .NET namespaces so that you can use a shape even if you defined it in another namespace, I’ve done this in the above XAML
code as an example.
- roytries
- roy-t
- roytri