Region.Activate does not switch between views - Solved

Topics: Prism v4 - Silverlight 4
Aug 2, 2010 at 8:49 PM

I have read several posts like this but "no cigar":

http://compositewpf.codeplex.com/Thread/View.aspx?ThreadId=42078

The Setup:

Very simple application based on "PrismSilverlight 4.0 QuickStart solution" with a small variation - I moved the XAML of the original ShellView to Module1 and named it "RegionsView". Then I replaced the original ShellView with a simple ItemsControl which has only one main region "MainRegion" defined inside this ItemsControl. The main idea being - working with nested regions where I can use the container of the new MainView to show the nested regions from Module1.

In Module1 the main view is the "RegionsView" which has a region "MainRegion1" which is defined inside a view containing a "ContentControl" - this is to allow the switch between views inside the same region only by using myRegion.Activete(myView_n). "MainRegion_1" (in RegionsView.XAML) is supposed to show as a nested region inside "MainRegion" (in ShellView.XAML) (sorry for the very descriptive names). I also preserved the two origin views in Module1 "View1" and "View2" which are supposed to alternate inside MainRegion_1.

Upon start of the application nothing shows inside the MainRegion. Upon a button click I register MainRegion_1 which properly shows as a nested region.

Upon the click of another button I register and show View1 and then upon click of another button I register and try to show View2 - which does not show.

I do see that the code flows through correctly and that both views are registered and added. I make sure they are initialized only once. I also use a ContentControl which is supposed to take care of switching between the views via "Acitvate()". This does not happen however. If I start with View1 - View2 does not show. If I start with View2 - View1 does not show.

Here the most meaningful lines:

      private void DisplayView(string viewName)
        {
            // Get a reference to the main region.
            IRegion mainRegion = _regionManager.Regions[RegionNames.MainRegion];

            // Create the view if we need to.
            object view = mainRegion.GetView(viewName);

            if (view == null)
            {//Register each view only once
		//Step-1: Button_1-> Show RegionsView
		//Step-2: Button_View1-> Show View1
		//Step-3: Button_View2-> Show View2
                switch (viewName)
                {
                    case "View1":
                        _regionManager.RegisterViewWithRegion("MainRegion1", typeof(View1));
                        view = this._container.Resolve<View1>();
                        break;
                    case "View2":
                        _regionManager.RegisterViewWithRegion("MainRegion1", typeof(View2));
                        view = this._container.Resolve<View2>();
                        break;
                    case "RegionsView":
                        view = this._container.Resolve<RegionsView>();
                        break;
                }

                // Add the veiw to the main region.
                mainRegion.Add(view, viewName);
            }

            // Activate the view only once.
            if (view != null)
            {
                mainRegion.Activate(view);
            }
        }

The Problem:

Basically the sticking point is - why is ContentControl not alternating between the views? I am assuming all of other things happen correctly as I am able to show either view as intended.

Forgot to mention - new to Prism - but that is evident I guess.

Many thanks for any tips or links.

 

Aug 3, 2010 at 4:38 PM
Edited Aug 3, 2010 at 4:40 PM

OK - this is the error I was making.

Note: this should be coded "nicer & cleaner" in a real-life project - but here all is crammed hardcoded so one can read it in a small space:

Basic understanding (I changed some of the names so they are more descriptive):

1. ShellView.XAML has an ItemsControl used as a "Parent" region for the entire application. This Parent view is used as a container for Modules to inject their views into it - however complex.

2. Module1 has three views: RegionsView (only regions); View1&2 - Views with actual functional code; These are supposed to appear inside "Module1_MainRegion"

The problem was that I was registering the views (View1&2) with the Parent-Region. One has to register Module1_MainRegion (the container of View1&2) with the ParentView and then register View1&2 with Module1-RegionsView (Their own container - not the global parent container) .... Huh ... now that I put it in writing it sounds like "duh ... what were you thinking" ... . Anyway - Here the code:

//Inside ShellViewModel.cs
        public void SwitchViewClicked(string name)
        {
            _eventAggregator.GetEvent<SwitchViewEvent>().Publish("RegionsView");
        }

//Inside Module1.MainRegionController.cs
        private void SwitchViewEventHandler(string viewName)
        {
            DisplayView(viewName);
        }

        private void DisplayView(string viewName)
        {
            
            IRegion mainRegion; 
            object view;

            if (viewName == "RegionsView")
            {//The button declared in ShellView.XAML is supposed to
             //show the main design of Module1 without populating it.
                mainRegion = _regionManager.Regions["ParentRegion"];
                view = mainRegion.GetView(viewName);
            }
            else
            {//Buttons inside the main design of Module-1 are
             //supposed to call View1&2
                mainRegion = _regionManager.Regions["Module1_MainRegion"];
                view = mainRegion.GetView(viewName);
            }

            if (view == null)
            {
                switch (viewName)
                {
                    case "View1":
                        _regionManager.RegisterViewWithRegion("Module1_MainRegion", typeof(View1));
                        view = this._container.Resolve<View1>();
                        break;
                    case "View2":
                        _regionManager.RegisterViewWithRegion("Module1_MainRegion", typeof(View1));
                        view = this._container.Resolve<View2>();
                        break;
                    case "RegionsView":
                        view = this._container.Resolve<RegionsView>();
                        break;
                }

                // Add the veiw to the main region.
                mainRegion.Add(view, viewName);
            }

            // Activate the view.
            if (view != null) mainRegion.Activate(view);
        }