How or where to store and load the data models?

Topics: Prism v4 - WPF 4
May 16, 2012 at 9:08 PM
Edited May 16, 2012 at 9:13 PM

In my project I have created classes that store the data for my project. I would imagine that some data models are inherently singleton type and some data models are instance based. I'm wondering what should be responsible for loading the data into these class objects and what is responsible for storing it? The models have the capability of loading the data from disk, but something has to manage the current instance(s) of the data....

For example, let's consider visual studio, or a similar type application. Visual studio has the capability of having a "Solution" which contains projects, files and data. Now, imagine, if there were a SolutionModule which contained all the logic for working with solutions. It would expose views for SolutionExplorer, SolutionNavigator, and the like. If this application didn't have the SolutionModule perhaps it would still be able to open and edit single code files, but would have no concept of a solution project. We also voluntarily impose the restriction that only one solution can be open at any time.

Now, it is clear there would need to be a SolutionExplorerViewModel and a SolutionNavigatorViewModel, each of these views depend on the instance of the Solution class. But, where exactly do they get that instance? Where is it stored?

Do we use dependency injection of the data model itself? I would not think so, because then the data model would need to be registered (I assume in the SolutionModule if using unity) as a Singleton, but then where would the logic be stored to implement commands for Loading, Saving, or Closing a solution?

I would think that perhaps a SolutionController, or SolutionService needs to be implemented. In the Prism examples they have both services and controllers. Why the distinction? What's the difference between a "service" and a "controller"? Right now, my assumption is I would need to implement a SolutionController that holds a reference to the current solution data module, and has methods or perhaps commands to Load, Open, Save a solution.

You know.. that brings up another good question. This application also has a main menu. Just like visual studio, it has options in the menu that interact with the current solution (open, save). Would it be best for this proposed SolutionController to implement actual Commands that are passed to the MenuService? Or would it be best for the SolutionModule.Initialize method to take care of setting up the commands for interacting with SolutionController?

I again, think it would make sense for the SolutionController to create its own commands and interact with the MenuService... Is it then, that the SolutionModule.Initiliaze would create and register an instance of the ISolutionController interface as a SolutionController, which then would during construction invoke the IMenuService to add its commands to the appropriate Menu?

Let me know if I'm thinking on the right track.. there's a lot of talk about creating ViewModels for Views or Views for ViewModels, etc. I'm a bit more confused how where, how, and when to interact with the vast amount of data behind my application. (none of which is database oriented).

Thanks,

 

Developer
May 17, 2012 at 9:27 PM

Hi,

First of all take into account that the implementation details of your application will depend mostly on your personal preferences and the requirements of your scenario.

Based on my understanding you could benefit from implementing a repository that will mediate between the domain and data mapping layers you could have, acting like an in-memory domain object collection. In other words the repository will encapsulate the set of objects persisted in a data store and the operations performed over them.

You could find more information about this in the following resources:

Also you could benefit from the use of shared services to access this repository from across your different modules without them knowing its specific implementation. Then your view models could interact with your repository and update its corresponding values.

Take into account that the Controller pattern allows you to separate the responsibility of creating and displaying views into a controller class. On the other hand Services are components that encapsulate non-UI related functionality, such as logging, exception management, and data access. These can be defined by the application or within a module. Usually Services are registered with the dependency injection container so that they can be located or constructed as required and used by other components that depend on them.

Also, I believe you could check the Stock Trader RI application as a reference that illustrates a common baseline architecture. There you could also find different approaches on how commanding can be used inside Composite Applications.

Additionally I believe you could find the following thread interesting:

I hope you find this useful,

Agustin Adami
http://blogs.southworks.net/aadami

May 18, 2012 at 3:44 PM
Edited May 18, 2012 at 3:50 PM

I do not think the Repository pattern helps me. I read about it and it seems overly complicated for what I need. I don't need complex querying logic of databases, etc.

Like I said, all I need is the ability to add logic including opening and saving a project and getting the data from within it. The projects are XML based files that would get loaded into an object-oriented data model. 

Please give me a simple example. I need some basic commands for opening from file, saving to file. Then that instance of the project needs to be able to be accessed from within the same Module's  ViewModels. This sounds simple, and I need a simple solution.

Suggestions?

Developer
May 18, 2012 at 7:18 PM
Edited May 18, 2012 at 7:19 PM

Hi,

In my opinion you could define this logic in a shared service. There you can define your custom implementation to retrieve and update your data models.

By using a dependency injection container, you could resolve this custom service implementation through a common Interface, this way you should be able to consume this information for example in your different view models in a different module.

An example of this can be found in the StockTrader RI, particularly in the MarketFeedService.cs and MarketHistoryService.cs, which exposes the data obtained from parsing two XML files. This services are registered as singletons in the container trough a common interface (IMarketFeedService and IMarketHistoryService) so they can be consumed by other modules through them.

Regards,

Agustin Adami
http://blogs.southworks.net/aadami

May 21, 2012 at 8:59 PM
Edited May 21, 2012 at 8:59 PM

