caching views and/or viewmodels?

Topics: Prism v2 - Silverlight 2, Prism v2 - Silverlight 3, Prism v2 - WPF 3.5
Jan 29, 2010 at 12:26 PM
Edited Jan 29, 2010 at 3:07 PM

I have a tab based application which is somewhat similar to windows explorer where there are alot of icons and such.

Each time I open a tab i have a delay until all the viewmodel and views are initialized (mostly the icons).

I think this problem can applied generally to most applications.

Im wondering if anyone have thought about caching and resuing viewmodels and views? Is it a good idea?

Ive tried something like this (wont compile i just wrote it as an example).

class SomeViewModel : IDisposable
{
      private readonly IUnityContainer container;
      private readonly ICacheService cacheService;

      public ViewModel(IMyView view, IUnityContainer container, ICacheService cacheService)
      {
	   this.View = view;
           this.View.DataContext = this;
           this.container = container;
           this.cacheService = cacheService;
      }

      public View { get; set; }
 
      public ObservableCollection Children { get; set; }

      void Initialize(Model model)
      {
 	   this.Children = new ObservableCollection();

           foreach(var item in model.Items)            
          {                   
             ViewModel viewModel = cacheService.Get();      
              if(viewModel == null)                         
                      viewModel = container.Resolve();              
               viewModel.Initialize(item);                   
               this.Children.Add(item);                
            }      
        }        

        void Dispose()       
        {             
               foreach(var child in this.Children)             
               {                  
                       child.Dispose();       
                       cacheService.Push(child);           
                }             
                this.Children = null;       
         } 
}

This way i simply reinitialize the viewmodel when i want to use it again. But there are alot of things one can do to optimize this.

For example the "CacheService" would see if there is a cached viewModel with the same already initialized "model" or maybe it would find the viewModel that has the closest initialized state to what one wants.

Maybe i should only dispose and cache in certain cases? For example in my example i remove all the "Children" in "SomeViewModel" soo that the children can be used by other new instances of "SomeViewModel".

However maybe it would be a good idea to keep the children incase i want to open an almost identitical instance of the current one.

Another idea is that the cacheservice becomes responsible for "tearing apart/disposing" viewModels soo that items in a cached viewModel are only used if required and the cached object maintain a "state level" (close to requested final state) as high as possible. 

There are alot of ways to do this... I would like to hear some opinions and ideas on the matter?

 

 

Feb 2, 2010 at 1:03 PM

Hi,

Without knowing the specifics of your application, having a cache service could be useful if the initialization of your Views/ViewModels is taking too long. You should take into account how much memory usage that will consume, but if you have “long lived views” in your application that don’t suffer many changes there shouldn’t be much overhead.

A couple of other things you could do to avoid initializing the views again:

  • Keep the view in the region, but deactivate it. That way the same view instance will persist, but the end user won’t be able to see it. You can reactivate your view when necessary.
  • Register the view/view model instance in the container. That way you can remove it from the view, but retrieve it when you require it.

You should follow the approach that best suits your needs (in this case faster view initialization), and if you find a good solution you can always post it for the community.

If you consider this kind of guidance could be useful of the community, you can add an item to the Issue Tracker. The team might take it into account for a future version.

Please let me know if this helps.

Damian Schenkelman
http://blogs.southworks.net/dschenkelman