XAML stands for Extensible Application Markup Language and pronounced as "zammel”.
XAML is the programming language introduced in .net framework 3.0 to create rich user interface for WPF, Silverlight and Windows Phone applications.
XAML is XML based markup language to instantiate and initialize .net objects
Below diagram provides a simple overview of WPF - XAML
As we can see in above image,
XAML Elements are arranged in hierarchy manner. XAML elements contains other nested elements. This creates Logical Tree of controls in User Interface.
XAML Root Element:
Every XAML document has root/top element. In WPF, Window is the top level element. In Silverlight UserControl is the top level element.
XAML Namespaces:
CLR namespace are imported into XAML using xmlns attribute. Once CLR namespace is imported into XAML, classes of that namespace become available in XAML for use. In WPF, there are 2 standard namespaces that are imported into XAML.
1. http://schemas.microsoft.com/winfx/2006/xaml/presentation is related to core WPF namespace which contains all WPF Classes including WPF Controls that we use to construct User Interface. This namespace is declared without any prefix, marking it as default namespace for the document. Hence we can use all WPF controls in XAML without using any prefix.
2. http://schemas.microsoft.com/winfx/2006/xaml is XAML namespace that defines the XAML keywords. This namespace is declared using prefix “x”. Hence any class in this namespace can be referred using x:ElementName.
XAML Elements:
Every Element in XAML maps to an instance of .net class.
<Button />
<Button /> syntax creates an instance of Button class using parameterless constructor. XAML relies on parameterless constructors to create an instance of class and hence classes that needs to be used in XAML must provide parameterless constructor. With WPF 4.0, it is also possible to pass arguments to constructors.
XAML Attributes:
Attribute of XAML Element maps to properties of .net class.
<Button Content="Home" Width="150" Height="50" Background="LightBlue">
Attributes like Content, Width, Height and Background maps to Button control properties respectively.
Property Element Syntax:
In above example, we have used inline attributes to set properties of a control. Ex: Content = “Home”. Here we set simple string as value for Content property. But what if we wish to assign a complex object to property. Ex: A Button that has Image and Text as Content. This can be done using Property Element Syntax. Each property can be set using element rather than attributes.
<Button Width="150" Height="60">
<Button.Content>
<StackPanel Orientation="Horizontal">
<Image Source="Home.png" Stretch="None"></Image>
<TextBlock Text="Home" VerticalAlignment="Center" Margin="10" FontSize="14" ></TextBlock>
</StackPanel>
</Button.Content>
</Button>
Output
Another example: Create a linear gradient effect for Background property instead of simple Background = “LightBlue”.
<Button Content="Home" Width="150" Height="50">
<Button.Background>
<LinearGradientBrush StartPoint="1, 0" EndPoint="1, 1">
<GradientStop Color="LightSkyBlue" Offset="0"></GradientStop>
<GradientStop Color="White" Offset="1"></GradientStop>
</LinearGradientBrush>
</Button.Background>
</Button>
Output
Implicit Type Converters:
Type Converters as the name suggests would convert value from one type to other and Implicit means that conversion happens in background. WPF has lot of built-in Type Converters. Let’s see below examples to understand where Type Converters are used and how they work.
<Button Content="Home" Width="150" Height="50" Background="LightBlue" Margin="10">
Example: We set Background property of Button control as Background = “LightBlue”. Now if we see Background property declaration in System.Windows.Controls.Control class then we find below.
Quick Tip: Write this.Background in code behind, move the cursor over Background and press F2 or “Go To Definition” which will take you to the property declaration.
public Brush Background { get; set; }
So Background property expects “Brush” object as value and we have assigned simple string to Background property. Here comes Built-In Type Converter that converts “LightBlue” string value to “System.Windows.Media.Brushes.LightBlue”.
Note: “System.Windows.Media.Brushes.LightBlue” is Named brush in WPF which internally returns an instance of SolidColorBrush of Color LightBlue.
Another example: Margin = “10”.
Now if we see Margin property declaration in System.Windows.FrameworkElement class then we find below.
public Thickness Margin { get; set; }
Margin property expects “Thickness” object as value and we assign value as 10. So Built-In type converter converts “10” to something as “new Thickness(10, 10, 10, 10)”.
OK. So how does XAML Parser decide which Type Converter to be used. XAML Parser checks for 2 places to identify Type Converter to be used.
1. Property Declaration: XAML Parser looks at property declaration for TypeConverter attribute. Margin property declaration below does not have have any information of TypeConverter.
public Thickness Margin { get; set; }
2. Class Declaration of related Data Type: If no information found in property declaration, XAML Parser looks at Class Declaration of related Data Type. In case of “Margin” property, data type is Thickness. So let’s check the Thickness class declaration.
[Localizability(LocalizationCategory.None, Readability = Readability.Unreadable)]
[TypeConverter(typeof(ThicknessConverter))]
public struct Thickness : IEquatable<Thickness>
{
// Actual Code. Omitted for simplicity.
}
Here XAML Parser finds TypeConverter attribute with ThicknessConverter as the actual Type Converter to be used.
If no TypeConverter is found and if there is data type mismatch then XAML Parser throws error.
Same way, there are several other built-in converts being used in WPF.
Markup Extensions
Till now we have set hard code values for attributes/properties in XAML. Many times we also need to set property values to an existing object, to some other control properties or set dynamic value. In such scenarios, Markup Extensions are very useful. Markup Extensions are like Placeholders for actual values that are retrieved at run time. Markup Extension are specified between using curly braces { }.
StaticResource Markup Extension example
We have seen an example above where we created linear gradient effect for Background property directly in Button control using Property Element Syntax. We would do that slightly differently.
Add linear gradient effect as an object to resource dictionary
<Window.Resources>
<LinearGradientBrush x:Key="BlueWhiteGradient" StartPoint="1, 0" EndPoint="1, 1">
<GradientStop Color="LightSkyBlue" Offset="0"></GradientStop>
<GradientStop Color="White" Offset="1"></GradientStop>
</LinearGradientBrush>
</Window.Resources>Use linear gradient effect object using StaticResource Markup Extension
<Button Content="Home" Width="150" Height="50" Margin="10" Background="{StaticResource ResourceKey=BlueWhiteGradient}"></Button>So here we used StaticResource Markup Extension to bind Background property of Button control to already defined LinearGradientBrush object.
Binding Markup Extension example
Binding is widely used Markup Extension for Data Binding UI controls to .net object properties. Here is a simple example of binding Text property of TextBox control to Name property of custom employee object.
<TextBox Text="{Binding Path=Name}"></TextBox>There are several different Markup Extension that are used for different purpose. Refer separate post that discuss all Markup Extension in detail.
Attached Properties
Each control provides their own set of properties. Attached properties are those properties which are not provided by the control itself but they are provided by their parent control and are used by child controls to specify their position and behaviors with respect to parent control.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Enter Name:" Margin="10"></TextBlock>
<TextBox Grid.Row="0" Grid.Column="1" Height="30" Margin="5"></TextBox>
</Grid>
In this example, Row and Column property are not provided by TextBlock and TextBox control, but they are provided by Grid control. TextBlock and TextBox control uses Grid.Row and Grid.Column to specify its location in Grid control.
Now after understanding some basics of XAML language, we should be able to co-related advantages of XAML.
Advantages of XAML
- XAML code is lesser, easier to read and understand
- XAML allows organizing controls in hierarchy manner
- XAML provided better separation of concerns by separating User Interface and Application/Business logic. User Interface is created using XAML and programming language like C#, VB.net are used to write code for application functionalities.
- Visual tools like Microsoft Expression Blend are widely used for creating rich UI applications. Microsoft Expression Blend generate XAML code which can be directly used in WPF applications.
- XAML introduced concept of declarative programming with dependency properties and powerful data binding