Sunday, September 1, 2013

Introduction to XAML

XAML stands for Extensible Application Markup Language and pronounced as "Zammel", it is a markup language used to instantiate .net Objects and hierarchical relations.
In other words, XAML documents define the arrangement of panels, and controls that make up the windows in a WPF application.

XAML is an all-purpose XML-based syntax for representing a tree of .NET object.(These object could be buttons and text boxes in a window or custom classes you've defined.)

XAML is used to create user interfaces in WPF, Silverlight, declare workflows in WF and for electronic paper in the XPS standard.

All classes in WPF have parameterless constructors and make excessive usage of properties. That is done to make it perfectly fit for XML languages like XAML.

Understand why need XAML?
From a very long ago the group of UI developer realized that the most efficient way to tackle complex, graphically rich application is to separate the graphical portion from the underlying code. so that designer can own the graphics and developers can own the code and both design and code can be design and refined separately.

Advantage of XAML

It is important to understand that WPF doesn't required XAML.All you can do in XAML can also be done in code. XAML ist just another way to create and initialize objects. You can use WPF without using XAML.
Declare your UI in XAML has some advantages:
  •     XAML code is short and clear to read
  •     Separation of designer code and logic
  •     Graphical design tools like Expression Blend require XAML as source.
  •     The separation of XAML and UI logic allows it to clearly separate the roles of designer and developer.

XML Namespace

Suppose you are using any class name in your XAML so as .Net code XAML parser also need to know the .Net namespace where this class is located.

e.g. There is a class XYZ; this could be exist in several places- it might be in the .Net, it might in the third party component or one you have defined in your application.To figure out which class you really want, the XML parser examine the XML namespace that's applied to the element.


At the beginning of every XAML file you need to include two namespaces.
The first is "http://schemas.microsoft.com/winfx/2006/xaml/presentation". It is mapped to all wpf controls in System.Windows.Controls.
The second is "http://schemas.microsoft.com/winfx/2006/xaml" it is mapped to System.Windows.Markup that defines the XAML keywords.

the mapping between an XML namespace and a CLR namespace is done by the XmlnsDefinition attribute at assembly level. You can also directly include a CLR namespace in XAML by using the clr-namespace: prefix.

<Window xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation” xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”>
 </Window>  

The xmlns attribute is a specialized attribute in the world of XML that's reserved for declaring namespace.
The two main namespace
http://schemas.microsoft.com/winfx/2006/xaml/presentation is the core WPF namespace.it include all the WPF classes, including the controls you use to build user interfaces.In the example, this namespace is declared without a namespace prefix, so it becomes the namespace for the entire document.

http://schemas.microsoft.com/winfx/2006/xaml is the XAML namespace. it includes various XAML utility features

XAML vs Code  
 code download
That we can do from code can also be achieve by the XAML, take a example of UI block

           <StackPanel>
                  <TextBox Margin="10" Text="Hello" />
                  <Button Width="50" Height="30" HorizontalAlignment="Right">OK</Button>
          </StackPanel> 
    
 The same in c# code:
   
            StackPanel stackPanel = new StackPanel();
            this.Content = stackPanel;

            TextBox textbox = new TextBox();
            textbox.Margin = new Thickness(10);
            textbox.Text = "Hello";
            stackPanel.Children.Add(textbox);

            Button button = new Button();
            button.Width = 50;
            button.Height = 30;
            button.Content = "OK";
            button.HorizontalAlignment = HorizontalAlignment.Right;
            stackPanel.Children.Add(button);

As you can see is the XAML version much shorter and clearer to read. And that's the power of XAMLs expressiveness.

How to create a dependency property


What is dependency Property? Read my post : Difference between the dependency property and clr-property

Code Example Download
Below are the steps to create dependency property

1) Defining a Dependency Property
2) Registering a Dependency Property
3) Adding a property wrapper

Defining a Dependency Property

