4

I am developing an WPF application in which I have to provide a canvas to the end user. The canvas should have a toolbox containing basic shapes like rectangle , square etc. which he can drag and drop to the canvas. After the user has finished he would click the save button.

The canvas should now be saved into the database and the next time when user goes to retrieve it he should get the canvas in the same state where he left the last time so that he can continue editing. The canvas represents a floor and which there are sections and each section is represented by a basic shape.

Any guidance would in this would be appreciated.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Rachit
  • 136
  • 1
  • 7
  • Have you thought about serializing to the db? – Gayot Fow Jan 07 '14 at 10:27
  • yes serializing to the db would be the last step. the XAML file would have to be serialized and deserialized but where I am stuck is that what approach I take to built the canvas and the toolbox. How user can drag and drop on the surface and how after the editing I can save the file and then again load it back for editing. – Rachit Jan 07 '14 at 11:35
  • 1
    The key here is MVVM. Persist the model, not the view. – Clemens Jan 07 '14 at 12:50
  • @Rachit, the database is meant to deal with an *abstraction* of your canvas. Create a DTO that contains all of the values needed to recreate your canvas from the beginning. If you examine your canvas and tools etc, you will see that it can all be abstracted into simple strings and numbers. Read Sheridan's answer for more info. – Gayot Fow Jan 07 '14 at 13:30

3 Answers3

4

@Rachit, I could be wrong, but you seem to be missing the point here. That point is that you're not supposed to save the UI elements, you're supposed to save the data that is displayed as the UI elements.

You must already have data objects that contain the positions and colours and types of shapes that are on the Canvas... this is what you should be saving, not the actual XAML. Using Serialization, it's a very simple procedure. You can follow the answer in the How to save/restore serializable object to/from file? question.

Now it is possible to save XAML directly, using the XamlWriter.Save Method. Let's assume for a minute that you actually did that... so you now have a saved file containing some XAML. What now? Even if you managed to reload your Canvas in the view model or code behind (which really shouldn't know anything about the UI), then what would you do?

You might have a Canvas in your hand, but you no longer have the data. What if the user wants to move an object? You don't have the data, so you can't. Now if you had saved the data instead, then the Canvas can always be re-rendered at any time. This is (one of the many reasons) why you need to save the data and not the UI controls.

Community
  • 1
  • 1
Sheridan
  • 68,826
  • 24
  • 143
  • 183
  • Fully agree, but of course there is a `XamlReader.Load` method. – Clemens Jan 07 '14 at 14:10
  • Good catch @Clemens, thanks... I must learn to concentrate better. :) – Sheridan Jan 07 '14 at 14:32
  • @Sheridan thanks for your thoughts .. I understood the point .. will try and implement this in a small project and then may ill do the actual implementation... will keep updating the post with my progress .. – Rachit Jan 08 '14 at 04:13
0

If you look at my answer to this question about writing a WPF chess application then you'll see how to create a canvas with various elements using a data driven model. You can then serialize that data out to whatever persistent storage you need using standard C# serialization.

Community
  • 1
  • 1
Mark Feldman
  • 15,731
  • 3
  • 31
  • 58
  • mark thanks for the link to the post however I want the canvas to be dynamic i.e. not fixed like a chessboard. The requirement is that the user can drag and drop to the canvas and then the canvas must be stored and then loaded again .. – Rachit Jan 07 '14 at 11:38
  • if you look at the code I posted then you'll see that actually it is dynamic, it's just a collection of items that can be manipulated and added/removed etc and it's the responsibility of the XAML to decide how it decides to render those items based on their properties. – Mark Feldman Jan 07 '14 at 22:04
0

Save canvas mainImageCanvas located in WPF form:

FileStream fs = File.Open("fileName.xaml", FileMode.Create);
XamlWriter.Save(mainImageCanvas, fs);
fs.Close();

Read saved canvas into mainImageCanvas:

FileStream fs = File.Open("fileName.xaml", FileMode.Open, FileAccess.Read);
Canvas savedCanvas = XamlReader.Load(fs) as Canvas;
fs.Close();

while (savedCanvas.Children.Count > 0)
{
     UIElement uie = savedCanvas.Children[0];
     savedCanvas.Children.Remove(uie);
     mainImageCanvas.Children.Add(uie);
}
Ihor Konovalenko
  • 1,298
  • 2
  • 16
  • 21