Monday 9 September 2013

ControlTemplate in WPF

WPF controls are logically divided into their Appearance and Functionality.

Appearance defines look and feel of the control. Each WPF control has default control template that defines its appearance.

Functionality of the control is defined using methods, events and so on. Simple example of functionality is click event of button control.

Hence appearance of control can be customized by creating new ControlTemplate for control without affecting the functionality of the control.

In this post, we would customize Button control by creating a new ControlTemplate.

Let’s start by adding a simple Button control.

XAML

<Button Width="100" Height="100" FontSize="16" Content="Home" Name="btnHome" Click="btnHome_Click"></Button>

Code behind

private void Button_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Home Button Clicked");
}

Output



What we see above is the output of default button control template.


 


Creating Inline ControlTemplate


Now we create an inline control template for Button control to change its appearance to circle.


XAML

<Button Width="100" Height="100" FontSize="16" Content="Home" Name="btnHome" Click="btnHome_Click">
<Button.Template>
<ControlTemplate>
<Grid>
<Ellipse Fill="LightBlue" Stroke="Blue"></Ellipse>
<TextBlock Text="Home" HorizontalAlignment="Center" VerticalAlignment="Center"></TextBlock>
</Grid>
</ControlTemplate>
</Button.Template>
</Button>

Output


 


Important points are highlighted in yellow color in above code. Every Control has a Template property that is used to assign new control template to control. ControlTemplate is the class to create control template. Inside ControlTemplate, we have added a grid layout control with ellipse  and TextBlock containing text.


 


ControlTemplate defined as a resource


ControlTemplate created in above code is inline and hence applies to single button. To apply same template to multiple button controls, modify the code as below.


XAML

<Window x:Class="ControlTemplateSample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="300" Width="300">
<Window.Resources>
<ControlTemplate x:Key="EllipseButton" TargetType="{x:Type Button}">
<Grid>
<Ellipse Fill="{TemplateBinding Property=Background}" Stroke="{TemplateBinding Property=BorderBrush}"></Ellipse>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"></ContentPresenter>
</Grid>
</ControlTemplate>
</Window.Resources>
<StackPanel>
<Button Width="100" Height="100" FontSize="16" Content="Home" Name="btnHome" Margin="10" Click="btnHome_Click" Template ="{StaticResource ResourceKey=EllipseButton}" Background ="LightBlue" BorderBrush ="Blue">
</Button>
<Button Width="100" Height="100" FontSize="16" Content="About us" Name="btnAboutus" Margin="10" Click="btnAboutus_Click" Template ="{StaticResource ResourceKey=EllipseButton}" Background ="LightGreen" BorderBrush ="Green">
</Button>
</StackPanel>
</Window>

Output



What we have done here is added new ControlTemplate as a resource in resource dictionary, set its TargetType to Button and provide a unique key to the ControlTemplate. Then we apply new ControlTemplate to multiple button controls using Template property and StaticResource markup  extension.


 


TemplateBinding and ContentPresenter


If you have noticed same ControlTemplate is applied to both button controls, but their content, ellipse background and border color are different. If these values were set directly inside ControlTemplate, then they would have been same for all button controls which is not desired. Instead these values are actually derived from parent control to which template is applied. This is achieved using TemplateBinding.


TemplateBinding is a DataBinding Markup Extension that binds a property of a control inside ControlTemplate to the property of a templated control (Control to which this ControlTemplate is applied). This makes ControlTemplate flexible and reusable at different places.


TemplateBinding requires TargetType to be specified in ControlTemplate. TargetType=”{x:Type Button}” means this ControlTemplate is for Button control. If not specified, default TargetType is “Control” element which is base class for all WPF control.


If we do not specify TargetType and if we bind any property that is not present in “Control” class then compiler will throw error.


Ex: Consider below TextBlock added inside ControlTemplate

<TextBlock Text="{TemplateBinding Property=Content}"></TextBlock>

