Creating windows and controls
At most times, when we develop an application, it is not possible to fit all the content in just one page. Even if we were able to do so, sometimes it is preferable to divide the content in several parts and group areas by functionality or reusability. On other occasions, we may need other windows, such as modal dialogs, to show other information to the user. Finally, we should not forget that the application may get bigger and we could need more pages for all of its functionality.
UserControl
Let us begin by talking about the most versatile and easiest control to use, UserControl.
It consists of two parts, Interface definition (XAML) and Code (Code-Behind).
In a new Project, the main page inherits from this control.
We can use both to create a form and a user control. When we create user controls, we encapsulate some of the functionality of our application so as to instantiate this control in other places without replicating code.
Let us pose a simple example where we will see how to create a UserControl and instantiate it declaratively (XAML) and from code (Code-Behind). The application will show a form where the user will be able to enter their name and address. The form will be encapsulated in a UserControl, and this will be instantiated by the Page.
Hands on! We will start from a Silverlight blank project (created in the same way we showed in the previous chapter). The name of this new project will be Chapter2.Sample.Forms, as shown in the following screenshot:
- Add a new Views folder, which will help us make the code a little bit tidier. We will add UserControl views (or other pages, if necessary) to this folder.
- In this folder, right-click and choose Add | New Item on the Context menu, as shown in the following screenshot:
- Select the option Silverlight User Control and give it a name (for example, MyControlUCView), as shown in the next screenshot:
- When the UserControl is created, lay out the form that we have defined within the control. To do so, define a Grid layout container and insert the corresponding controls. The final aspect of the layout we want to build is similar to the following screenshot:
- Open the
MyControlUCView.XAML
file and insert the following code:<Grid Margin="10"> <Grid.RowDefinitions> <RowDefinition Height="30"/> <RowDefinition Height="30"/> <RowDefinition Height="30"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="80"/> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <TextBlock Text="Name: " VerticalAlignment="Center"/> <TextBox x:Name="txtName" Grid.Row="0" Grid.Column="1" Width="200" Height="25" HorizontalAlignment="Left"/> <TextBlock Text="Mail Address: " VerticalAlignment="Center" Grid.Row="1" Grid.Column="0"/> <TextBox x:Name="txtAddress" Grid.Row="1" Grid.Column="1" Width="200" Height="25" HorizontalAlignment="Left"/> <TextBlock Text="Country: " VerticalAlignment="Center" Grid.Row="2" Grid.Column="0"/> <ComboBox x:Name="ddlCountry" Grid.Row="2" Grid.Column="1" Width="200" Height="25" HorizontalAlignment="Left"> <ComboBoxItem Content="Spain"/> <ComboBoxItem Content="Germany"/> <ComboBoxItem Content="Italy"/> <ComboBoxItem Content="France"/> <ComboBoxItem Content="EEUU"/> </ComboBox> </Grid>
This is the way the code is instantiated declaratively.
- Open the file
MainPage.XAML
and add the following statements:<UserControl x:Class="Chapter2.Sample.Forms.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:MyControls="clr-namespace:Chapter2.Sample.Forms.Views;assembly=Chapter2.Sample.Forms" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400">
Thereby, a namespace is added, which references the assembly in which the control was created (in our example, the main project one).
If we break down the chain which defines namespace, we can see four parts:
Xmlns
: It indicates that we are adding a namespace: XML NameSpace.Mycontrols
: It is the name which comes after the character ":". It assigns a descriptive name to the namespace, in a way in which we can reference the controls easily.clr-namespace:Chapter2.Sample.Forms.Views
: It indicates the namespace which contains the elements we want available.assembly=Chapter2.Sample.Forms
: This indicates the assembly in which the namespace we are adding is defined. In our example, it is optional that the namespace which we are referring is in the same assembly as the page.
We are ready to instantiate the control. In order to do this, we add the control within the main layout element. The right way is namespace:control
.
<StackPanel x:Name="LayoutRoot" Background="White" Orientation="Vertical" Margin="10" > <MyControls:MyControlUCViewx:Name="myControl"> </MyControls:MyControlUCView> </StackPanel>
When we execute this, we see the control is instantiated.
Before going to the code file, we need to add a button to the page. At the click of this button, we can add a new instance of our UserControl.
To do this, open the MainPage.XAML
file and add the following code, which defines a button in our main layout.
<StackPanel x:Name="LayoutRoot" Background="White" Orientation="Vertical" Margin="10"> <Button x:Name="btnAddUserControl" Content="Add Control" Width="100" Height="30" Click="btnAddUserControl_Click"/> </StackPanel>
When we observe the XAML code which defines the button, we see it specifies a function to manage the action when the user clicks. Instead of copying the code, if we write it manually and we write Click
, Visual Studio brings us the possibility of creating an event handler automatically (we only need to press Tab or Enter once, and the pop-up helper window is displayed) as shown in the following figure:
Now, we can navigate to the implementation of the event handler by right-clicking on the event and choosing Navigate to Event Handler. Let's add few lines of code to create a new instance of the control MyControlUCView
and add it to the object collection in the main layout container:
private void btnAddUserControl_Click(object sender, RoutedEventArgs e) { //Create a new Instance of our User Control MyControlUCView myUC = new MyControlUCView(); //Add the control to the Container of our MainPage LayoutRoot.Children.Add(myUC); }
If we copy the code, the compiler will show an error, as it will not find the definition for MyControlUCView,
because it is located in a different namespace. We must add a reference to it via the using
clause in the following manner:
using Chapter2.Sample.Forms.Views;
When we execute the previous code, we will be able to see how it instantiates and also shows the control when we press the button.
Page control
Page control is a specialization of UserControl. It includes functionality to integrate with the Silverlight Navigation Framework. Since it is a control which inherits from UserControl, it is a container element. We will use this control to create an application with several pages, if we are going to make use of the Navigation Framework.
Page control offers functionality to make use of navigation history, NavigationService (going backwards or forwards in the history), and events where we can control every single state of the navigation process. We will go deeper into these points in this chapter devoted to Navigation Framework.
It is a fundamental control for developing management applications.
To create a new page, click Add New Item and choose the option Silverlight Page, as shown in the following screenshot: