Load module into a specific region

Aug 26, 2008 at 3:12 PM
Hi

To dynamically load a menu, from a menu event I use a code like this (found the example on this forum)

  // This handles the load module command logic
  void LoadModule(string moduleName) {
    ModuleInfo[] moduleInfo = _container.Resolve<IModuleEnumerator>().GetModule("ModuleName");
    _container.Resolve<IModuleLoader>().Initialize(moduleInfo);
  }

I would like to load this module into a specific region. How do I accomplish this??? 

Also,, is there a way to unload the module view from the region to it was added ???


//lasse
Aug 28, 2008 at 3:32 PM
Am I the only person who would like to load a Module "on demand",,, and would like to be able to control to which region the View of the module should be added????? 

//lasse
Aug 28, 2008 at 4:22 PM
Hi Lassel,  you actually don't load a module into a region; a module contains the view that you will load into a region.  The information you require is beyond the scope of a message thread.  Fortunately! the P&P team did a great job on the documentation; I trust that once you read the following topics that not only will your questions be answered but you'll a better understanding of the infrastructure:

  • Development Activities
    • How to: Dynamically Load Modules
      • How to: Using the Configuration Module Enumerator (has load on demand configuration)
    • How to: Load Modules on Demand
    • How to: Show a View in a Shell Region

 

Aug 29, 2008 at 7:35 AM
Hi and thanks for your answer.
First, I am not a proffersional SW developer so that I am aware that my way to express myself is restricted, both in knowledge and language.

I have read how to "Load Modules" on demand. In all exemples I have found, it seems like the module is aware in advance into which region it will show its view. It looks like ...  

.........
// First dynamically load the module, this is typically done from a Menu Item....................
ModuleInfo[] moduleInfo = moduleEnumerator.GetModule("ModuleName"); moduleLoader.Initialize(moduleInfo);
.....
// This code belongs to the Module, and used for showing the view.
// (This is cut and paste from the manual.....)
public Module(IRegionManager regionManager)
    {
        this.regionManager = regionManager;
        IRegion mainRegion = this.regionManager.Regions["MainRegion"];
        View view = new View();     mainRegion.Add(view);
         mainRegion.Activate(view);
    }
....

/

My question is,,,,, is there a way to change "MainRegion" to different values ???


//lasse
Aug 29, 2008 at 1:00 PM
[Lassel] First, I am not a proffersional SW developer so that I am aware that my way to express myself is restricted, both in knowledge and language.

Actually Lassel you did good, it was me that didn't closely read what you were asking ;)  Above you wrote "which region the View of the module should be added????? "

[Lassel]  "is there a way to change "MainRegion" to different values ???".

Yes, but I'm unsure in what context, i.e., do you want to load a module's view to a different region or change the name of "MainRegion" to something different.  If you could provide a simple scenario (use case) on how you want to apply it I'll be glad to create you sample code to meet the requirement; this may prevent some round trips in message content.
Aug 29, 2008 at 7:39 PM
.. I would like to add a module's view to different regions.....

I am trying to move a wpf application into prism.
Basically I have a view displaying "persons" (using a listbox). I have defined this as a Module named PersonCollectionModule. To be able to add/modify/remove persons from the list a have defined another module called PersonCrudModule. The reason I have defined a separate module for this, is that same functions (crud) also is required from other parts of my application (defined in other modules). The PersonCollectionView contains a region to which a would like to add the PersonCrudView.
For different reasons I would like to avoid to have a fixed name on the region to which I will add the PersonCollectionView.

I don't know if I somehow breaks the ideas behind prism,,,,,,, but it would make my life easier ,,, porting my application.

//lasse
Aug 30, 2008 at 7:44 PM
Edited Aug 31, 2008 at 3:50 PM
For my http://www.CodePlex.com/SDMS project I started creating my interface with you in mind.  It will have a Visual Studio Style inteface with a Tools | Options |  RSS Feed configuration module/view where you can configure the pane that the RSS feed module/view should be placed in (dynamically).   I should have this done in a few days.

Where it "may" get tough is that I'm going to implement the http://www.Codeplex.com/CLRAddins so that the modules can be loaded and unloaded in the main region.  I'm currently studying the WPF Calculator which shows how powerful this feature is;  I'll code it in a manner consistent with the requirements to make it available as a Contrib project which may slow me down further however I'll let you know as soon as I have a "functional" prototype (hopefully by this time next week).

The above should cover your requirements.  (Shameless plug for my SDMS project ;) In addition... I feel a wee bit cramped having my MDI interface taken away with WPF (I know it can be done but I am going to stay away from WinForms on this solution) so I plan on also providing the ability to load an Add-in within a new window (as a child of my main shell).  When this infrastructure is completed I should have all the freedom required to implement the UI as required and will move on to TDD of my data layer (NHibernate).

Edited: Flash demo of Visual Studio style interface is show in this BLOG
Sep 2, 2008 at 12:54 PM
Tanks for the links. I will look into them.
//lasse
Sep 3, 2008 at 4:47 AM
Edited Sep 3, 2008 at 4:57 AM
I have the first part of the demo done for you - this should cover all of the bases on loading modules (on demand) and updating regions with Views.  The demo displays a RSS Feed listbox which you can change from one region to another with the click of a button - see flash DEMO HERE.   Disclaimer: I took "a lot" of shortcuts, e.g., threw code in code-behind and am using Smart Client Software Factory subscription/publish event handling since this is throw-away code (for the sake of this demo).   This is practical because CodePlex saves change sets so it will be available as I move on.

  1. The SDMSMain \ MainModule.cs will load MainView.xaml into the MainRegion of the MainShell.
  2. The MainView.xaml takes over from there and is the main layout/design for the demo
  3. The SDMSMain and RSSFeed are separate projects