Here we bind Text property of TextBlock to Content property of templated control. If TargetType is not specified on ControlTemplate, then compiler takes default “TargetType” as Control. Now Content property is used in TemplateBinding but not present in Control class so Compiler with throw compile time error saying: “Cannot find the static member 'ContentProperty' on the type 'Control”.


ContentPresenter is the place holder for the content property of element and will be replaced by the actual content from the templated parent control at run time. ContentPresenter internally uses TemplateBinding and requires TargetType to be set. If we remove TargetType from ControlTemplate, then compile will not throw error but at runtime content would not be displayed. This is the mistake that sometimes people make and finds it difficult to debug.


Different between TemplateBinding & ContentPresenter


TemplateBinding is a DataBinding Markup Extension that can be used to bind any property of a control inside ControlTemplate to template control property of same type. While ContentPresenter is actually a Place Holder for Content Property of template control.


 


 Triggers


After creating a new ControlTemplate and running the application, we noticed that when we move mouse over the Button, there is no effect. Default button control template changes button background with some sort of blue gradient. Trigger would be useful to achieve this. ControlTemplate allows defining Trigger that can be used to change appearance of controls based on some user interaction.


XAML

<ControlTemplate x:Key="EllipseButton" TargetType="{x:Type Button}">
<Grid>
<Ellipse Name="ellipse" Fill="{TemplateBinding Property=Background}" Stroke="{TemplateBinding Property=BorderBrush}"></Ellipse>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"></ContentPresenter>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property ="IsMouseOver" Value ="True">
<Setter TargetName ="ellipse" Property ="Fill" Value ="Goldenrod"></Setter>
<Setter TargetName ="ellipse" Property ="Stroke" Value ="Brown"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>

Output



Here we have given name to ellipse control so that ellipse can be used in Trigger section. When user moves mouse over Button control, we set Fill and stroke property of ellipse control to different values.


 


Additional information


While understanding TemplateBinding and ContentPresenter I explored 2 other ways in which we can derive values from parent/templated control. So I am mentioning them here. This is just for sake of knowledge and understanding. Mainly prefer to use TemplateBinding and ContentPresenter inside ControlTemplate.


Consider a TextBlock inside ControlTemplate. Text property of this TextBlock control should be derived from Content property of templated control. We can use RelativeResource DataBinding.



1.  RelativeResource - RelativeResource is a DataBinding markup extension that is used to reference a resource/control that is positioned relatively to current control.


<TextBlock Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}, Path=Content}"></TextBlock>


In above code, Binding will search for Ancestor control of Type Button up in the hierarchy and set the value of Content property of Button control to Text property of TextBlock control.


This syntax is not specific to templates. This is generic way of finding any control up in the hierarchy and binding its properties. Below is more template specific syntax.


2. TemplatedParent - RelativeResource provides Mode property which can be set to TemplatedParent. This means search for parent control to which this template is applied.

<TextBlock Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Content}"></TextBlock>


TemplateBinding can be thought as an optimization to above TemplatedParent syntax and provides easier, better and preferred way of binding property of parent control.

Sunday 1 September 2013

C# Delegates Series Part 4 - Delegates can be used to Invoke methods asynchronously

Below is the reference of all posts in this series

  1. C# Delegates Series Part 1 - Overview
  2. C# Delegates Series Part 2 - Delegates allows methods to be passed as parameters
  3. C# Delegates Series Part 3 - Delegates can be used to define event handlers and event handling mechanism
  4. C# Delegates Series Part 4 - Delegates can be used to Invoke methods asynchronously

When Main UI thread invokes some method, main thread waits until that method completes and then continues with rest of the processing. This might turn out expensive in some scenarios where called method takes more time to execute or communicates with third party service or downloads a large file. This would make application less responsive. In such cases, delegates can be useful to call these methods asynchronously.

Note: BackgroundWorker class in C# is another powerful way to execute code asynchronously. BackgroundWorker also supports reporting progress, cancelling the thread and so on.

