Windows-XAML / Template10

Making Windows 10 apps great again
Apache License 2.0
1.41k stars 389 forks source link

Persist the View and ViewModel #254

Closed pellea closed 8 years ago

pellea commented 8 years ago

Hello,

Is it possible to persist the View and ViewModel using a DI container ? I don't want my views to be created each time because of the "heavy load" of the data.

Regards, Adrien.

saguiitay commented 8 years ago

I would also love to see some way of persisting the ViewModel (perhaps some form of caching service?)

pellea commented 8 years ago

Usually I use Prism with Unity container to achieve that.

qmatteoq commented 8 years ago

Template10 doesn't come with its own DI implementation, but you can absolutely use it with any other DI container, like Unity or SimpleIoC

pellea commented 8 years ago

I found 2 possible ways to do it but ... The Resolve() method is never used. The other method ResolveForPage() is called when the DataContext is null. How do I get the ViewModel in the view in that case? Is it possible to have constructor injection ?

JerryNixon commented 8 years ago

We can easily handle the view model but not the view. Not until we add Navigate To Instance too the Navigation Service. We NEED an injection sample.

JerryNixon commented 8 years ago

Resolve for page will automatically inject the returned result into any pages data connect. But it is only an alternative to a view model locator which can easily implement injection. It's a one or the other approach, to be honest. Many developers prefer the locator approach. I could go either way.

JerryNixon commented 8 years ago

Persist an entire view model? Hmm. Maybe we need a serializer util to help with that. Not a common approach I will warm you though.

jhalbrecht commented 8 years ago

First thing I do with a new project is add MvvmLight libs only via nuget. There is an MvvmLight Sample in the Template10 repository. I use MvvmLight for not only my view models but inject my services, repositories etc....

in .xaml code behind I can get a single instance I sometimes use with x:Bind;

public MainPageViewModel ViewModel => SimpleIoc.Default.GetInstance<MainPageViewModel>();

Be sure in ViewModelBase.cs

// public abstract class ViewModelBase : Template10.Mvvm.ViewModelBase
// change to:
    public abstract class ViewModelBase :
    GalaSoft.MvvmLight.ViewModelBase, Template10.Services.NavigationService.INavigable
[...]

I use the MvvmLight ViewModelLocator.cs

   public class ViewModelLocator
    {
        static ViewModelLocator()
        {
            ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
            SimpleIoc.Default.Register<IMyDataService, MyDataService>();
            SimpleIoc.Default.Register<MainPageViewModel>();
        }
        public MainPageViewModel Main => ServiceLocator.Current.GetInstance<MainPageViewModel>();

wiring it up in

App.xaml

 <viewModels:ViewModelLocator x:Key="Locator"
                                         d:IsDataSource="True" />

MainPage.xaml

<Page
[...]
    DataContext="{Binding Main, Source={StaticResource Locator}}"
>

In MainPageViewModel.cs

private readonly IMyDataService _myDataService;

 public MainPageViewModel(IMyDataService myDataService)
        {
            _myDataService = myDataService;
        }
pellea commented 8 years ago

"Persist" was not the better word to explain what I tried to do. Usually I have all my ViewModel in the container. Everything is resolve using constructor injection. I use this "way" because I don't want to reload every time the ViewModel between each navigation of pages (and ultimatly I shared ViewModels between pages. I know some people don't like that). If I need to "persist" the ViewModel, I add them to the container with the ContainerControlledLifetimeManager (with Unity).

How do I do constructor injection (in the view) ? This is not possible in this library ...