CHAPTER 8
Prism 4 regions are an important part of how we dynamically build User Interfaces (UI) in XAML based solutions. In chapter 6 we briefly looked at the RegionManager.RegionName property. We used this property to assign Prism 4 regions to user controls in our shell forms. In this chapter we'll take a closer look at Prism 4 regions and get a better idea of how to use them in our solutions.
A Prism 4 region is a place holder in a window or view that sets aside a section of the UI for dynamic injection of content.
You may recall that when we talked about the shell form in chapter 6, that we added regions to the shell forms in that project.
Listing 29: The MathRegion Of The ShellLogoTop Shell Form.
prism:RegionManager.RegionName="MathRegion" |
The code in Listing 29 serves as the place holder for math content in the shell form. A container control (In this case the Syncfusion TabControlExt control) is added to the shell form with no content. Listing 29 sets the control's RegionName attached property to MathRegion.
The MathRegion RegionName property will serve as an identifier that is used to inject views at runtime.
Note: We are going to defer going into detail about Prism 4 view injection at this time. We'll go into detail in the next chapter when we talk about Prism 4 modules.
Prism 4 Regions And Microsoft Controls:
Adding Microsoft controls with Prism 4 regions is easy. Simply add the Prism 4 library to your Window or view. Then add an appropriate container control and add a unique RegionManager.RegionName to that control.
There are three types of Microsoft container controls that work with Prism 4 out of the box.
The content control can use a single injected view at a time. If a content control that already has a view injected, is injected with a new view, the previous view is replaced with the new one. An example of content controls is the ContentControl.
The Items control can use multiple injected items or views in a single container. An example of a Items Controls are listboxes and comboboxes.
Selector controls can use multiple views in a single container also. An example of selector controls are Tab Controls and Dock managers.
The reason that these controls work with Prism 4 out of the box is because the Prism 4 framework comes with three RegionAdapters that are designed to work with Microsoft controls that derive from the three control types.
Built in Prism 4 RegionAdapters:
These RegionAdapters are included when you install Prism 4. As long as you are using Microsoft controls that derive from these types your code should work with no modifications.
Microsoft Types That Work With the Three RegionAdapters:
Using Prism 4 Regions With Third Party Controls:
Now that we have seen how RegionAdapters work with Microsoft controls, let's look at an example where we use a third party control. In the Virtual Calculator solution, two Microsoft based ContentControls are used to display the company logo and application logo and each of these modules work just fine.
In the case of the math module, we use Syncfusion's TabControlExt control. If we try to add the RegionManager.RegionName attached property to this control we get an error. The reason for this is that there is no RegionAdapter that works with the TabControlExt control in the Prism 4 library. So, how do we deal with this issue?
Tip: Most third party control venders supply RegionAdapter example code with their control suites. This is the case with at least three control suite vendors that I have worked with, including Syncfusion.
If your intention is to use Microsoft Prism 4 in your solutions with third party controls, insure that the control vendor's controls work with the framework.
The Syncfusion TabControlExt RegionAdapter Class:
When working with third party controls, it's necessary to create RegionAdapter classes for the controls that you want to use with Prism 4.
Note: This is the only area of Prism 4 where I have found it necessary to configure Prism 4 to work with third party controls. In all other areas I have found Prism 4 to work transparently with these controls.
You may be wondering why we to create a special class in order to work with non Microsoft controls? To understand why this is necessary, let's look at the RegionAdapter class for the Syncfusion TabControlExt control.
Listing 30: The SyncfusionTabCtrlRegionAdapter Class.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Practices.Prism.Regions; using Syncfusion.Windows.Tools.Controls; using System.Windows; namespace PRISM4.MAIN.REGION_ADAPTERS { public class SyncfusionTabCtrlRegionAdapter : RegionAdapterBase<TabControlExt> { public SyncfusionTabCtrlRegionAdapter (IRegionBehaviorFactory regionBehaviorFactory) : base(regionBehaviorFactory) { } protected override void Adapt(IRegion region, TabControlExt regionTarget) { region.Views.CollectionChanged += delegate { foreach (var tab in region.Views.Cast<FrameworkElement>()) { if (!regionTarget.Items.Contains(tab)) { regionTarget.Items.Add(tab); } } }; } protected override IRegion CreateRegion() { return new Region(); } } } |
The first thing to take into account is that the RegionAdapter class inherits a generic class of type RegionAdapterBase. This base class takes a payload of TabControlExt, the Syncfusion Tab Control.
Next constructor injection is used to instantiate a type of IRegionBehaviorFactory this interface derives from Microsoft.Practices.Prism.Regions. The RegionBehaviorFactory class is then passed to the base class.
Listing 31: Using Constructor Injection and Passing the regionBehaviorFactory to the base class.
public SyncfusionTabCtrlRegionAdapter (IRegionBehaviorFactory regionBehaviorFactory) : base(regionBehaviorFactory) { } |
The inherited RegionAdapterBase class has two abstract methods CreateRegion and Adapt.
The RegionAdapterBase CreateRegion Method:
The CreateRegion method determines the type of object to return, it returns one of three Prism 4 region types:
The Region return type is used with controls that derive from the Selector class. Tab controls and dock managers are some of the controls that use this return type.
The SingleActiveRegion Return Type:
The SingleActiveRegion return type is used with controls that derive from the content control class. Content controls is one of the controls that use this return type.
The AllActiveRegion Return Type:
The AllActiveRegion return type is used with controls that derive from the Items control class. Listboxes and comboboxes are some of the controls that use this return type.
The RegionAdapterBase Adapt Method:
The Adapt method is where Prism 4 adds and removes views to and from Prism 4 regions.
Taking a look at the code in listing 30 we see that two arguments are passed to the method, a IRegion object (region) and a TabControlExt object (regionTarget).
The region.Views.CollectionChanged event is triggered each time that a view is added or removed or otherwise changed in the region's Views collection.
An iterator is used to loop though each tab in the Views collection. If the tab is not already in the collection, it is added.
In this case it is only necessary to add tabs. If required, code could be added to trigger when tabs are removed.
Adding the RegionAdapter to the Bootstrapper:
Ok, we have a RegionAdapter. How do we let Prism 4 know about it? That's the next step in the process.
The ConfigureRegionAdapterMappings Method:
One of the methods in the bootstrapper class is the ConfigureRegionAdapterMappings method. This method is used to register RegionAdapters with Prism 4. Listing 32 is an example of the ConfigureRegionAdapterMappings method that is used by the Virtual Calculator solution.
Listing 32: The Bootstrapper ConfigureRegionAdapterMappings Method:
protected override RegionAdapterMappings ConfigureRegionAdapterMappings() { RegionAdapterMappings mappings = base.ConfigureRegionAdapterMappings(); if (mappings != null) { mappings.RegisterMapping(typeof(TabControlExt), this.Container.Resolve<SyncfusionTabCtrlRegionAdapter>()); } return mappings; } |
The first step is to create the RegionAdapterMappings object from the base class's mappings object.
A guard clause is used to insure that the mappings object was created correctly. If the mappings object is not null, the TabControlExt and its associated RegionAdapter is registered in the mappings object.
As many RegionAdapters as needed can be registered in this manner.
The bottom line is that RegionAdapters show Prism 4 how to work with controls that do not work with the three RegionAdapters that are included with Prism 4 out of the box. This makes it possible to extend the types of controls that can be used with the Prism 4 framework as views.
So, what have we learned so far? Prism 4 regions allow for the dynamic building of user interfaces at runtime. Regions are placed in views using the RegionManager.RegionName attached property. The Microsoft control library already has RegionAdapters that work with its container controls. Third party controls need custom RegionAdapter classes in order to be used as regions in Prism 4 solutions. Many third party control companies furnish the needed RegionAdapter code for their controls.
Now that we have looked at Prism 4 regions in detail, let's take a look at Prism 4 modules.