views:

83

answers:

1

I have a shell which looks like toolbar and defines my main region (a wrap panel). What I need to do is be able to add widgets to the shell and when a widget is clicked, a new window (view) is opened. Below is what I have so far:

I created a module class which adds a view to the main region:

public class MyModule : IModule
{
  protected IUnityContainer Container { get; private set; }

  public MyModule(IUnityContainer container)
  {
    Container = container.CreateChildContainer();
  }

  public void Initialize()
  {
    var regionManager = Container.Resolve<IRegionManager>();
    MyModuleView myModuleView = new MyModuleView();
    regionManager.Regions["MainRegion"].Add(myModuleView);
  }
}

Here is the content of MyModuleView:

  <Grid>
    <Grid.DataContext>
      <vm:MyModuleVM/>
    </Grid.DataContext>
    <Button Content="My Module" Foreground="White" FontWeight="Bold" Command="{Binding Path=LaunchCommand}">
    </Button>
  </Grid>

The view model, MyModuleVM:

  class MyModuleVM : ObservableObject
  {
    protected IUnityContainer Container { get; private set; }

    public MyModuleVM()
    {
    }

    RelayCommand _launchCommand;
    public ICommand LaunchCommand
    {
      get
      {
        if (_launchCommand == null)
        {
          _launchCommand = new RelayCommand(() => this.LaunchTestView(),
              () => this.CanLaunchTestView());
        }
        return _launchCommand;
      }
    }

    private void LaunchTestView()
    {
      TestView view = new TestView();
      view.Title = "Test View";
      var regionManager = Container.Resolve<IRegionManager>();
      regionManager.Regions["MyWindowRegion"].Add(view);
    }

    private bool CanLaunchTestView()
    {
        return true;
    }
  }

So my plan was as follows:

  • Create the class that implements IModule (MyModule) and have it load a view (MyModuleView) into the shell when initialized

  • Create a view model for the module (MyModuleVM) and set it as the DataContext of the view displayed in the shell

  • MyModuleVM contains a command that a button in MyModuleView binds to. When the button is clicked the command is triggered

  • Now, here is where I am stuck. Using a WindowRegionAdapter (an adapter that helps to create views in separate windows) I wanted to create and display a new view. As seen in MyModuleVM, LaunchTestView needs access to the container in order to add the view to a region. How am I supposed to get to the container?

Besides my specific question about accessing the container, how is my overall strategy of adding "widgets" to a toolbar shell and launching views when they are clicked? Am I comlpetely off track here when it comes to MVVM with Prism?

Thanks guys.

A: 

Hi,

You can get the container injected through constructor or property injection. To do that, the ViewModel instance must be resolved by the container, or the BuildUp method should be called after it has been instantiated.

I hope this helps.

Thanks, Damian

Damian Schenkelman
Hey Damian. My view model (which needs access to the container) is created through the xaml of the view. Where would I even write the code to call container.Resolve or container.BuildUp?
Flack
In this case, you can do it right after new MyModuleView() (i.e.: container.BuildUp(typeof(MyModuleVM), myModuleView.DataContext);), but in this kind of scenario, resolving teh RegionManager through the ServiceLocator might also be a good approach.
Damian Schenkelman
Hmm. It looks like myModuleView.DataContext has not yet been created if I add the BuildUp right after MyModuleView myModuleView = new MyModuleView(). Maybe I am going about this wrong. This seems like a simple task that I am making harder than it needs to be. Is my approach to implement a toolbar with widget views that launch other views sound? Do you know of any good resources discussing the ServiceLocator?
Flack
Some resources: http://commonservicelocator.codeplex.com/, Prism documentation and code, Prism forum questions at codeplex.The common approach for "modular toolbars" is similar to the one you are following:1) Load module.2) Resolve V-VM pair.3) Add V to toolbar region.You seem to be having trouble with 2), so I would recommend taking a look at the Prism docs and code, as well as the Unity docs to understand the different ways the V-VM can be hooked together.
Damian Schenkelman
Thanks for the help Damian.
Flack