RSS 2.0
# Tuesday, May 22, 2007

Source code for this segment is available at http://www.cavinconsulting.com/Code/Scribble4.zip.

After our first few segments concentrating on framework, it's time to attach some actions to our commands. We have a decision to make. Do we support multiple open scribble documents or do we only allow a single item. For now, let's stick with only a single document. We can add multiple document support later.

Let's start with Save. We'll use the built-in support from the InkCanvas to load and save the InkCanvas' strokes collection. I know Jean-Paul Boodhoo will lie awake at night due to the lack of separation between presentation and data. Should a windows control rerally be the keeper of the document data? I have a feeling we'll revisit this when we want to add multiple views on the same stroke collection. Of course, we'll see.

Here's the code I wrote corresponding to the OnFileSaveAs:

private string _filename = string.Empty;
public void OnFileSaveAs(object sender, RoutedEventArgs e)
{
    SaveAs();
}
private bool SaveAs()
{
    SaveFileDialog saveDialog = new SaveFileDialog();
    saveDialog.DefaultExt = ".isf";
    saveDialog.AddExtension = true;
    saveDialog.Title = "Save Ink";
    saveDialog.OverwritePrompt = true;
    saveDialog.ValidateNames = true;
    saveDialog.CheckPathExists = true;
    saveDialog.CreatePrompt = false;
    saveDialog.Filter = "Ink Files (*.isf)|*.isf|All Files (*.*)|*.*";

    bool? saveResult = saveDialog.ShowDialog(this);
    if (saveResult.HasValue && saveResult.Value == true)
    {
        _filename = saveDialog.FileName;
        return SaveInk();
    }
    return false;
}
private bool SaveInk()
{
    try
    {
        using (FileStream writer = new FileStream(_filename, FileMode.OpenOrCreate))
        {
            inkCanvas.Strokes.Save(writer);
            writer.Close();
        }
    }
    catch (Exception ex)
    {
        Trace.Fail(ex.Message, ex.StackTrace);
        return false;
    }
    return true;
}

From here, it's easy to add the functionality for OnFileSave:

public void OnFileSave(object sender, RoutedEventArgs e)
{
    Save();
}
private bool Save()
{
    if (String.IsNullOrEmpty(_filename))
    {
        return SaveAs();
    }
    else
    {
        return SaveInk();
    }
}

Now, let's add OnFileNew:

private bool _dirty = false;
public void OnFileNew(object sender, RoutedEventArgs e)
{
    ClearCanvas();
}
public void OnStrokeCollected(object sender, InkCanvasStrokeCollectedEventArgs e)
{
    _dirty = true;
}
private bool ClearCanvas()
{
    bool eraseAnyway = true;
    if (_dirty)
    {
        // Prompt for save
        MessageBoxResult result = MessageBox.Show(
            "Do you want to save changes?",
            "Modifications Detected",
            MessageBoxButton.YesNoCancel);

        if ((result == MessageBoxResult.Cancel) ||
            ((result == MessageBoxResult.Yes) && (!Save())))
        {
            eraseAnyway = false;
        }
    }
    if (eraseAnyway)
    {
        inkCanvas.Strokes.Clear();
        _dirty = false;
        return true;
    }
    return false;
}

Change the InkCanvas declaration in xaml to this:

<InkCanvas Name="inkCanvas" Grid.Row="2" StrokeCollected="OnStrokeCollected" />

And finally, OnFileOpen:

public void OnFileOpen(object sender, RoutedEventArgs e)
{
    if (ClearCanvas())
    {
        OpenFileDialog openDialog = new OpenFileDialog();
        openDialog.DefaultExt = ".isf";
        openDialog.AddExtension = true;
        openDialog.Title = "Load Ink";
        openDialog.CheckFileExists = true;
        openDialog.Filter = "Ink Files (*.isf)|*.isf|All Files (*.*)|*.*";

        bool? openResult = openDialog.ShowDialog(this);
        if (openResult.HasValue && openResult.Value == true)
        {
            _filename = openDialog.FileName;
            LoadInk();
        }
    }
}
private bool LoadInk()
{
    try
    {
        using (FileStream reader = new FileStream(_filename, FileMode.Open))
        {
            inkCanvas.Strokes = new StrokeCollection(reader);
            reader.Close();
        }
    }
    catch (Exception ex)
    {
        inkCanvas.Strokes.Clear();
        _dirty = false;
        Trace.Fail(ex.Message, ex.StackTrace);
        return false;
    }
    return true;
}

Pretty straight forward. We're just using the built-in serialization methods of the InkCanvas to load and save the strokes stored in the canvas. We also attach an event handler to the Canvas' StrokeCollected event to set the dirty bit (to prompt the user to save if there are changes).

Of course, there are some validations we ought to add, and Brad Abrams will get really mad when he sees the catch (Exception ex) line since you're not supposed to catch System.Exception. But, it loads and save the canvas so we can take comfort in our ability to create inky masterpieces and be able to retrieve them sometime in the future.

Tuesday, May 22, 2007 2:32:26 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0] -
WPF
Comments are closed.
Navigation
Categories
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2010
Cavin Consulting
Sign In
Statistics
Total Posts: 28
This Year: 0
This Month: 0
This Week: 0
Comments: 4
All Content © 2010, Cavin Consulting
DasBlog theme 'Business' created by Christoph De Baene (delarou)