Question

I have a InkPresenter and add Strokes onto it using InkPresenter.Strokes.Add(Stroke). After that, I want to serialize/save the InkPresenter to the file system or database. Ink.Strokes is type of StrokeCollection and MSDN says that there is the Save(Stream) method for this issue. On windows Phone, there seems to be a lack of this functionality.

Maybe, there's another way to serialize and deserialize an InkPresenter control.

Was it helpful?

Solution

As in Jeff's post, on windows phone the only way to do this is have your own type that stores the strokes and then you can save that to isolated storage then you can load it and basically "replay" the strokes. Or you can just save the StrokeCollection as a formatted string.

Basically, each stroke consists of a color and a bunch of points. This way you can for example store the StrokeCollection as a collection of strings in a simple format like this:

Color|X1,Y1$X2,Y2$X3,Y3 -- Represents a single stroke

With that you can write a function that accepts a stroke collection and a file name and it can save your StrokeCollection

public void SaveStrokes(string filename, StrokeCollection strokeCollection) {
  var isf = IsolatedStorageFile.GetUserStoreForApplication();
  var stream = isf.CreateFile(filename);

  using (var writer = new StreamWriter(stream)) {
    foreach (var stroke in strokeCollection) {
      writer.WriteLine(String.Format("{0}|{1}", 
          stroke.DrawingAttributes.Color.ToString(), 
          String.Join("$", stroke.StylusPoints.Select(p => String.Format("{0},{1}", p.X, p.Y)))));
    }
  }
}

Now you only need a function that loads this and displays your stroke. A loading function to load a stroke collection saved by the above method could be something like this:

public void LoadStrokes(string filename, InkPresenter inkPresenter) {
  var isf = IsolatedStorageFile.GetUserStoreForApplication();
  var stream = isf.OpenFile(filename, FileMode.Open);

  using (var reader = new StreamReader(stream)) {
    var strokes = reader.ReadToEnd().Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
    foreach (var stroke in strokes) {
      var strokeParams = stroke.Split('|');

      var myStroke = new Stroke();
      myStroke.DrawingAttributes.Color = HexToColor(strokeParams[0].ToString());

      var pointList = strokeParams[1].Split('$');
      foreach (var pointPair in pointList) {
        var pointPairList = pointPair.Split(',');
        var x = Convert.ToDouble(pointPairList[0]);
        var y = Convert.ToDouble(pointPairList[1]);

        myStroke.StylusPoints.Add(new StylusPoint(x, y));
      }

      inkPresenter.Strokes.Add(myStroke);
    }
  }
}

Since colors are going to be saved in Hex format you'll need a function to convert that to a color enum:

public System.Windows.Media.Color HexToColor(string hexString) {
  string cleanString = hexString.Replace("-", String.Empty).Substring(1);

  var bytes = Enumerable.Range(0, cleanString.Length)
                 .Where(x => x % 2 == 0)
                 .Select(x => Convert.ToByte(cleanString.Substring(x, 2), 16))
                 .ToArray();

  return System.Windows.Media.Color.FromArgb(bytes[0], bytes[1], bytes[2], bytes[3]);
}

Now you can simply call this to save the strokes

SaveStrokes("filename", myInkPresenter.StrokeCollection);

And call it like this to redraw the saved strokes

LoadStrokes("filename", myInkPresenter);

OTHER TIPS

The answer seems to be no. :-/

Jeff Wilcox suggests that you create an object that you can serialize, store and then restore from.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top