Introduction
When we work in WPF we have the option of creating reusable UI control. In this article we will see what is reusable UI and how can we use them or create them. And also some of the advantages we get from this.
What is Reusable UI?
In a short description we can say that whenever we reuse a certain UI control in our view or page then we can say that we are using Reusable UI. That means reuses of resources, templates, custom elements, custom controls.
Ways of creating Reusable UI.
Basically there are five ways of creating or using Reusable UI. They are
- Resource reuse
- Template reuse
- XAML reuse
- Custom elements
- Custom controls
In this article we will see the first two way of doing it. We will see rest of the item in next article.
Resource reuse:
The easy and simple way of making UI Reusable is using the resource system though it has limited value. Simply because this is not suitable for framework element. The idea behind is to use any UI resource declared as static resource. Let's see how we can do this..
<Window.Resources>
<TextBlock x:Key="SharedTB" Text="Hello"/>
<Button x:Key="SharedBT" Content="Hi"/>
</Window.Resources>
<StackPanel VerticalAlignment="Center">
<StaticResource ResourceKey="SharedTB"/>
<StaticResource ResourceKey="SharedBT"/>
<StaticResource ResourceKey="SharedTB"/>
<StaticResource ResourceKey="SharedBT"/>
</StackPanel>
In the above example we can see that we have declared a TextBlock
and Button in between Windows Resources. And we used both of them more than once in our StackPanel
. Now whenever we will run this code we can see that we get a XamlParseException error. Now why is that? If we check the declaration of resources we can see that both the UI control only defines content or text property. And both of them are framework element. By default the resource system makes each resource reference to the same underlying object. That's why we get an error whenever we are trying to use a resource more than once.
This way is good in those reusing scenarios where we can share the object instance itself. So this way is good for freezable elements like Animation, Brushes, Drawing, etc. But for framework element this is not the right way. Although there is an alternate way of doing the same thing for framework element. And for that all we have to do is to set the following attribute in our resource declaration.
x:Shared = "False"
So the above code should look like this:
<Window.Resources>
<TextBlock x:Key="SharedTB" x:Shared="False" Text="Hello"/>
<Button x:Key="SharedBT" x:Shared="False" Content="Hi" Click="Button_Click"/>
</Window.Resources>
<StackPanel VerticalAlignment="Center">
<StaticResource ResourceKey="SharedTB"/>
<StaticResource ResourceKey="SharedBT"/>
<StaticResource ResourceKey="SharedTB"/>
<StaticResource ResourceKey="SharedBT"/>
</StackPanel>
Basically what it tells is that whenever a reference of this resource is requested, the resource management system will not share the same instance but will create a new one for each request. This works only on compiled XAML scenario. That's why we can't see the "Shared" option. Now run this XAML and we will see that everything is working fine.
Template reuse:
Another way of making UI Reusable is template reuse. Now there are basically two types of template; Control template and Data template. We can use both templates for this purpose. We use control template to present or customize a particular control and reuse it in our UI. We use data template to present data in different format. Depending on the situation we decide what template to use. There's another thing and that is we can add behavior to our template. For example we can declare event handler to the XAML and this will be hooked up to the function in code behind each time the template is being instantiated. Each time we use a template it generates a new copy of itself. Lets directly go to a example that uses control template.
<StackPanel VerticalAlignment="Center">
<StackPanel.Resources>
<ControlTemplate x:Key="TBox">
<TextBox>
Hello
</TextBox>
</ControlTemplate>
</StackPanel.Resources>
<Control Template="{StaticResource TBox}" Focusable = "False" />
<Control Template="{StaticResource TBox}" Focusable = "False" />
<Control Template="{StaticResource TBox}" Focusable = "False" />
</StackPanel>
In the above example we are declaring a control template where we define a textbox. And then we are using the as a static resource for reusable UI purpose. Check that we have set the Focusable property to False. This is because if we don't do this each text box will have two focus value. It is really not necessary to use control template for the purpose of reusable ui. We can use data template too. It's just how you define your template to do the job. In the below example we will see the same thing using data template.
<StackPanel VerticalAlignment="Center">
<StackPanel.Resources>
<DataTemplate x:Key="TBox">
<TextBox>
Hello
</TextBox>
</DataTemplate>
</StackPanel.Resources>
<ContentPresenter ContentTemplate="{StaticResource TBox}" />
<ContentPresenter ContentTemplate="{StaticResource TBox}" />
<ContentPresenter ContentTemplate="{StaticResource TBox}" />
</StackPanel>
You can see that we have replaced the control template by data template and control by contentpresenter. Now what is Contentpresenter?? In a very short line "It is kind of a place holder for XAML content. It also has the capability to insert content at run time." This is just a small example of how we can do things.