Radical - UI Composition: concepts
Cool…but what the hell is it?
it is a Window… :-) whose xaml (MainView) is defined as follows:
<Window ...> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Menu ... rg:RegionService.Region="{lrg:MainMenuRegion Name=MainMenuRegion}"> <MenuItem Header="File" rg:RegionService.Region="{lrg:MenuItemRegion Name=FileMenuRegion}"> <MenuItem Header="Sub Item" /> </MenuItem> </Menu> <ContentPresenter ... rg:RegionService.Region="{rg:ContentPresenterRegion Name=SampleContentRegion}" /> </Grid> </Window>
(“…” content removed for clarity)
The UI is really, really simple but defines 3 different regions where content can be injected at runtime.
What does it mean “inject content at runtime”?
First of all let us take a look at what the xaml does: we are using the “Region” attached property, provided by the Radical framework, to attach to standard WPF UI elements 3 different types of region, each one created by a specific markup extension and uniquely identified, within this view, by its name.
Regions
Radical offers some built-in region types:
As you can see from the diagram there are some interfaces, and already built generic abstract classes ready for inheritance, that defines the 3 (well 4…) main region concepts:
IRegion: the IRegion is the mother of all regions carrying the basic information required such as the region name and a reference to the hosting view, its concrete implementation is a markup extension that provides to the inheritors all the plumbing required the WPF; An IRegion, nor a Region<T>, can be directly used as a concrete region, the real regions are the followings:
- IContentRegion: a IContentRegion is a region that is capable of hosting one single content at a time, at runtime the content can be replaced whenever is needed using the Content property, that directly maps to the Content property of the element this region is attached to; An obvious and built-in implementation of this type of region is the ContentPresenterRegion that can be attached to any WPF ContentPresenter;
- IElementsRegion: a IElementsRegion is built to host more than one element, where all the elements are all visible at the same time, basically it is a collection of “region content”, one built-in implementation is the PanelRegion that can be attached to any panel type, but it is really easy to built your own ItemsControlRegion that can be attached to any ItemsControl; in the Radical samples there is a MainMenuRegion and a MenuItemRegion that are built to host MenuItem(s) in the Menu WPF element and in the MenuItem WPF element;
- ISwitchingElementsRegion: a ISwitchingElementsRegion, as its ancestor, is built to host more than one element at a time and adds the concept of active element, that is automatically tracked for changes. A real world sample of this type of region is a TabControlRegion where where runtime region elements will be TabItem(s) that the user can click to activate;
The abstract classes are generic classes ready to be “closed around” the UI element for which we are building the specialized region. Here is the full code required to build a new region type for menus:
public class MainMenuRegion : ElementsRegion<Menu> { public MainMenuRegion() { } public MainMenuRegion( String name ) { this.Name = name; } protected override void OnAdd( System.Windows.DependencyObject view ) { this.Element.Items.Add( ( MenuItem )view ); } protected override void OnRemove( System.Windows.DependencyObject view, RemoveReason reason ) { view.As<MenuItem>( e => { if( this.Element.Items.Contains( e ) ) { this.Element.Items.Remove( e ); } } ); } }
Really, really easy.
In the next post we’ll see how all this stuff can be used to inject content at runtime.
.m