Microsoft patterns and practices prism 4.0 framework
Thanks to the rich template support in WPF, you can actually add models directly to the region. Regions can be registered in two ways. Once a region has been defined via XAML, it will automatically be registered at run time with RegionManager, one of the composition services registered by the bootstrapper.
RegionManager is essentially a Dictionary where the key is the name of the region and the value is an instance of the IRegion interface. The RegionManager attached property uses a RegionAdapter to create this instance.
Note, however, that if using attached properties doesn't work for you or you need to register additional regions dynamically, you can manually create an instance of the Region class or derived class and add it to RegionManager's Regions collection. Adapters are registered with a RegionAdapterMappings class. Figure 6 shows the implementation of ItemsControlRegionAdapter.
How the adapter itself is implemented depends completely on the type of UIElement to which it is being adapted. The Adapt method accepts two parameters. The second parameter is the UIElement that represents the region. The Adapt method performs the relevant plumbing to ensure that the region works with the element. In the case of an ItemsControl, the adapter automatically removes any child items from the ItemControl itself and then adds them to the region.
The region's Views collection is then bound to the ItemsSource of the control. Regions can contain views that are active or inactive. In the case of the ItemsControl, all of its items are active all the time because it does not have a notion of selection.
However, in the case of other types of regions, such as Selector, only one item is selected at a time. A view can implement the IActiveAware interface so that it is notified by its region that it is selected. Whenever the view is selected, it will have its IsSelected property set to true.
Throughout the development of your composite application, you may have to create additional regions and region adapters, such as one that will adapt a control from a third-party vendor. Once that is done, add code similar to the following:.
The common way to do this in a CAL application is to have the dependency injection container inject the RegionManager into the constructor of the class that needs it.
To add a view or model to a region, simply call the region's Add method. When you add a view, you can pass an optional name:.
You can later use that name to retrieve the view from the region by using the region's GetView method. By default, there is only one RegionManager instance in your application, thereby making every region globally scoped.
This addresses a wide set of scenarios, but there are situations where you may want to define a region that exists only at a particular scope. An example of where you might want to do this is when your application has a view for employee details where multiple instances of the view can be displayed at the same time.
If these views are fairly complex, they behave like mini-shells or CompositeViews. In these cases, you may want each view to have its own regions, as the shell does. The CAL allows you to define a local RegionManager for a view so that any regions defined within it or its child views are automatically registered in that local region.
The UI Composition quickstart included with the guidance illustrates this employee scenario see Figure 7. In the quickstart there is an employee list. As you click on each employee, you see the associated employee detail. For each employee selection, a new EmployeeDetailsView is created for that employee and added to the DetailsRegion see Figure 8.
The region is rendered as a TabControl and contains both static and dynamic content. The Current Projects tab, however, has its views injected. You can see in the code that a new RegionManager instance is returned from the detailsRegion.
Add method. Also notice that I am using the overload of Add that passes in a name for the view and sets the createRegionManagerScope parameter to true. Doing this creates a local RegionManager instance that will be used for any regions defined in the children. Using local regions provides an additional benefit even if you are not using instance regions.
You can use them for defining a top-level boundary so that a module does not automatically expose its regions to the rest of the world. To do this, all you need is to add the top-level view for that module into a region and specify for it to have its own scope. Once you do that, you've effectively shielded that module's regions from the rest of the world. It's not impossible to access them, but it's much more difficult.
Without views you would have no need for a composite. Views are the single most important element that you will build within your composite apps, as they are the gateway for your users to the world of functionality that your application provides. Views are typically the screens of your application.
Views can contain other views, thereby becoming composite views. Another use of views is for menus and toolbars. In Windows Forms you were basically restricted to using controls as your visual representation. In WPF, this model is still supported and you can create custom user controls for representing your different screens. If you look throughout the Stock Trader application, this is the primary mechanism employed for defining views.
Another approach is to use models. Templates are rendered recursively, meaning that if a template renders an element that binds to a property of the model, that property will be rendered using a template if it is available. For an example of how this works, let's take a look at the following code sample.
This sample implements the same UI as the Composition quickstart but uses models and DataTemplates entirely. There is not one user control in the entire project. Figure 9 illustrates how the EmployeeDetailsView is handled. The view is now a set of three DataTemplates that have been defined in a ResourceDictionary.
Its template declares that it should be rendered as a TabControl. This collection is populated with two pieces of information when the Employee details are constructed:. A separate tab will be rendered for each item in the collection. The HeaderedEmployeeData model contains the employee name and contact info. Its associated template renders the model as a series of labels for displaying the information.
The second item will get rendered using the template specified for EmployeeAddressMapUrl, which in this case will render a frame that contains a Web page with a map of where the employee lives.
This is quite a paradigm shift in that it means that the view as you previously knew it only really exists at run time through the combination of the model and its associated template. You can also implement a hybrid of both approaches as demonstrated in the Stock Trader , where you have user controls that have controls within them that are then bound to models that are rendered through templates.
Earlier in this article I mentioned that one of the benefits of building a composite is that it allows the code to be more maintainable and testable. There are several established presentation patterns you can apply within your views to achieve this.
The Presentation Model pattern assumes a model that contains both the behavior and the data for the UI. The view then projects the presentation model's state "onto the glass. Behind the scenes the model interacts with business and domain models. The model also includes additional state information such as the selected item or whether an element is checked.
The view then binds to the Presentation Model directly and renders it see Figure The rich support in WPF for data binding, templates, and commands makes the Presentation Model pattern an attractive option for development. The Stock Trader application uses Presentation Model judiciously, such as in the position summary:. This interface allows the view to be mocked in unit testing. These items are bound to the PostionSummaryView and rendered.
Within the Supervising Controller pattern there exists the model, the view, and the presenter; this is illustrated in Figure The model is the data; it is more often than not a business object. The view is a UIElement to which the model directly binds. And lastly, the presenter is a class that contains the UI logic. In this pattern, the view contains very little logic other than delegating to the presenter and responding to callbacks from the presenter to perform simple actions including either displaying or hiding a control.
The Supervising Controller pattern is also used in a few instances in the Stock Trader app in favor of Presentation Model. One example is the trend line see Figure The Presenter exposes an OnTickerSymbolSelected method that the view invokes through its delegation logic.
In that method, note that the presenter then calls back to the view, invoking its UpdateLineChart and SetChartTitle methods. One of the challenges that arise when implementing separated presentation is the communication between the view and the presentation model or presenter.
There are several approaches to handling this. One that is often implemented is having event handlers in the view that either directly call or raise events to the presentation model or presenter. The same UIElements that initiate calls to the presenter often have to be enabled or disabled in the UI based on state changes or permissions.
This requires the view to have methods that can be used to call it back in order to disable those elements. Another approach is to use WPF commands. But when an enterprise application needs to be developed, then UI interaction operations are not only limited to these controls.
Most of the times we need to provide code-less UI interaction facilities for controls like ListBox, ComboBox for Master-details operations or in some cases, we even need to provide code-less direct UI interaction facilities for DataGrid controls. So the question arises - can we define a Custom Command or Command Parameter behavior to these controls? The answer is YES! In this article, I have explained the same and demonstrated it using the ListBox control.
You can do the same for other controls too. You need to have VS, Silverlight 4. In this project, add the following references of the Prism 4 libraries. You need to also add a reference to System. This time we define data-classes for the application. This file will be used to define custom behavior class for the ListBox. In the constructor of this class, you need to add the following code:. Step 4: Now we need to define the Command property, CommandParameter property and the ClickCommandBehavior property for the class defined above.
The class is as shown below:. The above class defines attached properties and also defines the following methods:. Step 5: Now we need to build the DelegateCommand for the custom command defined above. This class will call methods from the DataClasses defined in Step 2 and provide command objects to the UI.
The code is as shown below:. Step 6: Open MainPage. These properties can be set as shown below:. Step 7: Run the application and the following result will be displayed:. Prism provides an implementation of a collection of design patterns that are helpful in writing well-structured and maintainable XAML applications, including MVVM, dependency injection, commands, EventAggregator, and others.
Prism's core functionality is a shared code base in a Cross Compiled. NET Standard and. NET 4.
0コメント