First step is to define the DP ,it is the instance of DP class
  
 public class xTextBox : TextBox
    {

        public static readonly DependencyProperty MinNumProperty ;

}
Note: You can add dependency property only to those classes that drive from Dependency Object.
Define a static field of DependencyProperty Object in the associated class.
The field is defining read only which can be set only in the static constructor for the associated class.
Conventionally, the field that defines the dependency property has the name of ordinary property plus the word ‘Property’ at the end.
In the first step define the object of dependency property class.

Registering a Dependency Property

After defining Dependency Property, we need to register the Dependency Property with WPF.
DependencyProperty object can not be instantiated directly because DependencyProperty Class has no public constructor. So for creating the DependencyObject instance use the static method DependencyProperty.Register() .

DependencyProperty objects can not be changed after they are created because all DependencyProperty object are read only. Instead, their values must be supplied as arguments to the Register() method.

MinNumProperty =
           DependencyProperty.Register("MinNum", typeof(int), typeof(xTextBox), new
           FrameworkPropertyMetadata(new Int32(),
           FrameworkPropertyMetadataOptions.AffectsArrange));


There are two steps of registering a dependency property.
                a) Create a FrameworkPropertyMetadata object
                                It indicate what services you want to use with your dependency Property
(Such as support for data binding, animation, and journaling).
                b) Call the static DependencyProperty.Register() method to register.

Adding a property wrapper

Finally wrap the Dependency property to the .Net CLR- property to access it.
There are two methods SetValue() and GetValue() that are defined in the base
DependencyObject class.


public int MinNum
        {
            get
            {
                return (Int32)GetValue(xTextBox.MinNumProperty);
            }
            set
            {
                SetValue(xTextBox.MinNumProperty, value);
            }
        }
In the property wrapper just call SetValue() and GetValue() method. You should not add extra code to validate values, raise events, and so on.

Note: The property wrapper is not the right place to validate data or raise an event. We should use dependency property callbacks. For the validation purpose we should use DependencyProperty.ValidateValueCallback.
Now we can use this dependency property now:

txtTest.MinNum = 2;

There are three callbacks provided by the Dependecy Property

  • ValidateValueCallback
  • CoerceValueCallback
  • PropertyChangeCallback

The first two ValidateValueCallback and CoerceValueCallback should be use for Property validation.
These two could prevent invalid value.

ValidateValueCallback In this Validation callback you can check if the value is valid or not. If it returns true means value is valid otherwise a exception ‘ArgumentException’ will be thrown.


private static bool OnValidateValueCallback(object data)
        {
            return data is Int32;
        }


CoerceValueCallback  Suppose the Property value is valid but it is not acceptable e .g. you need to enter integer  value between 0 to 8 but you enter 9, the 9 is valid integer value but it is not acceptable. So CoerceValueCallback allow you to adjust the value.

 private static object OnCoerceValueCallback(DependencyObject sender, object data)
        {
            if ((int)data < 0 || (int)data > 8)
            {
                return 0;
            }

            return (int)data;
        }

PropertyChangeCallback PropertyChangeCallback is a method and called every time as property value gets changed, in the event argument there is old and new value.
At this point you can raise a change event if you want to provide the notification to other class

private static void OnPropertyChangeCallBack(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            MessageBox.Show("CallBack Call--" + " Old value: " + e.OldValue + ", New value: " + e.NewValue + ", Property: " + e.Property);
        }



PropertyChangeCallback and CoerceValueCallback are use with FrameworkPropertyMetadata

And ValidateValueCallBack is use with DependencyProperty.Register()

public static readonly DependencyProperty MinNumProperty =
            DependencyProperty.Register("MinNum", typeof(int), typeof(xTextBox), new
            FrameworkPropertyMetadata(new Int32(),
            FrameworkPropertyMetadataOptions.AffectsArrange, new PropertyChangedCallback(OnPropertyChangeCallBack), new CoerceValueCallback(OnCoerceValueCallback)), new ValidateValueCallback(OnValidateValueCallback));