There are 4 different ways to invoke methods asynchronously using delegates with some variations.

1.   Call a Method Asynchronously using Delegate BeginInvoke and EndInvoke: In this approach, main thread will invoke other method using delegate BeginInvoke method. BeginInvoke initiates asynchronous call on separate thread and returns immediately so that main thread can continue with rest of the processing. Main thread can later call EndInvoke method to end the thread and return the result. If main thread has call EndInvoke and if method has not completed the execution, then main thread will wait for method to complete.

2.   Call a Method Asynchronously using WaitHandle: In this approach, the main thread will invoke other method using delegate BeginInvoke method, waits for a WaitHandle and then call EndInvoke().

3.   Call a Method Asynchronously in .NET using Polling: In this approach, Main thread will invoke other method using delegate BeginInvoke, continue with rest of the processing and periodically poll other thread/method (using IAsyncResult IsCompleted property) to check if method has completed the execution. During polling, if main thread finds that method has completed the execution (IsCompleted = true), delegate EndInvoke will be used to end the thread and return the result from method.

4.   Call a Method Asynchronously in .NET using Callback: In this approach, main thread will invoke other method using delegate BeginInvoke along with callback method passed as parameter and continue with rest processing. When other method completes the execution, it invokes callback method which is passed as delegate reference. This callback method will then call delegate EndInvoke to end the thread and return the result from method.

MSDN article provides a good description of these approaches along with examples.

C# Delegates Series Part 1 - Overview

At times, I have come across people who understand some basics of delegates but are really confused on when should they use delegates and how delegates are useful. During course of my development, I came across several scenarios where delegates were quite useful in achieving the desired functionality. So here is a series of delegates that would help you understand basic concepts of delegates and some scenarios  where delegates are useful.

  1. C# Delegates Series Part 1 - Overview
  2. C# Delegates Series Part 2 - Delegates allows methods to be passed as parameters
  3. C# Delegates Series Part 3 - Delegates can be used to define event handlers and event handling mechanism
  4. C# Delegates Series Part 4 - Delegates can be used to Invoke methods asynchronously

 

Let’s start with Overview of delegates

Delegates are similar to function pointers in C, C++. Delegates holds reference to function/method of same signature. When delegates are invoked, they in-turn invoke the function that is referenced. At first glance, it might seem difficult to understand why we need delegate and why can’t we call functions directly. Thinking of single class/file, it might not make much sense. But delegates starts getting useful when they span across multiple classes, multiple components, implementing event handles, callbacks, invoking functions asynchronously and so on. Don’t worry we would understands these scenarios in details as the article follows.

Let’s first understand steps involved in creating and using a simple delegate.

1.  Declaring delegate: A Delegate is a type that define method signature.

public delegate int MathDelegate(int a, int b);


2.  Creating method: Method that should be invoked when delegate is used.

public int Add(int a, int b)
{
return a + b;
}

public int Subtract(int num1, int num2)
{
return num1 - num2;
}

Here we define 2 methods that have same signature as delegate (return type, number of parameters and type of parameters).


Simply remove delegate keyword in step - 1 and replace MathDelegate with Add and this becomes our Add method signature.


It is not compulsory to match names of parameters. Check Subtract method where I have changed parameter name a with num1 and parameter name b with num2.


3.  Instantiate delegate: Create an instance of delegate and pass the function as parameter.

MathDelegate addDelegate = new MathDelegate(Add);
MathDelegate subtractDelegate = new MathDelegate(Subtract);

4.  Use delegate:

int result = addDelegate(10, 5);
MessageBox.Show(result.ToString());

result = subtractDelegate(10, 5);
MessageBox.Show(result.ToString());


Here, calling the delegate would invoke function that is referenced and return the result.



Now as we know what a delegate means, let’s understand some facts and real examples of delegate in next sequence of articles.

