Showing posts with label Markup Extension. Show all posts
Showing posts with label Markup Extension. Show all posts

Saturday, 4 May 2013

Markup Extension in WPF

Download Code – Sample containing all Markup Extensions

Markup Extension is very useful and handy feature in XAML.

Instead of directly specifying string values for properties in XAML, Markup extension can be used to provide values to properties that can be retrieved from different sources.

Let’s take a simple example of setting Background color of TextBlock.

Directly specify string value for Background property

<TextBlock Background="LightBlue"></TextBlock>

Using Markup Extension


We will use StaticResource Markup Extension to set Background property value. StaticResource means referring to a resource defined in XAML. So we define a resource for LightBlue color.

<Window.Resources>
<SolidColorBrush x:Key="LightBlueColor" Color="LightBlue"></SolidColorBrush>
</Window.Resources>

Now, Markup Extension can be set using Attribute syntax or Property Element Syntax.


Attribute syntax: This syntax is used in most of the cases when using Markup Extension. Syntax uses opening and closing curly braces ( { } ). Type of Markup Extension to be used is identified through string immediately after opening curly braces.

<TextBlock Background="{StaticResource ResourceKey=LightBlueColor}"></TextBlock>

Here, StaticResource string after opening curly braces indicates XAML parser to use StaticResource Markup Extension. StaticResource has a ResourceKey property which should be set to the key value of resource to be used. StaticResource extension would internally use this ResourceKey to lookup and return the resource.


Property Element syntax: Syntax is similar to using any other element using angle brackets ( <> )

<TextBlock>
<TextBlock.Background>
<StaticResource ResourceKey="LightBlueColor"></StaticResource>
</TextBlock.Background>
</TextBlock>

You might not get StaticResource in intellisense when using property Element syntax but it compiles and works fine.


Markup Extension is simple and easy to use but adds lots of power and flexibility to programming language. Once you start exploring different built-in Markup Extension provided in WPF you will start realizing that.


Types of Markup Extension


WPF provides several built-in Markup extensions which can be broadly classified into 2 categories.



XAML Defined - Markup Extension that are defined as an intrinsic feature of XAML as a language. Note: XAML language is also used for creating UI in other platforms like Silverlight, Windows Phone, Windows 8 etc. These extension are present in XAML namespace and accessed using default “x:” prefix.


WPF Specific - Markup Extension that are specific to WPF.


Below chart provides a quick overview of different Markup Extensions and their short description.


WPF MarkupExtension


I have added all Markup Extensions in sample attached at the top of this post. I have also posted code snippets in separate post here.


Here is a nice MSDN link which has links to different Markup Extension.


In next post, we will look at creating custom Markup Extension.

WPF Markup Extension Sample Code Snippets

In last post, we have seen an brief overview of Markup Extension and different types of Markup Extensions.

I thought it would be useful to create a sample that uses all Markup Extensions. You can download the sample: Download Code – Sample containing all Markup Extensions

Also I am posting code snippets for all Markup Extension for quick reference.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WPFMarkupExtension
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private string simpleText = "Text set using Binding Markup Extension";
public string SimpleText
{
get { return simpleText; }
set { simpleText = value; }
}

private string firstName = "Text set using";
public string FirstName
{
get { return firstName; }
set { firstName = value; }
}

private string lastName = "MultiBinding Markup Extension";
public string LastName
{
get { return lastName; }
set { lastName = value; }
}

//private string bindingValue1 = "first binding";
//public string BindingValue1
//{
// get
// {
// throw new ApplicationException();
// return bindingValue1;
// }
//}

private string bindingValue2 = "Second binding returned value successfully";
public string BindingValue2
{
get { return bindingValue2; }
set { bindingValue2 = value; }
}

public static string StaticField = "Text set using Static Markup Extension";

public MainWindow()
{
InitializeComponent();
}
}
}

 

<Window x:Class="WPFMarkupExtension.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPFMarkupExtension"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="MainWindow" Height="600" Width="600">
<Window.Resources>
<SolidColorBrush x:Key="LightBlueColor" Color="LightBlue"></SolidColorBrush>
<local:MyConverter x:Key="myConverter"></local:MyConverter>

<!--Usage of x:Array Marukup Extension-->
<x:ArrayExtension x:Key="fruits" Type="sys:String">
<sys:String>Apple</sys:String>
<sys:String>Orage</sys:String>
<sys:String>Mango</sys:String>
<sys:String>Banana</sys:String>
</x:ArrayExtension>

