Doodle Pad

Doodle Pad uses the InkPresenter feature of Silverlight featuring Draw Width and Colour, plus Open and Save support.

www.cespage.com/silverlight/sl4tut23.html

Step 1

Start Microsoft Visual Web Developer 2010 Express, then Select File then New Project... Select "Visual Basic" then "Silverlight Application" from Templates, select a Location if you wish, then enter a name for the Project and then click OK, see below:

New Project

Step 2

New Silverlight Application window should appear, uncheck the box "Host the Silverlight Application in a new Web site" and then select the required Silverlight Version, see below:

New Silverlight Application

Step 3

A Blank Page named MainPage.xaml should then appear, see below:

MainPage.xaml

Step 4

Select Project then Add Reference... The "Add Reference" window should appear, select "System.XML.Linq" from the ".NET" List, see below:

Add System.XML.Linq Reference

Step 5

Add the Reference to "System.XML.Linq" by Clicking on OK
Then from the All Silverlight Controls section in the Toolbox select the Canvas control:

Canvas Control

Step 6

Draw a Canvas on the Page then in the XAML Pane above the "</Grid>" then change the "Canvas1" line to the following:

<Canvas Height="65" Width="400" VerticalAlignment="Top" HorizontalAlignment="Left" Name="Toolbar"></Canvas>

See below:

MainPage with Toolbar Canvas

Step 7

Then from the Common Silverlight Controls section in the Toolbox select the Button control:

Button Control

Step 8

Draw Three Buttons on the "Toolbar" Canvas by dragging the Buttons from the Toolbox onto the Canvas then in the XAML Pane inbetween the "<Canvas>" and "</Canvas>" tags change the "<Button>" lines to the following:

<Button Canvas.Left="6" Canvas.Top="6" Height="23" Width="75" Name="New" Content="New"/>
<Button Canvas.Left="87" Canvas.Top="6" Height="23" Width="75" Name="Open" Content="Open..."/>
<Button Canvas.Left="168" Canvas.Top="6" Height="23" Width="75" Name="Save" Content="Save..."/> 

See below:

MainPage with Canvas and Buttons

Step 9

While still in the XAML Pane, below the last "<Button>" tag and above the "</Canvas>" type the following ComboBox XAML:

<ComboBox Canvas.Left="6" Canvas.Top="35" Height="23" Width="156" Name="Size">
  <ComboBoxItem Tag="1">
    <Rectangle Height="1" Width="150" Fill="Black"/>
  </ComboBoxItem>
  <ComboBoxItem Tag="2">
    <Rectangle Height="2" Width="150" Fill="Black"/>
  </ComboBoxItem>
  <ComboBoxItem Tag="5" IsSelected="True">
    <Rectangle Height="5" Width="150" Fill="Black"/>
  </ComboBoxItem>
  <ComboBoxItem Tag="10">
    <Rectangle Height="10" Width="150" Fill="Black"/>
  </ComboBoxItem>
  <ComboBoxItem Tag="15">
    <Rectangle Height="15" Width="150" Fill="Black"/>
  </ComboBoxItem>
  <ComboBoxItem Tag="20">
    <Rectangle Height="20" Width="150" Fill="Black"/>
  </ComboBoxItem>
  <ComboBoxItem Tag="25">
    <Rectangle Height="25" Width="150" Fill="Black"/>
  </ComboBoxItem>
  <ComboBoxItem Tag="30">
    <Rectangle Height="30" Width="150" Fill="Black"/>
  </ComboBoxItem>
  <ComboBoxItem Tag="40">
    <Rectangle Height="40" Width="150" Fill="Black"/>
  </ComboBoxItem>
  <ComboBoxItem Tag="50">
    <Rectangle Height="50" Width="150" Fill="Black"/>
  </ComboBoxItem>
</ComboBox>

<ComboBox Canvas.Left="168" Canvas.Top="35" Height="23" Width="75" Name="Colour">
  <ComboBoxItem Tag="FF000000" IsSelected="True">
    <Rectangle Width="25" Height="14" Fill="Black"/>
  </ComboBoxItem>
  <ComboBoxItem Tag="FF808080">
    <Rectangle Width="25" Height="14" Fill="Gray"/>
  </ComboBoxItem>
  <ComboBoxItem Tag="FFFF0000">
    <Rectangle Width="25" Height="14" Fill="Red"/>
  </ComboBoxItem>
  <ComboBoxItem Tag="FFFFA500">
    <Rectangle Width="25" Height="14" Fill="Orange"/>
  </ComboBoxItem>
  <ComboBoxItem Tag="FFFFFF00">
    <Rectangle Width="25" Height="14" Fill="Yellow"/>
  </ComboBoxItem>
  <ComboBoxItem Tag="FF008000">
    <Rectangle Width="25" Height="14" Fill="Green"/>
  </ComboBoxItem>
  <ComboBoxItem Tag="FF00FFFF">
    <Rectangle Width="25" Height="14" Fill="Cyan"/>
  </ComboBoxItem>
  <ComboBoxItem Tag="FF0000FF">
    <Rectangle Width="25" Height="14" Fill="Blue"/>
  </ComboBoxItem>
  <ComboBoxItem Tag="FFFF00FF">
    <Rectangle Width="25" Height="14" Fill="Magenta"/>
  </ComboBoxItem>
  <ComboBoxItem Tag="FF800080">
    <Rectangle Width="25" Height="14" Fill="Purple"/>
  </ComboBoxItem>