C# Delegates Series Part 3 - Delegates can be used to define event handlers and provide event handling mechanism

Below is the reference of all posts in this series

  1. C# Delegates Series Part 1 - Overview
  2. C# Delegates Series Part 2 - Delegates allows methods to be passed as parameters
  3. C# Delegates Series Part 3 - Delegates can be used to define event handlers and event handling mechanism
  4. C# Delegates Series Part 4 - Delegates can be used to Invoke methods asynchronously

Delegates are the base for Event handling mechanism in .net framework. Consider an example of Button Click event. Let’s see below code.

C# - Windows Forms

public Form1()
{
InitializeComponent();
btnSave.Click += btnSave_Click;
}

private void btnSave_Click(object sender, EventArgs e)
{

}

WPF

public MainWindow()
{
InitializeComponent();
btnSave.Click += btnSave_Click;
}

private void btnSave_Click(object sender, RoutedEventArgs e)
{

}

Here Click is the event of Button. btnSave_Click is the event handler/method that will be executed when button is clicked. Above syntax is called wiring event with event handler/method.


Now if we see the definition of button Click event  (Place cursor over Click keyword and Press F12 or right click on Click keyword and select go to definition), we find below code.


C# – Windows forms

public event EventHandler Click;

Drill down further to definition of EventHandler and we see below.

public delegate void EventHandler(object sender, EventArgs e);

So EventHandler is of type delegate that takes 2 arguments and returns nothing. Now if we see our definition of BtnSave method this would match with signature of delegate.


WPF

public event RoutedEventHandler Click;

Drill down further to definition of RoutedEventHandler and we see below.

public delegate void RoutedEventHandler(object sender, RoutedEventArgs e);

So RoutedEventHandler is of type delegate that takes 2 arguments and returns nothing. Now if we see our definition of BtnSave method this would match with signature of delegate.


That’s all about .net framework, now we see a real life example where we would find this useful.


There can be several examples.


Suppose you are designing a Login UserControl that takes login information from User. When user click OK button, you want en event to be fired on parent control (hosting Login UserControl) for further/additional processing.


In this post, we extend an example of our previous post where we created a Form that displays list of Assets. When user selects an Asset and clicks OK button, an event is fired in parent control (control that opened this Assets form) and selected asset information is passed to parent control.


Below is the code to achieve this functionality using delegates and events. In this post, we take an example of WPF application. Download the attached sample for complete example in C# console application, Windows forms and WPF.


Assets.xaml.cs


Assets page will load and displays list of assets in DataGrid. When user selects an asset in DataGrid and clicks OK button, an event should be fired in calling window that invoked Assets window. To achieve this we declare a delegate that can hold reference to method with one argument and returns no value. Then we create an event based on this delegate.

// Declare delegate
public delegate void AssetSelectedEventHandler(AssetItem item);

// Create event based on delegate
public event AssetSelectedEventHandler AssetSelected;

When user clicks OK button, we check if parent control (MainWindow in this case) has subscribed to this event by comparing AssetSelected to null and then we raise the AssetSelected event with argument as selected asset.

private void btnOK_Click(object sender, RoutedEventArgs e)
{
if (AssetSelected != null)
AssetSelected((AssetItem)AssetsGrid.SelectedItem);

this.Close();
}

MainWindow.xaml.cs


This is the main window that is displayed when application is started. In MainWindow, we load Assets.xaml window.

Assets assetSelector = new Assets(FilterMethod);
assetSelector.Owner = this;
assetSelector.AssetSelected += assetSelector_AssetSelected;
assetSelector.ShowDialog();
private void assetSelector_AssetSelected(AssetItem item)
{
// Here we get selected AssetItem information.
}

Code highlighted in yellow shows that “AssetSelected” event defined in Assets.xaml is attached to the event handler “assetSelector_AssetSelected”. Hence when AssetSelected event is raised in Assets.xaml window, assetSelector_AssetSelected event handler is called in MainWindown.xaml

