Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Save and Load data "the MVVM" way?

I'm currently working on a C# WPF project using some of the Controls provided by Telerik and I'm respecting the MVVM pattern with:

  • a Model containing the data

  • a ViewModel presenting the data to the View

  • a View displaying the data

Of course, some of the Models can be reused and displayed in several Views (in my case, the data can be the content of shapes displayed on different diagrams).

Now I'm starting to design how to save the data. My goal is very simple: when the user leaves the application and comes back, all Views must be identical in terms of content, color, fonts, size, position in space...

Saving a Model covers only the content part. How would you save the display properties like color, fonts, position in space, especially when several Views will rely on the same Model ? Should I use Bindings and move all properties from the View to the Model ? With the risk that the Model complexity will greatly increase ?

Do you have any solution where you keep the UI properties separated from the Model ?

Also is there any best practice on how to save and load data "the MVVM way" ?

Thanks in advance.

like image 403
David MVVM Avatar asked Aug 01 '14 15:08

David MVVM


1 Answers

I save user options like that in the Application Settings. If you're not familiar with them, you can find out the full story on the Using Settings in C# page on MSDN. In short, you can have Application and User Settings and it sounds like you'd want User Settings that are saved per user. UI properties have no place in any model as there is no benefit from storing that kind of information along with model data. You can do this kind of thing with them:

private void LoadSettings(MainWindow window)
{
    Settings.Default.Reload();
    window.WindowStartupLocation = WindowStartupLocation.Manual;
    window.Left = Settings.Default.ApplicationLocation.X;
    window.Top = Settings.Default.ApplicationLocation.Y;
    window.Width = Settings.Default.ApplicationSize.Width;
    window.Height = Settings.Default.ApplicationSize.Height;
    window.WindowState = Settings.Default.IsApplicationMaximised ? WindowState.Maximized : WindowState.Normal;
}

private void SaveSettings(MainWindow window)
{
    Settings.Default.ApplicationLocation = new Point(window.Left, window.Top);
    Settings.Default.ApplicationSize = new Size(window.Width, window.Height);
    Settings.Default.IsApplicationMaximised = window.WindowState == WindowState.Maximized;
    Settings.Default.Save();
}

It might be easier to add some of the properties to a base or main view model, so that you can data bind to them:

public void SaveSettings(string tabName)
{
    Settings.Default.ReleaseTrackSideFormat = StateManager.ReleaseTrackSideFormat;
    Settings.Default.ReleaseLabelCopyFormat = StateManager.ReleaseLabelCopyFormat;
    Settings.Default.ReleaseExportDestination = StateManager.ReleaseExportDestination;
    Settings.Default.ReleaseSearchOptions = new SerializableReleaseSearchOptions(ReleaseSearchOptions);
    ...
    Settings.Default.Save();
}

public void LoadSettings()
{
    Settings.Default.Reload();
    StateManager.ReleaseTrackSideFormat = Settings.Default.ReleaseTrackSideFormat;
    StateManager.ReleaseLabelCopyFormat = Settings.Default.ReleaseLabelCopyFormat;
    StateManager.ReleaseExportDestination = Settings.Default.ReleaseExportDestination;
    ReleaseSearchOptions = new ReleaseSearchOptions(Settings.Default.ReleaseSearchOptions);
    ReleaseExportSearchOptions = new ReleaseExportSearchOptions(Settings.Default.ReleaseExportSearchOptions);
    ...
}

UPDATE >>>

You're quite right... you wouldn't want to store your model data in this way. This is for UI related user preferences. If you're also asking how to save your model data, then the quick answer is that I'd store mine in a database, but that's up to you. You could just as easily store it in a file on your computer. It all depends on scale, convenience, speed, access to resources, etc., so it's not really a question that is suitable in scope for this website.

However, there are plenty of tutorials online showing different ways of saving data step by step. To answer that question, I recommend that you follow some of them.

What I can tell you is that it is customary to put your data access code into a class in a separate project (or folder for a small project). This class is then often referenced only in a parent, or base view model property and all child view models would access their data via this... perhaps something like this:

protected IModel Model
{
    get { return model; }
}

Then the child view models would use it like this:

SomeCollectionProperty = Model.GetSomeData();

Or:

Model.SaveSomeData(SomeCollectionProperty);

To clarify a little further, it makes no difference at this stage what implementation you have for this Model class. The view models don't care whether it is using a database, or a plain old text file as long as it implements the GetSomeData and SaveSomeData methods. Therefore, it is good to use an interface here, especially if you ever want to do any testing of the view models.

Finally, you might want to take a look at my answer to the Project structure for MVVM in WPF question to get a better idea about that too.

like image 173
Sheridan Avatar answered Oct 04 '22 04:10

Sheridan