</ComboBox>

See below:

MainPage with Toolbar Buttons and ComboBoxes

Step 10

Again while still in the XAML Pane below the "</Canvas>" and above the "</Grid>" Tag, type the following InkPresenter XAML:

<InkPresenter Height="236" Width="400" Margin="0,64,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" 
Background="White" Name="Surface"/>

See below:

MainPage with Toolbar Buttons, ComboBoxes and InkPresenter

Step 11

Right Click on the Page or the entry for "MainPage.xaml" in Solution Explorer and choose the "View Code" option. In the Code View above the "Partial Public Class MainPage" line type the following:

Imports System.Globalization.NumberStyles
Imports System.Xml.Linq

See Below:

MainPage.xaml Imports

Step 12

While still in the Code View for MainPage.xaml, below the "Inherits UserControl" line type the following:

Public drawStroke As Stroke
Public drawColour As Color = Colors.Black
Public drawSize As Size = New Size With {.Height = 5, .Width = 5}

See Below:

MainPage.xaml Declarations

Step 13

While still in the Code View for MainPage.xaml, below the "End Sub" for "Public Sub New()" Constructor type the following Sub:

Private Sub Read(ByRef Stream As IO.Stream, ByRef Strokes As StrokeCollection)
  Dim _stroke As New Stroke
  Dim _drawAttr As New DrawingAttributes
  Dim _doc As XDocument = XDocument.Load(Stream)
  For Each Element As XElement In _doc.Root.<Stroke>
    For Each Item As XElement In Element.<Stroke.DrawingAttributes>.<DrawingAttributes>
      _drawAttr = New DrawingAttributes With {
      .Color = Color.FromArgb(
        Byte.Parse(Item.@Color.Substring(1, 2), HexNumber),
        Byte.Parse(Item.@Color.Substring(3, 2), HexNumber),
        Byte.Parse(Item.@Color.Substring(5, 2), HexNumber),
        Byte.Parse(Item.@Color.Substring(7, 2), HexNumber)),
      .Width = Item.@Width,
      .Height = Item.@Height}
    Next
    For Each Item As XElement In Element.<Stroke.StylusPoints>
      _stroke = New Stroke
      _stroke.DrawingAttributes = _drawAttr
      For Each Point As XElement In Item.<StylusPoint>
        _stroke.StylusPoints.Add(New StylusPoint With {
          .X = Point.@X,
          .Y = Point.@Y})
      Next
      Strokes.Add(_stroke)
    Next
  Next
End Sub

See Below:

MainPage Read Sub

Step 14

While still in the Code View for MainPage.xaml, below the "End Sub" for "Private Sub Read(...)" type the following Function:

Private Function Write(ByRef Strokes As StrokeCollection) As String
  Dim _doc As XDocument =
    <?xml version="1.0" encoding="utf-8"?>
    <StrokeCollection>
      <%= From Item As Stroke In Strokes Select
        <Stroke>
          <Stroke.DrawingAttributes>
            <DrawingAttributes
              Color=<%= Item.DrawingAttributes.Color %>
              Width=<%= Item.DrawingAttributes.Width %>
              Height=<%= Item.DrawingAttributes.Height %>
            />
          </Stroke.DrawingAttributes>
          <Stroke.StylusPoints>
            <%= From Point As StylusPoint In Item.StylusPoints Select
              <StylusPoint
              X=<%= Point.X %>
              Y=<%= Point.Y %>
              />
            %>
          </Stroke.StylusPoints>
        </Stroke>
      %>
    </StrokeCollection>
  Return _doc.ToString
End Function

See Below:

MainPage Write Function

Step 15

Return to the Designer View by selecting the "MainPage.xaml" Tab, or Right Click on the Page or the Entry for "MainPage.xaml" in Solution Explorer and choose the "View Designer" option.
Click on the "Surface" InkPresenter, then goto the Properties box and Click on the "Events" Tab, see below:

Surface InkPresenter Property Events

Double Click on the "MouseLeftButtonDown" Event and type in the Surface_MouseLeftButtonDown Sub:

drawStroke = New Stroke
drawStroke.DrawingAttributes.Color = drawColour
drawStroke.DrawingAttributes.Width = drawSize.Width
drawStroke.DrawingAttributes.Height = drawSize.Height
drawStroke.StylusPoints.Add(New StylusPoint With {
  .X = e.GetPosition(Surface).X,
  .Y = e.GetPosition(Surface).Y})
Surface.Strokes.Add(drawStroke)

See Below:

Surface InkPresenter MouseLeftButtonDown Event

Step 16

Return to the Designer View by selecting the "MainPage.xaml" Tab, or Right Click on the Page or the Entry for "MainPage.xaml" in Solution Explorer and choose the "View Designer" option.
Click on the "Surface" InkPresenter, then goto the Properties box and Click on the "Events" Tab, see below:

