0

My WPF application uses Caliburn.Micro as MVVM framework, Entity Framework as data access technology. The purpose of the application is to maintain database. There are multiple Views that consist of menu and result datagrid. With menu controls user specifies what DB data must be shown in results datagrid. Some of ComboBoxes in different Views binded to same properties List<EntityName> in their ViewModels.(Menus have same items to chose from). Each of this Lists loads from DB when it's ViewModel initialises. I don't want to load same Lists from DB for each View, I want make it once. For achieve this I have moved this List properties to another class MenuLists with PreloadLists() method to get lists from DB once, then injected this class as singleton to each ViewModel using Caliburn's built-it IoC container. Like this:

IoC container configuration:

container.PerRequest<KitchenOneViewModel>();
container.PerRequest<KitchenTwoViewModel>();
container.Singleton<IMenuLists, MenuLists>();

MenuLists class:

public class MenuLists : IMenuLists
{

    public List<Meat> MeatLst { get; set; }
    public List<Fish> FishLst { get; set; }

    public void PreloadLists()
    {
        using (var db = new DBEntities())
        {
            MeatLst = db.Meat.OrderBy(x => x.MeatName).ToList();
            FishLst = db.Fish.OrderBy(x => x.FishName).ToList();
        }
    }
}

Injecting it in ViewModel:

public KitchenOneViewModel(IMenuLists menuLists)
    {
        _menuLists = menuLists;
    }

The problem is that I need to call MenuLists.PreloadLists() somehow, but if I do this in MenuLists consructor, I'll get long UI freeze in first ViewModel initialization, because constructor of MenuLists(with expensive PreloadLists() DB-access operation) will be called. I don't know what of Views will be opened first, so I can't call PreloadLists method from there. I need to preload my lists once without freezing UI. How can I resolve it? Maybe delay MenuLists initialization somehow?

AsValeO
  • 2,859
  • 3
  • 27
  • 64
  • 1
    Does the list never change? Maybe add a "loaded" flag in the "PreloadLists" function, and check the flag, if its true, return, if not load the lists. You can then call the function inside another thread when the application starts, or as part of the spash-screen operations (you can also call it in every function with little impace if its already loaded). You could also have a "ResetLists" function that resets the loaded flag and reloads the lists if it changes... – Ron Beyer Apr 20 '15 at 18:47

1 Answers1

1

Either lazily load each list individually to cut down on initialization time, something like:

//only initialized when it's used
private static Lazy<List<Meat>> meatList 
     = new Lazy<List<Meat>>(
             () =>
             {
                 //load single list here
             }
     );
public List<Meat> MeatList { get{ return meanList.Value; } }

...or if you want to initialize everything at once, do so when your application starts up versus waiting for the ViewModels to be instantiated.

Alternately, you could consider having the initialization be async if you don't need to block.

Colin
  • 4,025
  • 21
  • 40