MainShell project - has a reference to SDMSMain and RSSFeed projects (nothing else to see here for this topic)

SDMSMain \ VPC \ MainView.xaml has new UseCaseRegion, RssFeedRegion and MainWorkspace for this demo
SDMSMain \ VPC \ MainController.cs has "throw-away" code (done for the purpose of this demo) 
RSSFeed \ RssFeedModule.cs - On-Demand module loaded by the Menu | Tools | Options menu click in MainController.cs
RSSFeed \ RSSFeedView.cs - Listbox view that will have blog list (from my blog)
RSSFeed \ RSSViewer.cs - loaded in the MainWorkspace (displays blog contents in Frame)

Http://www.CodePlex.com/SDMS  - source code

Lines 113-120 load the RSSFeed module On-Demand, Lines 93-112 processes the [Click Me] button

   88 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

   89 // THROW-AWAY CODE FOLLOWS - for demo purposes....

   90 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

   91 

   92 // Move the RSS Feed window in RSSFeedView.xaml.cs

   93 if (subFactoryKey.Equals("ClickME"))

   94 {

   95     IRegion useCaseRegion = RegionManager.Regions["UseCaseRegion"];

   96     IRegion rssFeedRegion = RegionManager.Regions["RssFeedRegion"];

   97 

   98     object rssView = rssFeedRegion.GetView("RssFeed");

   99     object useCaseView = useCaseRegion.GetView("RssFeed");

  100 

  101     if (rssView != null)

  102     {

  103         rssFeedRegion.Remove(rssView);

  104         useCaseRegion.Add(rssView,"RssFeed");

  105     }

  106     else

  107     {

  108         useCaseRegion.Remove(useCaseView);

  109         rssFeedRegion.Add(useCaseView, "RssFeed");

  110     }

  111 }

  112 

  113 // Dynamically load the RSS module

  114 if (subFactoryKey.Equals("mnuOptions"))

  115 {

  116     ModuleLoader.Initialize(new ModuleInfo[]

  117     {

  118         ModuleEnumerator.GetModule("RSSFeedModule")

  119     });

  120 }

  121 else

  122     if (!string.IsNullOrEmpty(subFactoryKey.ToString()))

  123         MessageBox.Show(subFactoryKey.ToString());


RSSFeedModule.cs code follows (On-Demand module)

   14 [Module(ModuleName = "RSSFeedModule", StartupLoaded = false)]

   15 public class RSSFeedModule : ModuleBase

   16 {

   17 /// <summary>

   18 /// Injection Constructor

   19 /// </summary>

   20 /// <param name="regionManager">Registered IRegionManager</param>

   21 /// <param name="container">Registered IUnityContainer</param>

   22 /// <param name="presenter">Registered IMainPresenter</param>

   23 public RSSFeedModule(IRegionManager regionManager,

   24     IUnityContainer container)

   25 {

   26     RegionManager = regionManager;

   27     Container = container;

   28 }

   29 

   30 protected override void RegisterViewsAndServices()

   31 {

   32     base.RegisterViewsAndServices();

   33 }

   34 

   35 public override void Initialize()

   36 {

   37     base.Initialize();

   38 

   39     // Add view to region

   40     IRegion mainRegion = RegionManager.Regions["RssFeedRegion"];

   41 

   42     // Name it so we can move it later in MainController.cs

   43     mainRegion.Add(Container.Resolve<RSSFeedView>(),"RssFeed");

   44 }

   45 }


RSSFeedView.xaml.cs

   23 public partial class RSSFeedView : UserControl

   24 {

   25     [Publishes("OnRssSelected")]

   26     public event EventHandler OnRssSelected;

   27     [Dependency]

   28     public IUnityContainer Container { get; set; }

   29     [Dependency]

   30     public IRegionManager RegionManager { get; set; }

   31 

   32     public RSSFeedView()

   33     {

   34         InitializeComponent();

   35     }

   36 

   37     private void listBox1_SelectionChanged(object sender,

   38         SelectionChangedEventArgs e)

   39     {

   40         IRegion mainRegion = RegionManager.Regions["MainWorkspace"];

   41         RSSViewer view = (RSSViewer)mainRegion.GetView("Viewer");

   42 

   43         if (view == null)

   44             // If we want to remove the View we'll need to name it

   45             mainRegion.Add(Container.Resolve<RSSViewer>(), "Viewer");

   46 

   47         // If OnRssSelected is subscribed to then notify

   48         if (OnRssSelected != null)

   49             OnRssSelected(this, e);

   50 

   51     }

   52 

  

RSSViewer.xaml.cs code follows:

   21 public partial class RSSViewer : UserControl

   22 {

   23     public RSSViewer()

   24     {

   25         InitializeComponent();

   26     }

   27 

   28     [SubscribesTo("OnRssSelected")]

   29     public void RssSelected(object sender, EventArgs e)

   30     {

   31         SelectionChangedEventArgs args = e as SelectionChangedEventArgs;

   32         ListBox listBox = args.Source as ListBox;

   33         lstRSSFeeds.SelectedIndex = listBox.SelectedIndex;

   34     }

   35 

   36 }

  

I cheat above...  The RSSView's binding is sync'd with a "collapsed" (hidden) listbox.  I simply publish the event and set the hidden listbox to the visible listbox's SelectedIndex.