Click here to Skip to main content
15,886,873 members
Articles / Desktop Programming / WPF
Tip/Trick

Grid/Canvas Lined and Squared

Rate me:
Please Sign up or sign in to vote.
4.94/5 (8 votes)
25 Nov 2013CPOL2 min read 18.1K   10   4
How to produce a dynamic lined or squared background on a canvas/grid

Introduction

Imagine a grid/canvas you want to present lined or squared to the user:

Image 1

Using MVVM and WPF, you can avoid overloading your Grid or Canvas with many Line-objects on the screen and you can avoid a lot of work whenever redrawing and adapting the lines to user inputs is necessary.

Background

Sometimes it is really useful - or necessary - to draw many lines by yourself. But that can become rather challenging. Using StreamGeometry and a small algorithm, you can do the whole thing with one Path-object for all horizontal lines (and a second Path-object for all vertical lines if needed) on the screen and updating them via RaisePropertyChanged whenever necessary. Fast as hell. That's it!

Image 2

This code-example first used Solution A. Today I had the idea of Solution B, which should make it even easier.

Using the Code

In your WPF/XAML, simply add:

XML
<Path Data="{Binding MyHorizontalLines}" Stroke="{Binding MyColor}" StrokeThickness="1" 
  RenderOptions.EdgeMode="Aliased" 
  IsHitTestVisible="False" HorizontalAlignment="Left" 
  VerticalAlignment="Top" />

<Path Data="{Binding MyVerticalLines}" Stroke="{Binding MyColor}" 
  StrokeThickness="1" 
  RenderOptions.EdgeMode="Aliased" IsHitTestVisible="False" 
  HorizontalAlignment="Left" VerticalAlignment="Top" />

In your viewmodel, of course, you have the properties MyHorizontalLines and MyVerticalLines as StreamGeometry and MyColor as SolidColorBrush (the desired color of your lines).

And then, you only call the following small method in order to produce all lines on the screen as only one StreamGeometry (one for all horizontal lines and, if needed, one for all vertical lines):

Solution A: 

C#
public static StreamGeometry MyLines (Point StartPoint, bool Horizontal, 
         int LengthOfLines, int NumberOfLines, int LineDistance)
{
    StreamGeometry lines = new StreamGeometry();
    Point toPoint;
    using (StreamGeometryContext strG = lines.Open())
    {
        toPoint = Horizontal ? new Point(StartPoint.X, 
        	StartPoint.Y) : new Point(StartPoint.Y, StartPoint.X);
        strG.BeginFigure(toPoint, false, false);
        for (var i = 0; i < NumberOfLines * 2 - 1; i++)
        {
            if (i % 2 == 1)
                StartPoint = new Point(StartPoint.X, StartPoint.Y + LineDistance);
            else
                StartPoint = new Point(StartPoint.X + 
                	(i % 4 == 0 ? LengthOfLines : -LengthOfLines), StartPoint.Y);
            toPoint = Horizontal ? new Point(StartPoint.X, StartPoint.Y) : 
            	new Point(StartPoint.Y, StartPoint.X);
            strG.LineTo(toPoint, i % 2 == 0, false);
        }
    }
    lines.Freeze();
    return lines;
}

Solution B:

C#
public static StreamGeometry MyLines(Point StartPoint, int LengthOfLines, int NumberOfLines, int LineDistance)
{
    StreamGeometry lines = new StreamGeometry();
    using (StreamGeometryContext ctxt = lines.Open())
    {
        ctxt.BeginFigure(new Point(0, 0), false, false);
        for (var i = 0; i < NumberOfLines; i++)
        {
            ctxt.LineTo(StartPoint, false, false);
            StartPoint = new Point(StartPoint.X + LengthOfLines, StartPoint.Y); 
            ctxt.LineTo(StartPoint, true, false);
            StartPoint = new Point(StartPoint.X - LengthOfLines, StartPoint.Y + LineDistance);
        }
    }
    lines.Freeze();
    return lines;
}  

(Change X and Y for vertical lines.) 

Afterwards, in your ViewModel with the mentioned properties (including the RaisePropertyChanged() in the setter as usual), you can always fill these properties with the updated StreamGeometry of the lines:

C#
MyHorizontalLines = MyLines (new Point(0, 0), true, 600, 10, 15);
MyVerticalLines = MyLines(new Point(0, 0), false, 1000, 50, 50);    

Points of Interest

The magic effect comes from the LineTo-method of the StreamGeometryContext: in its second parameter you can tell this method whether to draw a line or simply move to the next point ("line" in our case) without drawing.

In addition to that, our one or two (frozen) line-constructions as Data of the one or two Path-objects in the WPF/XAML are managed by MVVM really quickly.

History

  • 23.11.2013: Originally posted
  • 25.11.2013: Chart and Solution B added 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect www.schoder.uk
United Kingdom United Kingdom
I am a software architect and electronic musician.

Comments and Discussions

 
QuestionLooks Great! Pin
Carpi_196812-Dec-14 0:47
Carpi_196812-Dec-14 0:47 
AnswerRe: Looks Great! Pin
dietmar paul schoder17-Dec-14 20:21
professionaldietmar paul schoder17-Dec-14 20:21 
GeneralRe: Looks Great! Pin
Carpi_196829-Dec-14 0:06
Carpi_196829-Dec-14 0:06 
GeneralMy vote of 5 Pin
johannesnestler25-Nov-13 4:31
johannesnestler25-Nov-13 4:31 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.