Thanks for your help so far. I read the book front to back and looked over the examples but I still wasn't clear about the data models and some of the specifics of implementing my application using Prism/MVVM. This helps a lot but I could still use a little more guidance. Let me make an effort to be more exact about what I'm trying to accomplish. I just want to make sure I start off on the right foot, so that I can use these approaches for the rest of my future modules.

  1. I choose to use unity, and I've divided my application up into several modules. Each module has a Module class that implements IModule. The module I'm working on is my "ProjectModule" (Or at least that's what I'm calling it here for simplicity)
  2. The application's project includes the following: List of locations, List of times, list of associated data files (for given time, place).
  3. The application's projects are stored as XML. Objects representing the different classes are created from the XML file when it is loaded.
  4. There will be three views for this module. A view of the list of locations, list of times, and a view of data files in the project.
  5. There will be commands in the MainMenu (if it exists) that allow the user to view each of these three views (similar to solution explorer). I've implemented a MainMenuService in a separate module that has commands for adding MenuItems.
  6. The three views should not be displayed when no project is open, and should be displayed by default when a project is opened.

So.. would this be about the right idea?

  1. ProjectModule.Initialize method would register the Services and Controllers for the module?
  2. ProjectController would create the 3 views and have commands to switch to and display each one. The project controller could find the IMenuService if it exists and add a command to the MainMenu? It would subscribe to events from the ProjectService to handle displaying views.
  3. The ProjectService could keep the current instance of the Project and allow other Modules to retrieve it, close it, open etc. The Project service may have events that it publishes when such things happen.

Here's where I'm confused or unsure of the details.

  1. What exactly is normal to do in the Module.Initialize method? The StockTrader example is very poor  because it uses a custom attribute and does not use the initialize method. I would like to do my work in the Module initialize instead of a custom attribute. However, I do not know if I should create the 3 views in Initialize and add them to the region, or create the Controller and let it create the views and add them to their regions. Should the module's initialize method register the ProjectService as well?
  2. Should the controller implement the commands for opening, saving, and closing a project? Does it add the commands to the IMainMenuService? The logic for saving and opening projects, wouldn't that be in the IProjectService? So, does the controller implement these commands and call into the ProjectService to accomplish them?

There's one more concern of mine, and I haven't understood this from the book either.

I need to be able to detect if data is added to the project to make sure the views update. I understand that this should work through Data Bindings, IPropertyChanged, and ICollectionChanged. Here's my questions..

  1. Does the ListCollectionView class automatically synchronize / databind? If so, how does it work? The constructor takes an IList and does not require a ObservableCollection<T>, or a ICollectionChanged. Do views automatically update when the underlying data changes?
  2. For all of my project data,  I cannot implement ICollectionChanged or ObservableCollection<T> because they do not exist for one of the target platforms in which I'm using my code. (The library for these classes is shared with the CompactFramework 3.5). How would I ensure that my Views automatically update when the data changes? I could implement my own version of ObservableCollection which has events when the collection changes. However, I would need a way to link this to the ViewModels and then through that the Views.
Developer
May 22, 2012 at 9:54 PM

Hi,

In my opinion the architecture you described, seems to be like a valid approach for this scenario.

Regarding your first concern, take into account that in the Module.Initialize method, you can implement whatever logic is required to initialize and integrate the module's functionality with the application, that is to say registering views, registering additional services or extending the application's functionality.

Therefore it wouldn't be wrong if you want to register views in a region when the modules initializes. On the other hand if showing your views will depend on a particular event like when your project is opened, then creating a Controller, which for example would subscribe to a loosely coupled event to handle the initialization and construction of the views, sounds like a logical choice. Also it seems fine to register your ProjectService in this method.

Regarding where to implement the commands for opening, saving, and closing a project, I believe this will depend mostly on your personal preferences and who will be consuming these commands. As a possible  example you could check the WatchListService in the StockTrader RI which consumes the marketFeedService, and based on this service exposes the commands that are consumed by the view models.

About the ListCollectionView class you mentioned, as far as I know the corresponding view will be automatically updated if the source collection implements the INotifyCollectionChanged interface, then changes raised by the CollectionChanged event will be propagated to the view. Hence, using a collection that implements this interface like the ObservableCollection class will be required to automatically synchronize with the view.

You could find more information about this in the following MSDN article:

Finally, as far as I know currently Prism does not provide support or guidance for CompactFramework 3.5. As you can see in the source code Prism provides a version of its library for WPF / Silverlight and Windows Phone 7 but not for the aforementioned framework.

Therefore, I believe you could find better support on how to implement the MVVM pattern in Compact Framework 3.5  for example in the .NET Compact Framework forums.

Regards,

Agustin Adami
http://blogs.southworks.net/aadami

May 22, 2012 at 10:19 PM

Just for clarification I'm not using Prism in any way or MVVM (oops?) in the compactframework =). There are two applications here, one on a device and one on the desktop.

It's just that data files and project files need to be opened in the CF. Therefore I have a data library that includes these types only for re-use. The Desktop Application, which is implemented using Prism/MVVM, references this library then wraps that up in a Service for the data model etc.. I'll probably just have to wrap it in an ObservableCollection on the desktop so that it can support databinding.

That example for the WatchListService is helpful, it looks like it demonstrates what I could be doing, just implement my command in the service, wrap it in my ViewModel and expose it to the View that way.

Thanks a lot for your help.. after I complete this module I should have demonstrated several patterns using Prism that will be beneficial for myself and other developer to use as an example for implementing the future modules.

Thanks Again!

-Alan