What's a good pattern for reuseable lookup lists?

Topics: Prism v4 - Silverlight 4, Prism v4 - WPF 4
Aug 10, 2011 at 1:44 PM

Hi

I have a PRISM application with a master to multiple children setup. So for example I will insert a usercontrol showing a list of Person in my main region then have instances of Address, Contacts etc in my child region and load the filtered data when the master list publishes a selection changed event. In order to make it easy to do CRUD operations in the children I've set up all user controls with their own viewmodels.

My problem is that every child viewmodel needs a List<Person>, and of course when I do changes in the Master list that chnages the undelying data, all those List<Person> in each child viewmodel must be updated also.

Is there some clever way to set up a single List<Person> that all other child viewmodels can use so that I can update this one list only yet have it reflected in all viewmodels?

TIA

Dennis

Developer
Aug 10, 2011 at 7:21 PM
Edited Aug 10, 2011 at 7:21 PM

Hi Dennis,

If you want to share information between multiple viewmodels (regardless in which region/module they are) you could implement a shared service that stores a single List<Person> collection and inject that service in each viewmodel. Then, make each viewmodel access the data in the collection through the service, so when a CRUD operation is performed on the collection the changes will be reflected in all the viewmodels.

For more information about shared services you can check:

I hope you find this useful,

Damian Cherubini
http://blogs.southworks.net/dcherubini

Aug 12, 2011 at 1:25 PM

Hi

I'm not sure I see how this would help. I have a PeopleRepository that I can inject into the other ViewModels and then use peopleRepository.GetAll() to fill a public List<Person> in eacg ViewModel, but that only saves me from rewriting the LINQ call. When the underlying People entity set changes in the database, I would still have to tell each ViewModel to requery the repository/service and refresh it's own list, wouldn't I?

I was thinking maybe of having a global resource of public static List<Person> so that the comboboxes in the relevant Views can all bind to the one list, and I only have to update that one list, but I'm not comfortable with static resources yet so I worry what will happen down the road.

TIA

Dennis

Developer
Aug 12, 2011 at 1:38 PM

Dennis,

If you use a shared service and export it as a non shared export (or a singleton instance, in case you're using unity), the same instance of your PeopleRepository will be shared among all your viewmodels; therefore, when updating the List<Person> property in your service, you could make all your view models consume it. To this end, you could have your PeopleRepository expose an event, which can be raised when the GetAll method has finished executing, and make your view models subscribe to that event. By doing that, you only need to query the database once to fill the values in the different view models.

The approach of having a global static resource isn't recommendable, as it would break some testability and maintainability concerns (for example, you wouldn't be able to mock the dependency in your view models in a testing scenario).

I hope you find this helpful.

Guido Leandro Maliandi
http://blogs.southworks.net/gmaliandi

Aug 12, 2011 at 1:50 PM

OK, I think I see it more clearly now.

In this case the PeopelRepository shouldn't be used, but rather a dedicated service for this lookup list (since the repository has CRUD etc). I'm a newbie programmer (my background is IT admin) and singleton doesn't tell me much, but I assume it means the resource is static, or should I use container.RegisterInstance<>()? (I use Unity).

I would then need the following in the service; a List<Person>, a method that returns that list, a method that updates the list from the database and an IEventAggregator that publishes.

In the ViewModels I would have an EventAggregator that subscribes and refills each the List<Person> in the ViewModel.

Did I get it this time?

TIA

Dennis

Developer
Aug 12, 2011 at 2:23 PM

Hi Dennis,

That's correct, a dedicated service should be implemented for that, and that service would probably consume the people repository when needed.

In the context of using Unity in your application, a singleton instance is an instance of a class that will be kept alive as long as the container is kept alive (which is probably the whole life cycle of your application). Therefore, in practical purposes, the same instance of your class will be returned when you call the IUnityContainer.Resolve<T> throughout your application. Using the IUnityContainer.RegisterInstance<T> method is a possible way to achieve that. Another one is to use the IUnityContainer.RegisterType<TFrom,TTo> method, passing a ContainerControlledLifetimeManager as the parameter. The difference between them is that, when you use the RegisterInstance method, you need to pass an instance to that method, and that will be the one that will be shared and kept alive; whereas when you use the RegisterType method passing a ContainerControlledLifetimeManager, the container will instantiate your service, and will always return the first (and only) instance it has created.

Using a static resource would, as I've mentioned in my previous answer, break testability and maintainability concerns. This is because you would be creating a strong dependency between your components and your static resource, and you wouldn't be able to mock it on a test scenario. But in the case of using the container to expose a shared service (by doing an interface mapping), you would only depend on the interface, and your view models or any other component that depends on that service would be abstracted from the concrete implementation of the service (i.e. the only one that will be concerned with the concrete implementation of the service will be the container, which is responsible for mapping ISomeService -interface- to SomeService -implementation-).

You can read more about the benefits of the Inversion of Control pattern and Dependency Injection in the following chapter from the Prism MSDN documentation:

Chapter 3: Managing Dependencies Between Components

As for the approach you've proposed which involves using the event aggregator, it is a valid possibility to achieve your scenario. In case you use the event agrgegator, you don't need to make your view models depend on your service, but rather on the event aggregator.

However, using the event aggregator is not the only possibility to achieve that; when I mentioned the use of an event to notify that the list of people has been refreshed, I was referring to exposing a common .NET event in your service, which your components (such as the view models) could subscribe to.

Both approaches have their benefits and caveats, so the choice would be based on your personal preference and requirements. You can read more about it in the following chapter from the Prism MSDN documentation:

Chapter 9: Communicating Between Loosely Coupled Components

I hope you find this helpful.

Guido Leandro Maliandi
http://blogs.southworks.net/gmaliandi

Aug 12, 2011 at 2:29 PM

Hi

I just implemented my DialogService the way you suggested and it works great, so I should be able to implement lookuplists the same way. I'll look into the .NET events vs EventAggregator and see what suits me better.

Thanks a lot for all your help.

Re

Dennis