Where to store application settings/state in a MVVM application

.net, c#, mvvm, unit-testing, wpf

Solution

If you weren't using M-V-VM, the solution is simple: you put this data and functionality in your Application derived type. Application.Current then gives you access to it. The problem here, as you're aware, is that Application.Current causes problems when unit testing the ViewModel. That's what needs to be fixed. The first step is to decouple ourselves from a concrete Application instance. Do this by defining an interface and implementing it on your concrete Application type.

public interface IApplication
{
  Uri Address{ get; set; }
  void ConnectTo(Uri address);
}

public class App : Application, IApplication
{
  // code removed for brevity
}

Now the next step is to eliminate the call to Application.Current within the ViewModel by using Inversion of Control or Service Locator.

public class ConnectionViewModel : INotifyPropertyChanged
{
  public ConnectionViewModel(IApplication application)
  {
    //...
  }

  //...
}

All of the "global" functionality is now provided through a mockable service interface, IApplication. You're still left with how to construct the ViewModel with the correct service instance, but it sounds like you're already handling that? If you're looking for a solution there, Onyx (disclaimer, I'm the author) can provide a solution there. Your Application would subscribe to the View.Created event and add itself as a service and the framework would deal with the rest.

Problem

I'm experimenting with MVVM for the first time and really like the separation of responsibilities. Of course any design pattern only solves many problems - not all. So I'm trying to figure out where to store application state and where to store application wide commands. Lets say my application connects to a specific URL. I have a ConnectionWindow and a ConnectionViewModel that support gathering this information from the user and invoking commands to connect to the address. The next time the application starts, I want to reconnect to this same address without prompting the user. My solution so far is to create an ApplicationViewModel that provides a command to connect to a specific address and to save that address to some persistent storage (where it's actually saved is irrelevant for this question). Below is an abbreviated class model. The application view model: ``` public class ApplicationViewModel : INotifyPropertyChanged { public Uri Address{ get; set; } public void ConnectTo( Uri address ) { // Connect to the address // Save the addres in persistent storage for later re-use Address = address; } ... } ``` The connection view model: ``` public class ConnectionViewModel : INotifyPropertyChanged { private ApplicationViewModel _appModel; public ConnectionViewModel( ApplicationViewModel model ) { _appModel = model; } public ICommand ConnectCmd { get { if( _connectCmd == null ) { _connectCmd = new LambdaCommand( p => _appModel.ConnectTo( Address ), p => Address != null ); } return _connectCmd; } } public Uri Address{ get; set; } ... } ``` So the question is this: Is an ApplicationViewModel the right way to handle this? How else might you store application state? EDIT: I'd like to know also how this affects testability. One of the primary reasons for using MVVM is the ability to test the models without a host application. Specifically I'm interested in insight on how centralized app settings affect testability and the ability to mock out the dependent models.

Original source

Related problems