Sharp Technology with RizwanSharp
In last article we talked about WPF as a next generation UX development technology from Microsoft. We also talked about declarative programming model it provides through the use of new XML based declarative language “XAML (a.k.a Zammel)”. In this article we’ll be digging deeper in XAML by understanding its usefulness in application development and its principles by writing snippets of code.
If someone is not sure of what declarative programming model is, I suggest reading this or searching on web because this is not the part of our discussion today so I encourage you to explore it yourself.
What is XAML?
XAML (a.k.a Zammel) is a simple and general purpose XML based declarative language for declaring hierarchy of .Net objects which are instantiated at runtime. General purpose? Yes! It is very important to understand that XAML does not have ties to WPF and both of these can be used independently. Not to be mentioned that the use of XAML is optional when working with WPF and XAML can actually be used in other .Net technologies as well. Anything that can be done with XAML can also be done with the code of your favorite .Net language such as VB or C#.
Before you loose your interest in XAML due to the above explanation and before we proceed further in learning XAML, it is important to understand why XAML is important and why it should be used for laying out UI stuff in WPF applications.
Why use XAML?
· Separation of Design from Code
It is a good design principal to separate the UI design from the code for maintainability reasons and fortunately XAML encourages it by default. (UI stuff done in XAML and business logic in code behind)
· Designer/Developer Collaboration
Most developers don’t know the use of design tools such as Expression Blend, Expression Design, Adobe Illustrator etc. Same is true for designers who don’t know C#, VB or other programming languages. So you can say there was no way before WPF or specifically XAML for a software development team to effectively work together on a software project. But now with XAML it is possible that designers create a software prototype in their favorite design tool and export XAML which can be used by developers in further development or the reverse is also true.
· Easy to be Parsed, Serialized and Desterilized
XAML is xml based which makes it very easy to parse, serialized and desterilized XAML for dynamic UI scenarios whereas parsing C# or VB code and serializing/desterilizing it is a superb headache where only compiler designers may succeed.
· Simplicity
XAML is a simple language which has really short learning curve as compare to any other programming language. So it is very easy for a designer/web developer (those are already familiar with HTML) to learn it. After reading and understanding this article you’ll be in condition to validate this point.
· Shorter Code
In most scenarios XAML code is shorter (due to shortcuts provided in it) than the code in any other language for the same output.
To conclude the discussion of the importance of XAML in WPF we can say that though XAML is not necessary for WPF but it opens doors to a whole new world for designer/developer collaboration where they can produce a stunning output using the same underlying technology but different set of tools which interface with that differently.
At this point, I understand that you are convinced to learn XAML so let’s get startedJ.
Basics of XAML
As I mentioned previously that XAML is very easy to learn and work with if you really understand its rules which are as follow:
1. XAML is case Sensitive like XML and C#.
2. Each XAML document can have only one root element.
3. Each element in XAML usually represents an object of .Net class of same name. E.g. if there is a <Button /> element, it instruct WPF to create a Button object at runtime using its default constructor. (However, sometimes elements are also used to set properties which are not otherwise expressible. We’ll be looking at this shortly in this article).
4. On each element you can set one or more properties through attributes as we do in XML. But as mentioned previously some properties cannot be expressed through attribute syntax so we have to apply property element syntax i.e use of elements to set properties. For setting such properties we use a special syntax which makes them different from object elements.
5. On each element you can attach one or more event handlers using the same attribute syntax as used to set properties.
Initializing Object (Object Elements)
In XML, there is a concept of elements. Since XAML is an XML based language, same applies to XAML too. But to understand what elements in XAML mean to XAML compiler/runtime parser, let’s look at the following simple XAML code snippet:
XAML Code
<Button xmlns="" />
Equivalent C# Code
System.Windows.Controls.Button button = new Button();
Both XAML and C# code are equivalent but you can test XAML’s output without compilation in XamlPad which is a tool that comes with Windows SDK V.6 and is installed by Visual Studio 2008 (code named “Orcas”). You can find this tool in <Programs Files>\Microsoft SDKs\Windows\v6.0A\Bin\. Simply open up XamlPad by running the exe and paste the above given XAML snippet in the tool and you should immediately see the output.
You can also save XAML code snippet in a file with .xaml extension and open it in web browser such as Internet Explorer or Mozilla FireFox to view the output.
Above given XAML code snippet when pasted in XamlPad produces the following output:
Note that XamlPad is just a handy tool to test if XAML is valid and what it produces. Also there is no intellisense support in XamlPad but visual studio 2008 provides complete intellisense support for XAML.
Let’s get back our discussion in understanding role of elements in objection initialization in XAML.
Declaring an XML element in XAML is equivalent to instantiating the .Net object of same name with default (parameter-less) constructor. Such element is called object element.
You can also see an xml namespace declaration in previous XAML snippet but please forget about that for a little bit time and just assume that it must have to exist at the top level object element in your XAML file otherwise it will not work.
So conclusion is that initializing an object in XAML is as easy as writing an XML element whose name must be the same as off the corresponding .Net object you want to initialize.
It’s pretty neat and straightforward, isn’t it? I know your answer is yes of course. So let’s go aheadJ.
Setting Simple Properties (Property Attributes)
In previous example we learned that how to declare an object in XAML which will be created at runtime by WPF using its default constructor. And now we have to see that how to set properties of same object in XAML. Have a look at the following code snippet:
<Button xmlns=""
Content="Hello XAML" Width="200" Height="24" />
Button button = new Button();
button.Width = 220;
button.Height = 24;
button.Content = "Hello XAML";
Each attribute inside an object element represents either property or an event. (We’ll be looking at events shortly. But a thing to note is that you cannot distinguish between attributes which represent events and which represent properties unless you know them by name or use see the event or property symbols in Visual Studio’s Intellisense)
An important concept to understand here is that how a string representation of some value in XAML can be assigned to some property is not of type string. For example in above example Width="200". Here comes the role of TypeConvertors which do the dirty work for you. WPF includes type convertors for many .Net types and all are inherited from TypeConvertor base class.
Also, have you visualize the difference between size of XAML code and its corresponding C# code. I have already mentioned that in most cases XAML is shorter to type than some procedural code and Visual Studio even makes it fun to do with its rich intellisense support.
Setting Complex Properties (Property Elements)
We have just seen that how to use attributes to set properties in XAML but in many situations it is not possible to set properties using attribute syntax in XAML because you cannot express the it complexity using a simple string as we did in last example to set three different properties.
Let’s consider you need to set an image in button’s content property instead of plain text how you’ll set another button to button’s content property using property attribute syntax? Answer to this question is Property Elements. Yes, as I already mentioned that elements in XAML can also represent properties but they have special syntax so it’s indeed very easy to distinguish them from object elements. Let’ see XAML.
<Button xmlns="">
<Button.Content>
<Button Width="100" Height="24" Content="Inner Button" />
</Button.Content>
</Button>
Button outerButton = new Button();
Button innerButton = new Button();
innerButton.Width = 100;
innerButton.Height = 24;
outerButton.Content = innerButton;
Does this make sense to put button in button? I know you are thinking “NO” and that’s what I agree upon but I just wanted to remind one of the features of WPF I talked about in my last article i.e. “Customization and composition WPF provides where you can almost put anything in any other thing. You can even put a 3D animation, a listbox or any other control inside a button or any other item. So everything in WPF behaves like a container (parent control).
Attaching Event Handlers (Event Attributes)
Attaching events in XAML is as simple as setting property with property attribute syntax which is the simplest way to set simple properties.
Consider this:
button.Click += new RoutedEventHandler(button_Click);
The above example sets both property and event attributes through the same syntax. But this code is referencing some function to handle the click event; this code cannot be viewed in XamlPad because there is not code behind file with that function. Anyway, you can fire up Visual Studio and experiment it in there without any problem.
I think you have just had a sigh “Ahhh” XAML is based on extremely simple rules. Now you are familiar with what elements and attributes of XML mean in XAMl, Let’s move further.
Namespaces
In previous all XAML code snippets you noticed an XML attribute which seems to be a property set with property attribute syntax but it is not. It is XML namespace to be used to find the objects in WPF assemblies. This string is hard-coded in all WPF assemblies with several instance of XmlnsDefinitionAttribute custom attribute. This is needed because XAML cannot only be dependent on element name to use to initialize object because more than one namespaces can have classes with same name. One other thing is that mapping between .Net namespace and XML namespace is not one-to-one but several .Net namespaces have same XML namespace so that XAML should remain as simple as possible.
The root object element of each XAML file must contain at least one XML namespace to qualify itself and its children. Each child can have its own XML namespace in it object element but it’ll make XAML look messy. If there is need to define more than one namespaces then each additional namespace should be given a unique prefix.
The good design principal is that most basic and most used namespace should be prefix free and all additional namespaces should have a small prefix.
Let’s create a new WPF application in Visual Studio 2008, Visual Studio will create a Window1.xaml file with Window1.xaml.cs file for you as main window. We’ll be discussing about Window1.xaml.cs (Code behind shortly).
<Window x:Class="WpfLsArticle2.Window1"
xmlns=""
xmlns:
<Grid>
</Grid>
</Window>
In above XAML code snippet, we can see two XAML namespaces. First is prefix free so it becomes the default namespace of entire XAML document while the second one has been prefixed with an x and it can be referred by any element with the same prefix. We have two UI elements (Window and Grid) in the above XAML document and both are prefix free so it means XAML parser locates them in all .Net namespaces which are mapped to xmlns=".
But if we want to use something from the second namespace we would do it this way:
<Grid x:
In WPF it is not important to name every UI element, we can name only those items which we want to access and manipulate programmatically from the code behind this keeps XAML simplified with elimination of unnecessary attributes. There are two ways to set name of an element; one is to use its Name property but you may agree that not all classes expose Name property specially non UI classes we can still set name on such elements using XAML namespace (prefixed with an x) x:Name and the result remains the same. For consistency I personally prefer to use x:Name syntax.
Another Way to Set Properties (Markup Extensions)
We have already seen two ways (property attribute and property elements) to set properties on objects in XAML but it is not desirable to hard-code the property value. Or at some time, you may need to set a property’s value to an object that already exists somewhere in your application or you may need to bind it to some other control’s property and so on. In this situation you can only get your work done with Markup Extension which is another way to set properties in XAML. Markup Extension extends the previously described property attribute and property element syntaxes to set properties.
XAML Code
xmlns:
</Button>
button.Foreground = SystemColors.ActiveCaptionBrush;
button.Content = "Hello";
Markup extensions are written with curly brackes which enlose a string which evaluates to some value or object at runtime. Static identifier in the above example is the name of the markup extension class in XAML namespace prefixed with x. Such classes usually have Extension suffix with them such as StaticExtesion or NullExtension but in XAML, this prefix can be omitted. Markup extensions are very useful because they are used for data binding.
Code Behind Files
Of course XAML provides us a convenient way to define application’s UI elements in a hierarchal fashion and also helps us to integrate the other part of the world i.e. designers in application development process but application has no value without code which has your business logic and logic to manipulate the UI done in XAML. In other words, to build a true application both XAML and procedural code have to work together so let’s see how it works…
x:Class="WpfLsArticle2.Window1" on Window object element in the previous XAML document, links the two worlds together where the code behind file generated by Visual Studio looks like:
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
}
In this code behind file you can provide your event handling code.
XAML Compilation
A typical WPF application (with both XAML and Procedural Code) gets compiled and converted in to an assembly (.exe or .dll) in two phase process. In first phase of compilation of a WPF application, all XAML files get compiled into Binary Application Markup Language (BAML) by XAML compiler (xamlc.exe). For example, if your application has a XAML file MainWindow.xaml with its code behind in MainWindow.xaml.cs, during XAML compilation process MainWindow.xaml would get compiled into MainWindow.baml and then placed temporarily in obj\Debug or obj\Release (depending on debug or release build mode respectively). At the same time during the first phase of compilation process, a partial class would also be generated MainWindow.g.cs and placed with the BAML file (in obj\Debug or obj\Release) generated previously. This generated partial class includes code for all the fields of objects declared in window, code to load BAML, code which connects each control to its corresponding generate field and code which attached event handlers.
In the second phase of compilation your own partial class portion is compiled with the partial class portion generated by previous phase by your language compiler such as csc.exe in case of C#. Compiled code then becomes a single assembly and BAML files are embedded as a resource in that assembly.
“BAML is nothing but a compact, tokenized and fast to load representation of XAML”
The coolest part of the story is that you can build or customize UI of your application on the fly by loading XAML from database or somewhere from the internet. This can be done using XamlReader class in System.Windows.Markup namespace. Let’s have a quick look that how it works:
Create a new Project
Create a new WPF Application in Visual Studio. You’ll get a Window1.xaml file in your project ready to be run as main Window of your application with following XAML document:
</Grid>
You’ll also get a file Window1.xaml.cs which will be having code for your event handlers. Now, we want some control to be added inside the grid of Window1 at runtime based on user role so let’s create a XAML file which looks like the following:
Create a separate XAML Document
<Grid xmlns=""
xmlns:
<Button x:
<Button x: </Grid>
There must be one and only root element in each valid XAML file so we are using a Grid as a root element. Then we have added two buttons to it as you can see from the above XAML document. Lets save this document as Controls.xaml.
Use this code in Window’s Loaded event handler or in any other place depending on the application needs:
using (FileStream xamlFile = new FileStream("Controls.xaml", FileMode.Open, FileAccess.Read))
{
string[] roles = new string[] { "Admin", "User" };
Random rand = new Random();
int currentRoleId = rand.Next(0, 2);
// XamlReader.Load method returns the root element of passed XAML stream. In our case it is a Grid
Grid rootElement = (Grid)XamlReader.Load(xamlFile);
if (String.Equals(roles[currentRoleId], "Admin", StringComparison.Ordinal))
Button button = (Button)rootElement.FindName("adminButton");
rootElement.Children.Remove(button);
this.mainGrid.Children.Add(button);
}
else if (String.Equals(roles[currentRoleId], "User", StringComparison.Ordinal))
Button button = (Button)rootElement.FindName("userButton");
This is only a simplest example to show that it worksJ but you can actually load very complex prebuild heirarchy and set it to some portion of UI as a content, can manipulate properties in that heirachy, attach events and so on.
Conclusion
XAML is a very useful and extremely simple XML based language. Though it is not necessary for WPF development but it plays a major role in WPF and commercially there may not be any WPF application without it.
Assessment
After reading this article you should be able to understand:
1. Usefulness of XAML
2. Role of XML Elements and Attributes in XAML
3. Namespaces
4. How to load, parse XAML and then use it to dynamically build some part of UI.
5. XAML compilation process.
6. BAML
What’s next?
In next article, we’ll be talking about some new concepts introduced in WPF such as Logical and Visual Trees Routed Events etc. I’ll try my best to publish next article in next 3 days so stay tuned.
Though I tried my best to go as much deep as possible but article kept growing so I missed a few things and would recommend you reading them as well.
These are:
1. Attached Properties
2. Handling Special Characters in XAML
3. Content Property
Feedback
Your comments, feedbacks, suggestions, corrections and questions are most welcome. They’ll help both you and me learn the most from each other.
Skin design by Mark Wagner, Adapted by David Vidmar