首页 > 解决方案 > Prism 7.1 : IContainerProvider & IContainerRegistry

问题描述

Newer developer here, working on my second application, and the first using Prism 7.1.

I am hoping to get a little assistance with properly accessing a ViewModel registered within Shell.xaml.cs.

Here is what I am working with:

App.xaml.cs

public partial class App
{
  protected override Window CreateShell()
  {
    return Container.Resolve<Shell>();
  }
  protected override void RegisterTypes(IContanerRegistry containerRegistry)
  {
    containerRegistry.Register<ShellViewModel>();
  }
}

Shell.xaml.cs

public partial class Shell : MetroWindow
{
    public Shell()
    {
        InitializeComponent();
    }
 }

I am able to access my ViewModel's properties just fine, through doing the following:

var shellVM_Instance = containerProvider.Resolve<ShellViewModel>();
shellVM_Instance.IsBusy = false;

The code will compile, but it will not run. When I run the code, it tells me that ShellViewModel, from within the above var shellVM_Instance, is referencing a null object of type ShellViewModel. This leads me to think that I did not properly register the ViewModel with IContainerRegistry.

Can anyone offer any assistance?

I would like to avoid using a Bootstrapper class, and take advantage of what Prism 7.1 has to offer (Brian's Release Notes)

I appreciate any guidance here, and your patience while I try to wrap my mind around Prism and its true potential.

EDIT:

I see that IContainerRegistry has a RegisterInstance method..

void RegisterInstance(Type type, object instance);

I cannot for the life of me figure out the syntax. My attempts:

protected override void RegisterTypes(IContainerRegistry containerRegistry)
    {
        ShellViewModel shell_VM = new ShellViewModel();
        containerRegistry.RegisterInstance<ShellViewModel, shell_VM>();
    }

Thank you!

-Chris

标签: c#wpfinstanceunity-containerprism

解决方案


There's IContainerRegistry and IContainerRegistryExtensions.

So you can do either

containerRegistry.RegisterInstance( typeof( ShellViewModel ), shell_VM );

or generically with the extension methods

containerRegistry.RegisterInstance<ShellViewModel>( shell_VM );

Even better register as singleton, just in case you have any dependencies (that you would have to resolve yourself, otherwise)

containerRegistry.RegisterSingleton<ShellViewModel>();

That being said, you're doing it all wrong from the first place. Rarely, a view model is a singleton. Instead make your view models communicate through a third party singleton (either EventAggregator or one of your own services). For your case, I suggest something like this:

public interface IApplicationBusyIndicator : INotifyPropertyChanged
{
    bool IsBusy { get; set; }
}

Then make the shell view model watch for changes to IsBusy and activate or deactivate your wait-overlay, while other view models or services set IsBusy while they're doing stuff. You can make it more sophisticated, of course, if you happen to have more than one actor that makes the application busy and those actions overlap...

public interface IApplicationBusySetter
{
    IDisposable RequestBusy();
}

Then show the wait-screen until all of the requests are disposed.


推荐阅读