C# Delegates Series Part 2 - Delegates allows methods to be passed as parameters

Below is the reference of all posts in this series

  1. C# Delegates Series Part 1 - Overview
  2. C# Delegates Series Part 2 - Delegates allows methods to be passed as parameters
  3. C# Delegates Series Part 3 - Delegates can be used to define event handlers and event handling mechanism
  4. C# Delegates Series Part 4 - Delegates can be used to Invoke methods asynchronously

In part 1, we understood brief overview of delegates and how to create/use delegates. In this post we will look at how delegates can be used to pass methods as parameters and how would this be useful in real scenario.

We are used to passing properties as parameters to methods in same or different class/forms. But what about passing methods as parameters to other method/class. Is that really useful? If yes, how can we do that? Answer lies below.

Suppose you are asked to develop a component that loads all objects (ex assets) from database and display to user for selection. This component will be reused and called from multiple application.

Now you are asked to design the component to be flexible such that business/filter logic to decide weather an object (asset) to display or not should reside in consuming application (and not in the component) and can vary from application to application.

Ex: One client application can define filter criteria to load only those items (assets) that are of Category "X". Where as other client application can define filter criteria to load only those items (assets) that belong to Location "X". Consuming application should be able to define its own filter criteria without any change required in the component.

Design for creating such component would require that component would fetch all assets from database, and then for each item call some function in consuming application that has filtering logic to check if asset needs to be displayed or not and returns Boolean value. This is one such scenario where delegates can be extremely useful.

Now if you think of methods like FindAll, Select on generic List in C#, this would start making some sense. Internally these methods use delegates.

Let’s take an example of how you would achieve such functionality using delegate. To keep this language neutral, we take 3 simple class and use simple pseudo code. Download the attached sample for complete example in plain C#, Windows forms and WPF.

AssetItem.cs

public class AssetItem
{
public string ID { get; set; }
public string Name { get; set; }
public string Location { get; set; }
public string Category { get; set; }
}

AssetSelector.cs (Component part)

public class AssetSelector
{
// Declaring delegate
public delegate bool FilterDelegate(AssetItem item);

public FilterDelegate FilterMethod;

public AssetSelector(FilterDelegate filterMethod)
{
// Create an instance of delegate and assign client side method passed as parameter.
FilterMethod = new FilterDelegate(filterMethod);
}

public void LoadAssets()
{
// Load all assets from database.
List<AssetItem> Assets = GetAssets();

List<AssetItem> filteredAssets = new List<AssetItem>();
foreach (AssetItem item in Assets)
{
// Using delegate to invoke client side filter method passed as reference.
if (FilterMethod(item))
filteredAssets.Add(item);

}

// Bind data grid with filteredAssets;
}

private static List<AssetItem> GetAssets()
{
List<AssetItem> Assets = new List<AssetItem>();
return Assets;
}
}

Client.cs (Consuming application part)

public class Client
{
public void SelectAssets()
{
AssetSelector selector = new AssetSelector(FilterMethod);

// Pass "FilterMethod" method as parameter.
selector.LoadAssets();
}

// Declare method that matches delegate signature and contains filtering logic.
public bool FilterMethod(AssetItem item)
{
if (item.Category == "Electronics")
return true;
else
return false;
}
}

 


Implementing callbacks with delegates


If you understand the above concept of using delegates, then implementing callbacks would be similar and easy task for you. Steps remains the same.



Parent/Client class would create a CallbackMethod and pass this method as an argument when calling the component/another class.


Component class would create the delegate with same method signature, store the reference of CallbackMethod in delegate and task is completed use the delegate to invoke CallbackMethod.


Callback makes more sense when you are designing a component that performs a some task asynchronously or uses API/third party service that provides response asynchronously. In this case client application would call the component to perform the task and continue with other operations instead of waiting for the component to return the result. This makes client application responsive. Once component has completed the task, component use the delegate to provide callback to the client application.