Surface InkPresenter Property Events

Double Click on the "MouseLeftButtonUp" Event and type in the Surface_MouseLeftButtonUp Sub:

drawStroke = Nothing

See Below:

Surface InkPresenter MouseLeftButtonUp Event

Step 17

Return to the Designer View by selecting the "MainPage.xaml" Tab, or Right Click on the Page or the Entry for "MainPage.xaml" in Solution Explorer and choose the "View Designer" option.
Click on the "Surface" InkPresenter, then goto the Properties box and Click on the "Events" Tab, see below:

Surface InkPresenter Property Events

Double Click on the "MouseMove" Event and type in the Surface_MouseMove Sub:

If Not drawStroke Is Nothing Then
  drawStroke.StylusPoints.Add(New StylusPoint With {
    .X = e.GetPosition(Surface).X,
    .Y = e.GetPosition(Surface).Y})
End If

See Below:

Surface InkPresenter MouseMove Event

Step 18

Return to the Designer View by selecting the "MainPage.xaml" Tab, or Right Click on the Page or the Entry for "MainPage.xaml" in Solution Explorer and choose the "View Designer" option.
Double Click on the "New" Button and type in the New_Click Sub:

If MessageBox.Show("Start a New Doodle?", "Doodle Pad",
    MessageBoxButton.OKCancel) = MessageBoxResult.OK Then
  Surface.Strokes.Clear()
End If

See Below:

New Button Click Event

Step 19

Return to the Designer View by selecting the "MainPage.xaml" Tab, or Right Click on the Page or the Entry for "MainPage.xaml" in Solution Explorer and choose the "View Designer" option.
Double Click on the "Open..." Button and type in the Open_Click Sub:

Dim OpenDialog As New OpenFileDialog
OpenDialog.Filter = "Drawing (*.ipr)|*.ipr"
If OpenDialog.ShowDialog Then
  Try
    If OpenDialog.File.Exists Then
      Surface.Strokes.Clear()
      Read(OpenDialog.File.OpenRead, Surface.Strokes)
    End If
  Catch ex As Exception
    ' Ignore Errors
  End Try
End If

See Below:

Open Button Click Event

Step 20

Return to the Designer View by selecting the "MainPage.xaml" Tab, or Right Click on the Page or the Entry for "MainPage.xaml" in Solution Explorer and choose the "View Designer" option.
Double Click on the "Save..." Button Control and type in the Save_Click Sub:

Dim SaveDialog As New SaveFileDialog
SaveDialog.Filter = "Drawing (*.ipr)|*.ipr"
If SaveDialog.ShowDialog Then
  Try
    Using FileStream As IO.StreamWriter =
        New IO.StreamWriter(SaveDialog.OpenFile)
      FileStream.Write(Write(Surface.Strokes))
    End Using
  Catch ex As Exception
    ' Ignore Errors
  End Try
End If

See Below:

Save Button Click Event

Step 21

Return to the Designer View, by selecting the "MainPage.xaml" Tab, or Right Click on the Page or the Entry for "MainPage.xaml" in Solution Explorer and choose the "View Designer" option.
Double Click on the Large ComboBox (Size) and type in the Size_SelectionChanged Sub:

Dim _drawWidth As Double = Double.Parse(TryCast(Size.SelectedItem, ComboBoxItem).Tag)
drawSize = New Size With {.Height = _drawWidth, .Width = _drawWidth}

See Below:

Size ComboBox SelectionChanged Event

Step 22

Return to the Designer View, by selecting the "MainPage.xaml" Tab, or Right Click on the Page or the Entry for "MainPage.xaml" in Solution Explorer and choose the "View Designer" option.
Double Click on the Smaller ComboBox (Colour) and type in the Colour_SelectionChanged Sub:

Dim _colour As String = CType(Colour.SelectedItem, ComboBoxItem).Tag
drawColour = Color.FromArgb(
  Byte.Parse(_colour.Substring(0, 2), HexNumber),
  Byte.Parse(_colour.Substring(2, 2), HexNumber),
  Byte.Parse(_colour.Substring(4, 2), HexNumber),
  Byte.Parse(_colour.Substring(6, 2), HexNumber)))

See Below:

Colour ComboBox SelectionChanged Event

Step 23

Save the Project as you have now finished the Silverlight application. Select Debug then Start Debugging or click on Start Debugging:

Start Debugging

After you do, the following will appear in a new Web Browser window:

Application Running

Step 24

Click on the "Colour" ComboBox to change the Draw Colour, the Draw Width can be changed with the first ComboBox, then click the Left Mouse Button and move the Mouse to Draw, which then can be Saved, see below:

Doodle Pad

Step 25

Close the Application and Browser window by clicking on the Close Button Close on the top right of the Application Window and Web Browser to Stop the application.

This was a simple Doodle Pad example, using the InkPresenter and LINQ to Save the "strokes" used to draw with - Saved into XML, which can then be Opened later. Try adding more features such as more Draw Sizes and Colours - make it your own!