Reputation: 1362
In my WPF application's ViewModel
has few properties, observableCollections etc.
How can I save their current state as file when app is closing or save clicked
Should I use [Serializable]
implementation?
What is the best approach?
public class CustomerViewModel
{
private Customer obj = new Customer();
public string TxtCustomerName
{
get { return obj.CustomerName; }
set { obj.CustomerName = value; }
}
public string TxtAmount
{
get { return Convert.ToString(obj.Amount) ; }
set { obj.Amount = Convert.ToDouble(value); }
}
}
Upvotes: 1
Views: 1993
Reputation: 25623
There isn't a standard practice for persisting MVVM state. You just need to pick a format, just like you would for any other serialization problem. I personally am a fan of using Xaml, as it's human readable and can represent most of the types that you might be using in a WPF application.
Example code, included in a base class for your view models:
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private static string RootStoragePath =>
Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
"YourApplication",
"ViewState");
protected string StateFilePath =>
Path.Combine(RootStoragePath, this.GetType().Name + ".xaml");
public void Save()
{
var fileName = StateFilePath;
var directoryName = Path.GetDirectoryName(fileName);
if (directoryName != null && !Directory.Exists(directoryName))
Directory.CreateDirectory(directoryName);
XamlServices.Save(fileName, this);
}
public void Load()
{
var fileName = StateFilePath;
if (File.Exists(fileName))
{
using (var file = File.OpenRead(fileName))
using (var reader = new XamlXmlReader(file))
{
var writer = new XamlObjectWriter(
reader.SchemaContext,
new XamlObjectWriterSettings { RootObjectInstance = this });
using (writer)
{
XamlServices.Transform(reader, writer);
}
}
}
}
protected virtual void OnPropertyChanged(string propertyName)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
The saved state would look something like this:
<CustomerViewModel TxtAmount="3.5"
TxtCustomerName="Mike Strobel"
xmlns="clr-namespace:WpfTest;assembly=WpfTest" />
Note that this is a minimal example. Ideally, your error handling on the storage operations would be more robust. Be sure to change RootStoragePath
to be unique to your application.
Upvotes: 1
Reputation: 169400
What the best approach is depends on your requirements. You could for example serialize your class using the built-in DataContractJsonSerializer
class without modifying the class at all:
CustomerViewModel vm = new CustomerViewModel();
//...
using (MemoryStream ms = new MemoryStream())
{
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(CustomerViewModel));
ser.WriteObject(ms, vm);
File.WriteAllText("save.txt", Encoding.UTF8.GetString(ms.ToArray()));
}
You will need to add a reference to System.Runtime.Serialization.dll
. Please refer to the following blog post for more information: https://www.bytefish.de/blog/enum_datacontractjsonserializer/.
A popular high-performance third-party JSON serializer is othwerwise Json.NET: https://www.newtonsoft.com/json. And there are plenty of other solutions that use various formats, whether they are text-based or binary. In complex cases you may have to write your own custom serializer.
Upvotes: 2