CHAPTER 6
The Prism 4 shell form is the template that defines what the user of your solution sees. It provides layout, dynamic view population with Prism 4 regions and affects the workflow and feel of your solution. The shell form is the container for the solution's visual and business content. It is the first thing that a user sees when using your solution. If first impressions are important, the shell form of your solution is the equivalent of a firm handshake and good eye contact.
Although the shell form is used with Prism 4 solutions it's actually a WPF container control. Being a WPF control it uses some completely different methodologies when it comes to rendering User Interfaces (UI). First Direct X is used to render graphics rather than the older GDI and GDI+ libraries. This means that WPF solutions are able to take advantage of the advanced graphic rendering abilities of today's graphic cards.
It also means that we get a new markup langrage that's much more powerful than previous languages. Extensible Application Markup Language (XAML) is derived from the XML specification. It is an advanced markup language that addresses many of the issues that are associated with older markup languages.
XAML's power comes from the fact that it can perform tasks that were relegated to scripting languages in the older markup languages. XAML releases developers from the necessity of learning both a markup language and scripting language. Features such as data binding, data templates, control templates, data context, advanced layout and other features make XAML an easy to learn and powerful markup language.
Listing 16: The ShellLogoTop XAML Markup.
<Window
x:Class="PRISM4.MAIN.FORMS.ShellLogoTop"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:syncfusion="http://schemas.syncfusion.com/wpf" xmlns:prism="http://www.codeplex.com/prism"
Title="Virtual Calculator 1.0.0" Height="auto" Width="auto" WindowState="Maximized">
<Window.Background> <ImageBrush ImageSource= "/PRISM4.MAIN;component/IMAGES/Calculator.jpg"/> </Window.Background>
<Grid ShowGridLines="false">
<Grid.RowDefinitions>
<RowDefinition Height="auto"> </RowDefinition> <RowDefinition Height="*"> </RowDefinition> </Grid.RowDefinitions>
<Grid.ColumnDefinitions> <ColumnDefinition Width="30*"> </ColumnDefinition>
<ColumnDefinition Width="8*"> </ColumnDefinition> <ColumnDefinition Width="62*"> </ColumnDefinition> </Grid.ColumnDefinitions>
<Grid Name="HeaderGrid" Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2" Margin="0,10,10,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"> </ColumnDefinition> <ColumnDefinition Width="*"> </ColumnDefinition>
</Grid.ColumnDefinitions>
<ContentControl Name="CompanyLogo" Grid.Row="0" Grid.Column="0" Margin="0" HorizontalAlignment="Left" prism:RegionManager.RegionName="CompanyRegion"> </ContentControl> <ContentControl Name="ApplicationLogo" Grid.Row="0" Grid.Column="1" Margin="0" prism:RegionManager.RegionName="ApplicationRegion"> </ContentControl>
</Grid>
<Border BorderBrush="Red" BorderThickness="5" CornerRadius="5" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" Margin="0,10,20,30" Opacity="0.7" HorizontalAlignment="Stretch">
<Border.Background> <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> <GradientStop Color="LightSteelBlue" Offset="0"/> <GradientStop Color="LightSteelBlue" Offset="1"/> <GradientStop Color="White" Offset="0.535"/> </LinearGradientBrush> </Border.Background>
<syncfusion:TabControlExt Name="MathControl" CloseButtonType="Hide" prism:RegionManager.RegionName="MathRegion" IsSynchronizedWithCurrentItem="True" SelectOnCreatingNewItem="False"> </syncfusion:TabControlExt> </Border> </Grid>
</Window> |
Let's take a look at this Markup.
One of XAML's virtues is the ability to easily associate class libraries to the XAML markup. This is done with namespaces. Namespaces are added by first setting a project reference to the DLL that is needed. Next a name space is created in the XAML markup that references the correct library.
Listing 17: Example of the Prism 4 XAML Namespace.
xmlns:prism="http://www.codeplex.com/prism |
Listing 17 shows an example of the Prism 4 namespace in the in the ShellLogoTop form in the Virtual Calculator.
The Virtual Calculator solution uses a Syncfusion Tab control in the Math project. The syncfusion namespace provides the library that is needed to use this control in XAML.
Listing 18: Example of the Syncfusion XAML namespace.
xmlns:syncfusion="http://schemas.syncfusion.com/wpf" |
Listing 18 shows an example of the markup needed to create the syncfusion namespace.
The Virtual Calculator solution also needs to create a namespace for the Prism 4 library. Listing 17 shows an example of this namespace.
Content controls are controls that show single views. When a new view is added to a content control, the previous view is replaced with the new one. Two content controls are used in the Virtual Calculator shell forms. The first control provides a Prism 4 region that is populated by the company logo view. The second control provides a Prism 4 region that is populated by the application logo view.
Listing 19: The CompanyLogo Content Control.
<ContentControl Name="CompanyLogo" Grid.Row="0" Grid.Column="0" Margin="0" HorizontalAlignment="Left" prism:RegionManager.RegionName="CompanyRegion"> </ContentControl> |
How is a regular control converted to a Prism 4 region? The RegionManager.RegionName attached property is used to identify a user control as a Prism 4 region. Listing 19 shows an example of the markup that identifies the CompanyLogo content control with the region name of "CompanyRegion". When we look at Prism 4 modules in chapter 9, we'll see how Prism 4 uses the region name to populate regions with views.
Note: The reason why we can use the Prism 4 RegionManager.RegionName attached property, is because we added the prism namespace to the Window. Without this namespace there would be no access to the property.
The Syncfusion:TabControlExt Tag:
The Syncfusion tab control is used as the view for the Math module in the Virtual Calculator solution. This type of control is a selector control. Unlike the content control, selector controls allow for multiple views to be shown in a single control. The Syncfusion tab control in the Virtual Calculator solution has two tabs, an add two integers and subtract two integers tab. Each of these tabs are separate views that are injected into the MathRegion region at runtime.
Listing 20: The MathControl Tab Control.
<syncfusion:TabControlExt Name="MathControl" CloseButtonType="Hide" prism:RegionManager.RegionName="MathRegion" IsSynchronizedWithCurrentItem="True" SelectOnCreatingNewItem="False"> </syncfusion:TabControlExt> |
This control also uses the RegionManager.RegionName attached property to convert the control to a Prism 4 region. Listing 20 shows an example of the markup that identifies the MathControl tab control with the region name of "MathRegion".
In the case of the Syncfusion tab control, we have to do a bit of work to have the control integrate correctly with Prism 4. In chapter 8, "Prism 4 Regions", we'll look at region adapters. These classes are used with third party controls to adapt them for integration with Prism 4.
Note: Adding the RegionManager.RegionName property to the tab control without a region adapter class for the Syncfusion tab control will result in an exception. We'll talk about what region adapters do and how to use them in chapter 8.
Tip: The reason that we don't need a region adapter for the content control, is because Microsoft controls already have them. Only third party controls need region adapters.
XAML Element And Data Binding:
Unlike other markup languages, XAML provides built in data binding services. This allows the view to bind to public view model properties that are exposed though the view's data context. It is also possible to bind between the user control properties of different controls in the view this is called element binding.
Listing 21 shows an example of data binding between in the AddTwoView view and the AddTwoViewModel TabHeaderText view model property.
Listing 21: Binding to a Tab's Header Property with XAML Data Binding.
... Header="{Binding Path=TabHeaderText}" ... |
The ability to bind between controls and to bind between the view and view model are powerful features of the XAML markup language. We'll look closer at data binding and other XAML constructs when we look at MVVM in chapter 7.
The View's Data Context Property:
At this point you may be wondering how the view accesses the view model properties. The view's data context property provides this functionally. When the data context of a view is set to a view model class, all of the public properties in that class are exposed to the view.
The INotifyPropertyChanged interface is also exposed though the view model. This interface is used to insure that the view is updated when changes are made to the view model properties. We'll talk in greater detail about INotifyPropertyChanged when we look at the view model in chapter 7.
Views can be associated with view models in two ways, with XAML markup or with C# code in the view's code behind file. Listing 22 shows data context code in the code behind file.
Listing 22: Setting A view's Data Context with Code Behind.
public partial class AddTwoView : TabItemExt { private AddTwoViewModel ViewModel; public AddTwoView(AddTwoViewModel ViewModel) { InitializeComponent(); if (ViewModel != null) { this.ViewModel = ViewModel; }
this.DataContext = this.ViewModel; } } |
Notice that constructor injection is used to instantiate the view model. A guard clause is then used to make sure that a non null view model object is available for use. The view model argument is assigned to a local member if it is not null.
The data context property of the view is then set to the local view model member.
The other option is to use XAML markup to set the view model. Listing 23 shows an example of using this option.
Listing 23: Setting A view's Data Context with XAML.
<syncfusion:TabItemExt.DataContext> <vm:AddTwoViewModel> </vm:AddTwoViewModel> </syncfusion:TabItemExt.DataContext> |
The markup in Listing 23 can be added to the syncfusion:TabItemExt control directly.
In this chapter we learned that the shell form is the first thing that users see. Without the shell form it would be difficult or impossible to provide user interaction with Prism 4 solutions. The shell form provides a method of dynamic user interface construction as the solution starts and during its lifetime. This allows for loose coupling between the shell form and the views that populate it.
We also learned that XAML is a powerful and versatile markup language. It is used to render user interfaces and to provide a means of connecting the UI elements to the business rules though the view model. As we progress further into WPF and the Prism 4 framework, we'll learn about some of the other features of this markup language.
But at this time let's look at another aspect of well designed solution architectures, the Model View - View Model design pattern.