<!--Usage of x:Type Maukup Extension-->
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Margin" Value="5"></Setter>
<Setter Property="Padding" Value="5"></Setter>
</Style>

<!--Usage of TemplateBinding Markup Extension-->
<ControlTemplate x:Key="EllipseButton" TargetType="{x:Type Button}">
<Grid>
<!--TemplateBinding is used to set property of control in ControlTemplate to property of
parent control to which this template is applied.-->
<!--Instead of specifying hard code value for Fill property, we inherit property from
parent control. This adds flexibility to template.-->
<Ellipse Fill="{TemplateBinding Background}"></Ellipse>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"></ContentPresenter>
</Grid>
</ControlTemplate>
</Window.Resources>
<StackPanel>

<GroupBox Header="XAML Defined">
<StackPanel>
<!--Usage of x:Null Markup Extension-->
<!--Style defined for TextBlock in Window.Resources section applies to all TextBlock.
We want this particular TextBlock not to use that style. So we set Style to Null-->
<TextBlock Style="{x:Null}" Text="Null Markup extension usage"></TextBlock>

<!--Usage of x:Static Markup Extension-->
<!--local refers to namespace of current project which is imported in Window element at top
MainWindow refers directly to Class (and not instance of Class)
StaticField is static property in MainWindow class-->
<TextBlock Text="{x:Static Member=local:MainWindow.StaticField}"></TextBlock>
</StackPanel>
</GroupBox>

<GroupBox Header="WPF Specific">
<!--Usage of RelativeResource Markup Extension-->
<!--DataContext for StackPanel is set to current window (means code behind).
Hence all controls in this StackPanel will inherit this DataContext as source for binding.-->
<StackPanel DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}">
<TextBlock Background="LightBlue"
Text="Background property set using direct string vlaue"></TextBlock>

<!--Usage of StaticResource Markup Extension (Attribute Syntax) -->
<TextBlock Background="{StaticResource ResourceKey=LightBlueColor}"
Text="Background property set using StaticResource Markup Extension - Attribute Syntax"></TextBlock>

<!--Usage of StaticResource Markup Extension (Property Element Syntax) -->
<TextBlock Text="Background property set using StaticResource Markup Extension - Property Element Syntax">
<TextBlock.Background>
<StaticResource ResourceKey="LightBlueColor"></StaticResource>
</TextBlock.Background>
</TextBlock>

<!--Usage of DynamicResource Markup Extension (Attribute Syntax) -->
<TextBlock Background="{DynamicResource ResourceKey=LightBlueColor}"
Text="Background property set using DynamicResource Markup Extension"></TextBlock>

<!--Usage of Binding Markup Extension (Attribute Syntax) -->
<TextBlock Text="{Binding SimpleText}"></TextBlock>

<!--Usage of Binding Markup Extension (Property Element Syntax) -->
<TextBlock>
<TextBlock.Text>
<Binding Path="SimpleText"></Binding>
</TextBlock.Text>
</TextBlock>

<!--Usage of MultiBinding Markup Extension-->
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} {1}">
<!--StringFormat is can be used for simple string concat/manipulation.
For complex requirements ValueConverter can be used as commented below-->
<!--<MultiBinding Converter="{StaticResource ResourceKey=myConverter}"
StringFormat="{}{0} {1}">-->
<Binding Path="FirstName"></Binding>
<Binding Path="LastName"></Binding>
</MultiBinding>
</TextBlock.Text>
</TextBlock>

<!--Usage of StaticResource Markup Extension-->
<ListBox ItemsSource="{StaticResource ResourceKey=fruits}"></ListBox>

<!--Usage of PriorityBinding Markup Extension-->
<TextBlock HorizontalAlignment="Left">
<TextBlock.Text>
<!--PriorityBinding can be used for sharing same data template with multiple
controls or for showing progress in async operations.-->
<PriorityBinding>
<!-- // First Binding is not present or binding throws exception
or does not return some value then Second Binding is used -->
<Binding Path="BindingValue1"></Binding>
<Binding Path="BindingValue2"></Binding>
</PriorityBinding>
</TextBlock.Text>
</TextBlock>

<!--Usage of TemplateBinding Markup Extension-->
<!--See EllipseButton ControlTemplate-->
<Button Width="150" Height="75" Content="TemplateBinding usage" HorizontalAlignment="Left"
Background="LightBlue" Template="{StaticResource ResourceKey=EllipseButton}">
</Button>
</StackPanel>
</GroupBox>
</StackPanel>
</Window>