DCSIMG
January 2011 - Posts - Pavel's Blog
Sign in | Join | Help

Pavel's Blog

Pavel is a software guy that is interested in almost everything
software related... way too much for too little time

January 2011 - Posts

WPF For WinForms (and MFC) Developers (Part 5)

Published at Jan 29 2011, 09:48 PM by pavely

Previous posts in this series:

In the previous part we discussed dependency properties. We saw that dependency properties support change notifications, memory conservation, multiple property providers and more.

What are Attached Properties?

First and foremost, attached properties are dependency properties, meaning they support the same of features as regular dependency properties. The difference is, that attached properties are defined by one type, but can be used on any object (inheriting from DependencyObject). This is where the “attached” suffix comes from – there property may be attached to any object. This is a strange concept at first, and its usefulness seems questionable at best.

The simplest example of an attached property is in a XAML like so:

<Canvas>
<Ellipse Canvas.Left="50" Canvas.Top="60" Width="100" Height="100" Fill="Red" />
<Rectangle Fill="Blue" Width="50" Height="50" />
</Canvas
>

The result of this markup is an ellipse located at the x,y of 50,60 and a rectangle located at 0,0.

The markup Canvas.Left=”50” means: set the attached property named Left defined by the Canvas class to the value of 50 on the ellipse. The “Class.Property” syntax is XAML’s way of saying in code something like this:

e1.SetValue(Canvas.LeftProperty, 50);

 

or

Canvas.SetLeft(e1, 50);

 

Which are equivalent.

So, the Canvas class registers (defines) the property, but any object can use it.

In this example the Canvas object looks for the existence of properties such as Left and Top in the above example, and if found uses their values to place the elements at specific positions.

So, what’s so great about that? Wouldn’t it be simpler to add the properties Left and Top to the UIElement class, for example? Then all elements would inherit those properties and all this added “complexity” wouldn’t be necessary?

The thing is, an element may or may not be in a Canvas, so creating properties such as Left,Top,Right and Bottom upfront may be too much. Suppose the element is in a grid. In this case, another ser of properties may be relevant, such as Row and Column. It would be impractical (and confusing) to create every conceivable property that may be needed under some circumstance. That’s why the Grid class defines attached properties such as Grid.Row and Grid.Column that are set in the proper “context” – in the case the element is actually in a Grid.

What happens if we add a setting of Grid.Row to the ellipse like so:

<Canvas>
<Ellipse Canvas.Left="50" Canvas.Top="60" Grid.Row="1" Width="100" Height="100" Fill="Red" />
<Rectangle Fill="Blue" Width="50" Height="50" />
</Canvas
>

Note the Grid.Row setting. At runtime, this seems to have no effect at all. That’s because no one is interested in this Grid.Row value. If, however, that same ellipse is moved to a Grid container, that would have an effect – the ellipse would be placed in the second row of its containing grid (zero is the first row). This emphasizes the “contextual” nature of attached properties.

The above examples may seem to indicate that those properties are effective in some “container” element. But that is actually just a specific case; generally, any object may look for particular attached properties and act upon them. Here’s another example. Suppose we have a StackPanel with some elements:

<StackPanel>
<TextBlock Text="Some text" />
<Button Content="Click me" />
</StackPanel
>

Now suppose we want to change the font size used by the TextBlock and Button. We could do that by changing the regular dependency property FontSize on each of those. But we prefer a central location that would indicate the required font size – and because font size is “inherited” down the visual tree, we can try to do that in the StackPanel level. However, trying to add FontSize to the StackPanel like the following does not compile:

    <StackPanel FontSize="20">

That’s because FontSize is not defined on StackPanel (or any of its base classes). We can still do it though, with the TextElement.FontSize attached property. As an attached property, we can set it on anything, including a StackPanel:

    <StackPanel TextElement.FontSize="20">

This does the trick. The moral of this story is, an attached property may be effective on any element. This brings up some more questions. How did I know that this would work? There are literally dozens of attached properties out there (and we can create more), so how can we tell which to use where?

Unfortunately, there is no easy answer. There is no way to correlate an attached property to some use location that  would make sense. And really there’s no way to do it, because one can use an existing attached property in unpredictable ways. An example of this can be seen in this post I wrote a while back.

Attached properties are somewhat similar to the ExpandoObject of .NET 4. You can add members to exiting objects without deriving a new class. We’ll look at more interesting examples in a future post.

WPF For WinForms (and MFC) Developers, Part 4

Published at Jan 19 2011, 09:53 AM by pavely

Previous posts in this series:

In previous posts, I introduced WPF and XAML. XAML is a declarative, neutral language that fundamentally allows creating objects and setting properties. But what about properties? How are they implemented in WPF? Is it the customary private field access (plus maybe validation), or maybe it’s something else? And if it’s something else, then what is it and why?

Properties

Perhaps it helps to cover some basics first. What are properties in .NET? Properties are a kind of “syntactic sugar”, meaning they are a nice way to call methods – two at most: set and get. There’s really nothing in this definition that requires a property to hide a private field. That’s an implementation detail the property user does need to concern herself with.

The “classic” (and easiest) implementation for a property is undoubtedly a private field wrapping like so:

public class Person {

   private string _firstName;

 

   public string FirstName {

      get { return _firstName; }

      set { _firstName = value; }

   }

}

 

That seems perfectly reasonable. We can add some validation logic to the setter, like so:

set {

   if(string.IsNullOrWhiteSpace(value))

      throw new ArgumentException("name cannot be empty");

   _firstName = value;

}

 

That’s fine for many scenarios. But sometimes it’s simply too simple.

For example, suppose we wanted to bind the above property to some control in our UI. How would we do that? Data binding may seem like “magic”, but there are no rabbits in the computer. When a bound property changes, this change must be somehow broadcasted to whoever is interested. In the above implementation that will not happen. So, this property cannot be successfully data bound.
Let’s consider another facet of this. Suppose we have a Button class (e.g. in WinForms). How many properties does it have? The simple answer is “many”. I think about 50 or so (didn’t count them). Now suppose each property is backed by a private field like the example above. That means, that when a button is created, at least 50 fields come into existence, taking up memory, while usually we change very few properties, leaving most of them with their default values.

Now imagine using dozens of buttons and other controls (list box, check box, picture box, whatever) in one Form/Window: They become memory hogs – causing more frequent garbage collection and generally larger working set. This is unfortunate, as only a small number of properties are actually modified, leaving most with the default value, but still taking up memory.

These (and other) reasons led to the development of dependency properties.

Dependency Properties

So, what are dependency properties? It’s an infrastructure designed to support change notifications, validation, all while conserving memory – properties that don’t change – don’t need storage space.

the infrastructure is based upon the DependencyProperty class, along with the DependencyObject class, which is a required base class for any entity that wants to define dependency properties.

So, how does this look? Let’s change the Person declaration to use a dependency property:

public class Person : DependencyObject {

   public string FirstName {

      get { return (string)GetValue(FirstNameProperty); }

      set { SetValue(FirstNameProperty, value); }

   }

 

   public static readonly DependencyProperty FirstNameProperty =

       DependencyProperty.Register("FirstName", typeof(string), typeof(Person), new UIPropertyMetadata(string.Empty));

}

 

We can declare a dependency property in Visual Studio pretty quickly with the “propdp” code snippet (type “propdp” without the quotes and press TAB twice). What does this code mean?

First we see a “regular” property declaration, but its implementation (detail) is using the GetValue and SetValue methods inherited from DependencyObject. So, to the outside world (outside the Person class), FirstName appears as just a regular property, because a property is just syntactic sugar for two method calls behind the scenes (get_FirstName and set_FirstName in this case). But note that there is no private field anywhere.

The “real” declaration is with that public static field of type DependencyProperty named FistNameProperty that “registers” the property, supplying its name, its type, its owner’s type and a set of metadata (here just the property’s default value). The last setting means that unless someone changes the FirstName of some Person, its default value will be taken from the same location (defined by the registering of the dependency property).

Realistically, you would not implement a data object (such as Person) with dependency properties. First, it creates a dependency (pun intended) on the WPF assemblies – for no good reason – maybe your data objects already exist. Secondly, you must inherit from DependencyObject, which means you can’t inherit from anything else, which is pretty limiting.

But for elements and controls in the WPF world this is not a concern, as all elements inherit from DependencyObject indirectly, so elements use dependency properties all the time. In fact, all properties that we used so far (Background, Fill, Title, etc.) were all dependency properties. We accessed them (in XAML or in code) in the usual way, because the actual implementation is hidden behind the property.

What about change notifications? It turns out that we can supply more parameters to the Register method and provide a change notification delegate and validation delegate (if needed), so we are fully covered and ready for things like data binding. It’s important to note that validation code should not ever be placed inside the setter, because code using the property may elect to “skip the middleman” (the property wrappers) and call SetValue directly (in fact, the XAML parser does that).

Is that all? Not quite.

Why are they called “Dependency”?

Good question. The property value “depends” on a current “supplier” of a value. What does this mean? Suppose I create several TextBlock objects like so:

 

<Window x:Class="WpfApplication2.MainWindow"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <TextBlock Text="Some text 1" />
        <TextBlock Text="Some text 2" />
        <TextBlock Text="Some text 3" />
        <TextBlock Text="Some text 4" />
    </StackPanel
>
</
Window
>

We’ll see four text blocks rendered with the default font properties registered in the static constructor of the control. Let’s take the FontSize property as an example. Its default value is 12 as we can examine this in code by reading the FontSize property of one of the text blocks. Now, let’s change the FontSize property of the Window instance to 30:

<Window x:Class="WpfApplication2.MainWindow" …
       Title="MainWindow" Height="350" Width="525"
        FontSize="30"
>

You’ll notice all the text blocks rendered in font size of 30!

Why? Because of property value inheritance. The FontSize property has been “inherited”, not in the object oriented sense (as TextBlock does not derive from WIndow or vice versa) but in the visual tree sense. This means that the inherited value takes precedence over the default value. The default value is not overwritten, and if the inherited value “disappears” somehow, the default value will again be used. Not all dependency properties have value inheritance – only those that are registered as such (with the FrameworkPropertyMetadataOptions.Inherits flag)

Let’s continue and do one more change: Let’s change the font size of one of the text blocks to 20:

<TextBlock Text="Some text 1" />
<TextBlock Text="Some text 2"  FontSize="20"/>
<TextBlock Text="Some text 3" />
<TextBlock Text="Some text 4"
/>

Now what do we find? The changed text block uses a font size of 20. Again, this means that the local value (20) has higher precedence than the inherited value (30).

What this means is that a dependency property can have many “values”, but only the highest property value is reported by calling GetValue. When the highest priority “provider” “disappears”, the next priority value becomes the current property value. This allows for (e.g.) animation, which changes a property as long as the animation is active (animation is the highest precedence provider); when the animation is removed, the property reverts to its previous value (depending on the highest priority provider at that time).

Summary

Dependency properties is a mechanism that provides for many of its abilities: data binding, property value inheritance and animation, to name a few obvious ones. Dependency properties are used in Silverlight as well (a bit less powerful) and even the Workflow Foundation (again, less powerful and adjusted to that domain).

In the next part, we’ll take a look at a special kind of dependency properties that are surprisingly useful – attached properties.

WPF for WinForms (and MFC) Developers Part 3

Published at Jan 16 2011, 10:27 PM by pavely

In the previous part we learned the rules of XAML. So now we can create loose XAML files and view them in a container such as Internet Explorer. Note that there is nothing “webby” about those XAML files and they will not be rendered by IE if WPF is not installed.

Bringing it to the Real World

Now let’s use Visual Studio to create a new WPF application. Open Visual Studio, Select File->New Project, select C# (or VB if you’re that kind of guy) and then select “WPF Application” in the right pane. Give it a name, such as HelloWorld, a suitable location and click OK. Nothing too fancy.

image

What you get in Solution Explorer are some files, two of which are XAML files.

image

If we run the application now, we’ll get a standard window with a title of “MainWindow” and nothing else. That’s fine for now.

In the main working area, you are also faced with a designer and XAML split view. This is the MainWindow.xaml file and it looks like this:

<Window x:Class="HelloWorld.MainWindow"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       Title="MainWindow" Height="350" Width="525">
    <Grid>
       
   
</Grid
>
</
Window
>
Let’s see if we can make sense of this XAML according to rules we’ve learned in the previous post.

The root XML element is a Window instance (XML element) – we can understand that. We also find the two common XML namespace mappings. The first is the default namespace mapped (indirectly) to most of the WPF classes, and the second one (named “x”) mapped to the XAML namespace, meaning to System.Windows.Xaml and sometimes carries special keywords intended for the XAML parsing engine, as we’ll see shortly.

The Window has some properties set, namely Title, Height and Width. This is done via XML attributes. So far, so good.

But what’s that Grid object that’s “underneath” the Window? How can we interpret that based on the rules we’ve learned? Just to recap, here are the rules of XAML:

  • An Element means creating an instance
  • An attribute means setting a property
  • If a type converter exists, it’s invoked
  • If it’s a markup extension, it’s invoked
  • A property of type IList or IDictionary is automatically treated correctly and objects are added to the collection
  • A class can have a single ContentProperty that does not have to be specified in XAML when setting its value.

The first rules says that the Grid tag means creating an instance of Grid. That’s true, but where will that instance reside in relation to the Window instance? The intuitive answer is “in that Window”, but we need to make sure we know where this actually comes from.

The second, third, fourth and fifth rules don’t apply. We are left with the last rule which states that if a property (of Window) is marked as ContentProperty, then this is where the Grid will actually reside. And since it’s the last rule to consider, this must be true if this compiles ok (and it does). if we examine the declaration of Window we find nothing special. Going to its immediate base class, ContentControl is more revealing. Here’s an excerpt:

[ContentProperty("Content")]

public class ContentControl : Control, IAddChild {

 

So, the ContentProperty of Window is simply named Content. That means the previous XAML is equivalent to:

<Window x:Class="HelloWorld.MainWindow"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       Title="MainWindow" Height="350" Width="525">
    <Window.Content>
        <Grid>

        </Grid>
    </Window.Content
>
</
Window
>

The last piece of the puzzle is the x:Class keyword. This tells the XAML parser that the actual instance to create for the root object is not Window, but HelloWorld.MainWindow that derives from Window. This allows us to (among other things) handle events in that class, reference internal elements (such as the Grid). As you can see in Solution explorer, there is a “connected” file named MainWindow.Xaml.cs. This is a normal C# file, looking like this:

public partial class MainWindow : Window {

   public MainWindow() {

      InitializeComponent();

   }

}

 

Not much there at the moment, but still a few interesting bits. The class is marked partial, meaning there may be more C# source files that compose the MainWindow class. This seems somewhat obvious as there is a call from the constructor to a method named InitializeComponent, but it’s not defined anywhere in this file. It’s actually generated by the XAML compiler. Then the C# compiler combines the two pieces to form a complete class definition.

To see the “other side”, select the “Show Hidden Items” from the Project menu (alternatively, click on the second button from the left in the Solution Explorer). Navigate to the Obj/x86/Debug folder. This should look something like:

image

Double click the MainWindow.g.cs file (the “g” stands for “generated”). The gist file contains the following:

public partial class MainWindow : System.Windows.Window, System.Windows.Markup.IComponentConnector { 

     private bool _contentLoaded;

 

     public void InitializeComponent() {

         if (_contentLoaded) {

             return;

         }

         _contentLoaded = true;

         System.Uri resourceLocater = new System.Uri("/HelloWorld;component/mainwindow.xaml", System.UriKind.Relative);

         System.Windows.Application.LoadComponent(this, resourceLocater);

     }

 

We can see the implementation of InitializeComponent. Note that the static Application.LoadComponent does the heavy lifting. There is no explicit creation of a WIndow, a Grid, setting properties or whatever in the same way it’s done in Windows Forms. In actuality, the XAML is compiled to a more compact form called BAML (Binary XAML) and this is what gets “loaded” and parsed at runtime to create the user interface.

Building a User Interface

Now we can actually build some UI with XAML. Add the following inside the Grid tag:

<TextBlock FontSize="50" Text="Hello, WPF!" TextAlignment="Center" Foreground="Red"/>

The designer shows a preview of what’s to expect when actually running. Run the application and note that the text stays centered horizontally when the window resizes.

It’s unclear how a TextBlock can be”inside” a Grid. Does a Grid has a Content property like the Window? It does have a ContentProperty, but its called Children and it’s actually a collection implementing IList. So in this case, two XAMl rules are activated. We can add more elements inside the Grid and they will be added to its Children collection.

This is the basic way to build a UI with XAML. But why should we use it? Isn’t it easy enough (like WinForms) to create the objects in code? The WinForms designer does that, sending all the “ugly” code to the MyForm.designer.cs code file, creating instances, setting properties, connecting to events, etc. In XAML it’s all implicit, and is hidden away in the BAML.

But is this better?

So, Why XAML?

XAML is declarative. It says what, not how. That means it’s neutral, it’s unconnected to C#, VB or whatever. Other tools (not just Visual Studio) may be capable of consuming and producing it. It’s a kind of serialization format. The best known tool (other than VS) that reads and generates XAML is Microsoft’s Expression Blend, tool that’s designed for graphic designers, but conveniently works with the same solution files as Visual Studio. In fact, it’s common to open the same solution in VS and Blend at the same time, navigating between the two as appropriate. Although there is some overlap between the tools, some things can only be accomplished in one tool, and in any case all graphic related staff is better with Blend, not just because of its provided tools, but because it’s terminology is for graphic designers, not programmers. That said, programmers can certainly (and do) use both.

The declarative approach allows better separation of UI and logic. Ideally, the graphic designer can use a tool such as Blend to generate the UI, and the developer adds the necessary logic, such as event handlers, commands, data bindings, etc. that make the application work. As the developer works on the C# files, and the designer on the XAML, there is minimal collisions. Realistically, it’s not that easy, but with proper usage of patterns such as MVVM (Model-View-ViewModel, to be discussed in a future post, but many resources on this pattern are available on the web), it can actually be that simple.

Another advantage XAML has is being more short and concise. We haven’t seen any complex XAML yet, so I can prove that yet, but when we do data binding, create data or control templates, this really makes a big difference.

Accessing Elements

Naturally, once we have UI elements we may need to access them in code, e.g. to change some property, call a method, etc. How do we do that?

In the previous example we have a TextBlock element. Suppose we want to change its font size to a different value. How would we get to it?

One way would be to drill down starting with the Window object towards the TextBlock. Assume the method ChangeFontSize is part of our MainWindow class:

void ChangeFontSize(double newsize) {

   TextBlock tb = ((Grid)this.Content).Children[0] as TextBlock;

   tb.FontSize = newsize;

}

This works, but clearly there must be a better way, and there is. We can name an element, thus creating a field in the code behind for it (by the XAML compiler). This is similar to WinForms, but whereas WinForms creates a field by default (unless instructed not to), WPF does not. To do that we can use the x:Name XAML directive like so:

<TextBlock FontSize="50" Text="Hello, WPF!" TextAlignment="Center" Foreground="Red" x:Name="tb"/>

 

Now a field called tb is created in our MainWindw class and we can access the TextBlock directly:

void ChangeFontSize(double newsize) {

   tb.FontSize = newsize;

}

 

Definitely simpler (and safer). There is also a Name property for FrameworkElement derived types (virtually all elements derive from it). We can set that instead of x:Name, but we can’t set both on the same element. Either one works, so why the duplication?

First, Name is a property that can be used at runtime, such as with FrameworkElement.FindName. Secondly (and more importantly), some objects in XAML are not elements (do not derive from FrameworkElement), so there is only x:Name for them. The simple rule here is: always use x:Name, as it always exists, whether it’s an element or not.

How can an object not be an element? We actually saw an example of that in the previous post:

<Rectangle StrokeThickness="5" Stroke="Red" Fill="Yellow">
    <Rectangle.LayoutTransform>
        <RotateTransform Angle="30" />
    </Rectangle.LayoutTransform
>
</
Rectangle
>

Suppose we want to refer to the RotateTransform object in code. Clearly, RotateTransform is not an element, so only x:Name works. Now we can (e.g.) change the Angle of the rotation at runtime.


What’s Next?

There are still a few puzzles we didn’t solve. For example, why is there an app.xaml? Does the application object really have any UI? And how do we create our own objects in XAML?

We’ll talk about those in due time, but now we need to examine one of the core foundations of WPF – dependency properties.

WPF For WinForms (and MFC) Developers Part 2

Published at Jan 14 2011, 12:58 PM by pavely

In part 1 I discussed why should something like WPF exists. In this part I’ll talk about that thing called XAML. When people first hear there is a new language to learn to use WPF, they instinctively get defensive. Another language? What’s wrong with C#? If it’s good enough for WinForms and a bunch of other technologies, why do we need another language to learn? Isn’t learning WPF bad enough?

The “good” news is that a WPF application can be written entirely in C# and use no XAML at all. Anything that can be done in XAML can be done in code. But that would be missing out.

What is XAML?

XAML (eXtensible Application Markup Language) is an XML based language. That is, XAML is first and foremost regular XML. Its interpretation is what makes it interesting. XAML has very few capabilities, but combining them with its “eXtensible” part makes it pretty powerful. That said, it’s not a replacement for C# or VB or any other “normal” .NET programming language.

XAML is declarative. It says what, rather than how. The declarative approach to programming is pervasive these days, mostly popularized within the .NET world by the Language Integrated Query (LINQ) technology that came out in .NET 3.5 with language support by C# 3.0 and VB 9.0.

XAML started out in WPF, spread to Silverlight and the Workflow Foundation (WF), which hints that it’s pretty agnostic and really unrelated to UI. In fact, it’s possible to create (almost) any type of object in XAML as we’ll see shortly. In .NET 4, XAML took its rightful place as a first class citizen in the System.Xaml.Dll assembly (in the System.Xaml namespace). I’ve written something about that here and here. Note that WPF still uses its own XAML and does not (currently) support the latest XAML implementation (dubbed “XAML 2009”).

XAML Away!

Here’s a very simple XAML we can write:

<Button Content="OK" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" />
If we disregard the scary “xmlns” declaration, we have a simple XML element named Button and an XML attribute named Content with a value of “OK”. 

The first rule of XAML is, that an element means creating an object instance. In this case it’s creation of an instance of System.Windows.Controls.Button. The second rule of XAML states that an XML attribute means setting a property value. In this case, the property Content of the button is set to “OK”.

To view the results of this XAML, we can create a file (e.g. simple.xaml) with the code above and double click in Windows Explorer. If all is well, Internet Explorer will open the file and render it. You should see a giant button stretched within the client area of IE’s window and the caption “OK” in the center.

image

Not too impressive for now, but it’s a start.

Creating an instance is possible if the type is non-generic and it has a public default constructor. WPF’s XAML cannot create generic types (possible in XAML 2009) and cannot call any constructor other than the default (again, possible in the new XAML 2009, not part of WPF at the moment). Types that adhere to these constraints are sometimes called “XAML friendly”.

Now what’s this scary looking xmlns declaration? This is an XML namespace declaration, and is technically related to XML. The problem XML namespaces were designed to solve, is what (in this case) should we create? System.Windows.Controls.Button or perhaps System.Windows.Forms.Button or maybe System.Web.UI.Controls.Button or maybe it’s some MyNamespace.Button instead?

This XML namespace tells the XAML parser that the WPF namespaces should be consulted by default for all element names with no prefix. We can add prefixed XML namespaces to be able to create other objects (as we’ll do later).

Let’s try something else:

<Ellipse StrokeThickness="5" Stroke="Red" Fill="Yellow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" />

This is similar: Create an instance of the Ellipse class, set its StrokeThickness property to 5, its Stroke property to “Red” and its Fill property to “Yellow”. This is how it looks when opening with IE:

image

The code above may be a bit strange. What is the type of the Stroke property? Surely it can’t be a string. And it’s not. It’s a Brush. A Brush is an abstract class in WPF from which various brushes inherit. One of those is SolidColorBrush, which is the simplest brush, representing some constant color. How did “Red” got translated to a SolidColorBrush object by the XAML parser? The answer lies with type converters.

A type converter is a class inheriting from System.ComponentModel.TypeConverter that may try to convert a string to another type. In this case, the XAML parser uses the BrushConverter class. Why? Let’s take a look at the declaration of the Brush class:

[TypeConverter(typeof(BrushConverter))]

public abstract class Brush : Animatable, IFormattable, DUCE.IResource {

 

This is part of the declaration, of course. The key point here is the TypeConverter attribute applied to the Brush type. When the XAML parser sees that types don’t match (and most times they don’t, as XML only understands strings), it checks the target type to see if a type converter exists, and if so, hands it the value from the XML and expects a non-null response. In this case, BrushConverter returns an instance of type SolidColorBrush initialized with a red color. The equivalent code might be something like (assuming the Ellipse’s reference is e1):

e1.Stroke = new SolidColorBrush(Colors.Red);

 

Technically, this could be further shortened by using the Brushes static class that exposes static properties representing SolidColorBrush objects with 141 predefined color names:

e1.Stroke = Brushes.Red;

 

The same goes for the Fill property.

Note that the StrokeThickness property is not a string either – it’s a double. There’s a type converter for that, too (LengthConverter), set on the property itself, as setting it on the double type is not possible (and impractical). The XAML parser checks there, too.

Markup Extensions

Sometimes just setting properties is not enough. Perhaps there is something “declarative” in nature that needs to be applied, but there is no single property or a bunch of properties that can accomplish that. That’s what markup extensions are for. That’s the “eXtensible” part of XAML.

At this time, we’ll look at two existing markup extensions. Generally speaking, markup extensions are classes inheriting from the abstract MarkupExtension and need to override the abstract ProvideValue method.

Let’s look at an example. We want to set the Fill property of the Ellipse to null. In code it’s trivial. In XAML, how would we represent null? Enter the Null markup extension:

<Ellipse xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        StrokeThickness="5" Stroke="Red" Fill="{x:Null}" 
/>

Markup extensions start with a curly brace to let the XAML parser know we’re talking about a markup extension. In this case, it’s System.Windows.Markup.NullExtension. Note that we can use the markup extension without the word “Extension” (if exists in the class name).

The XML “x” namespace is mapped here (internally) to the System.Windows.Markup namespace. This is because that’s where the NullExtension class resides. This is not a requirement. Later we’ll encounter other extensions that do reside in the “normal” WPF namespaces. Of course, “x” is just a typical name used for this. You can use any string, just match it when used.

Another simple example of a markup extension is the {x:Static} extension (implemented in System.Windows.Markup.StaticExtension). This markup extension allows accessing any static property. Here’s an example:

<Ellipse xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        StrokeThickness="5" Stroke="{x:Static SystemColors.DesktopBrush}" Fill="{x:Null}" 
/>

This makes the Stroke of the ellipse the same color (SolidColorBrush) as the desktop as configured using the control panel).

Complex Properties

Sometimes a property’s value cannot be written as a string and there is no appropriate type converter. For example, a value can be another object that needs to be created. In this case there is a XAML syntax for that. Consider the following XAML that creates a rectangle and rotates it by 30 degrees (from now I’ll omit the XML namespace declarations for brevity):

<Rectangle StrokeThickness="5" Stroke="Red" Fill="Yellow">
    <Rectangle.LayoutTransform>
        <RotateTransform Angle="30" />
    </Rectangle.LayoutTransform
>
</
Rectangle
>

This is the result:
image
 

I wanted to set the LayoutTransform property to an instance of RotateTransform class. The format is Type.Property and then the value as a separate element (meaning creating an instance). The equivalent code is something like this:

Rectangle r = new Rectangle();

r.Fill = Brushes.Yellow;

r.Stroke = Brushes.Red;

r.StrokeThickness = 5;

var rt = new RotateTransform();

rt.Angle = 30;

r.LayoutTransform = rt;

 

The code could be a bit shorter because of a RotateTransform constructor that accepts an angle, but it’s not fundamentally different:

r.LayoutTransform = new RotateTransform(30);

 

Handling Collections

Some properties are collections. Adding items to collections mean calling some Add method, but XAML in itself cannot call methods. If a property’s type is an IList<T> or IList, the XAML parser will automatically call Add on elements appearing underneath the property. Here’s an example:

<Rectangle StrokeThickness="5" Stroke="Blue">
    <Rectangle.Fill>
        <LinearGradientBrush>
            <LinearGradientBrush.GradientStops>
                <GradientStop Offset="0" Color="Red" />
                <GradientStop Offset=".5" Color="Yellow" />
                <GradientStop Offset="1" Color="Purple" />
            </LinearGradientBrush.GradientStops>
        </LinearGradientBrush>
    </Rectangle.Fill
>
</
Rectangle
>

Here’s the result:

image

A LinearGradientBrush is another type of brush, made of linear gradients. The LinearGradientBrush.GradientStops property is of type GradientStopCollection, which implements IList<GradientStop> (and IList among others). The XAML parser calls Add on each object. The equivalent code might look like this:

Rectangle r = new Rectangle();

r.Stroke = Brushes.Blue;

var brush = new LinearGradientBrush();

brush.GradientStops.Add(new GradientStop(Colors.Red, 0));

brush.GradientStops.Add(new GradientStop(Colors.Yellow, 0.5));

brush.GradientStops.Add(new GradientStop(Colors.Purple, 1));

r.Fill = brush;

 

Notice how the XAML looks more intuitive (at least after using it for a while…).

The other type of collection supported by XAML is a dictionary (IDictionary implementations). In this case, a key is needed, as Add requires a key and a value. The key is then supplied with the special x:Key attribute on the added element. I’ll show an example of this at a later post.

Content Property

There is another, final, rule to XAML. In the previous LinearGradientBrush example, I’ve set the gradients to the GradientStops property. However, I did not have to actually specify this. I could have gotten away with this:

<Rectangle StrokeThickness="5" Stroke="Blue">
    <Rectangle.Fill>
        <LinearGradientBrush>
            <GradientStop Offset="0" Color="Red" />
            <GradientStop Offset=".5" Color="Yellow" />
            <GradientStop Offset="1" Color="Purple" />
        </LinearGradientBrush>
    </Rectangle.Fill
>
</
Rectangle
>


It looks like the gradient stops are direct children of the LinearGradientBrush. That’s possible because the GradientStops property is identified as the “Content” property of the LinearGradientBrush (you can think of that as a kind of “default” property). So, this code and the previous one are completely equivalent.

How does the XAML parser know this? Again, using an attribute. The GradientBrush abstract class (which is the base of LinearGradientBrush) is declared like this:

[ContentProperty("GradientStops")]

public abstract class GradientBrush : Brush {

 

That means, that the GradientStops property is the default property in XAML of GradientBrush objects. That’s why it’s permissible (and intuitive) to just specify the property’s value (in this case a collection, but really can be anything). Naturally, every class can have at most one Content property.

Summary: XAML Rules

These are all XAML rules. With that in place, you can read and XAML, no matter its apparent complexity. Here’s the bulleted list:

  • An Element means creating an instance
  • An attribute means setting a property
  • If a type converter exists, it’s invoked
  • If it’s a markup extension, it’s invoked
  • A property of type IList or IDictionary is automatically treated correctly and objects are added to the collection
  • A class can have a single ContentProperty that does not have to be specified in XAML when setting its value.

In the next part, we’ll see how this integrates with Visual Studio and talk some more on why should we want to use XAML.

WPF For WinForms (and MFC) Developers, Part 1

Published at Jan 11 2011, 04:00 PM by pavely

WPF has been around for more than 4 years now (since the release of Windows Vista), but only in the last couple of years there is increased move from Windows Forms to WPF. However, the transition is anything but easy. This is not just because WPF is relatively new, or because people are people, and as such don’t like change for the sake of change. I mean, WinForms is ok, isn’t it? MFC may be old, but it works, doesn’t it?

The term User Interface (UI) has served us for years. In recent years, this just isn’t enough. Now it’s all about User Experience (UX). Even if the application is a boring form entering system – now you want the user to actually like using the application, as boring as its various aspects may be.

In this series, I’ll introduce WPF to the skeptic, fearful or curious WinForms or MFC developer. It is not my intention to replace a good WPF book – and there are other tutorials on the web – my intention is to focus on the essentials, the core of WPF and especially why. Why is the question first asked by any WinForms or MFC developer when told about that new thing called WPF. Is WPF just another API for user interface development?

Why WPF?

So why WPF? What’s wrong with WinForms? What’s wrong with MFC? Granted, both are old, MFC is antiquity itself in computer time (created around 1989 if I’m not mistaken). Still, are they “bad” in any concrete way? Sure, both have their flaws. But then again all technologies / libraries have flaws. So, why WPF?

The basic problem with WinForms, MFC, VB6, WTL is the same: they are wrappers around the Win32 user interface API (in user32.dll or win32k.sys if you’re a kernel lover). Everything is centered around a handle to a window (HWND). An HWND is at the heart of the windowing system. It encapsulates a (usually) rectangular region that only one entity may control. Technically, a HWND doesn’t have to be rectangular – this can be changed with the SetWindowRgn Win32 function, but it’s awkward. Still, every pixel is controlled by a single entity, be that this HWND or that HWND. This means that transparency effects, such as blending of two HWNDs is difficult if not impossible.

The existence of these HWNDs makes other effects difficult to achieve. Moving HWNDs by changing their position, for example, is sluggish and usually flickers. They were simply not made for this.

One solution would be to redesign the windowing system. That would be a huge task, considering backwards compatibility would have to be maintained for years to come. I believe this is inevitable and will happen sooner or later. In the meantime, there is WPF.

That where WPF departs from the other technologies. In WPF, (barring a few minor exceptions) only a top level window has an HWND, so that the Windowing system recognizes it. The client are of the window is pure graphics to the windowing system. That means that buttons, list boxes and most other controls are “invisible” to windows, and veteran tools such as Spy++ wouldn’t find anything inside such a window.

Having given up on HWNDs opens up a world of possibilities in terms of graphic capabilities. And WPF takes the opportunity presented all the way.

So HWNDs are gone. So what?

Let’s take graphics as an example. How do you draw something in WinForms? There is GDI+ with classes such as Graphics, Pen, Brush and others. What’s wrong with those?

The first thing is that GDI+ is slow. In fact, it’s the slowest graphics API Microsoft has put out. It never undergoes hardware acceleration, which in today’s high powered graphic cards, is a real shame. Furthermore, it’s 2D only. Sometimes we need 3D, then what can we do? More on that later.

How do we do graphics with MFC? By using GDI (the original windows graphical API), and we can also use GDI+, as it’s a C++ graphic library. What’s wrong with GDI? It’s old and its API is primitive and unintuitive, for starters. It uses a device context (HDC, which is analogous to a GDI+ Graphics object), but that’s no better. Starting with Windows Vista, it’s not hardware accelerated either, although it’s faster that GDI+. What about 3D? Nothing like that.

With WinForms and MFC 3D graphics can be obtained using an external library such as DirecX (with its Direct3D component) or OpenGL. Both are native COM APIs, so for WinForms some wrapping is needed. There are a few around, such as SlimDX and Microsoft’s own wrappers found in the Windows API Code Pack. Although possible to use, it’s difficult and does not integrate well with WinForms (or MFC for that matter).

WPF renders everything using DirectX (Direct3D). This have several important benefits: first, all drawing is hardware accelerated, as DirectX works closely with the graphic hardware (technically through appropriate drivers). Second, mixing 2D and 3D is easy and natural. 3D can be used as easily as 2D (of course setting all the details is harder) but they are part of the same layout system and content model.

What about higher level multimedia, such as playing a video file? In WinForms or MFC we have to leverage an external library, such as DirectShow or the Windows Media Foundation. Again – native libraries, need to wrap somehow for .NET. And again – no integration.

WPF treats everything pretty much the same. Whether it’s a control, an image, a 3D scene, a video or whatever, everything can be mixed together any way we wish – we have great integration. No need to fish out to other libraries – everything is in the box.

This flexibility has other implications. A button in WPF, for example, does not have to contain text or an image or both. It can contain literally anything. It can contain a 3D moving scene, a playing video, text, image or any combination of the above. Yet it’s still a button, raising a Click event when pressed with the mouse, or the space bar is pressed when it’s in focus. WPF splits a control to have looks and behavior and the two can be kept separate most of the time. The same feat in WinForms would require deriving a new class from Button, overriding some OnPaint method and maybe others. With MFC it’s similar. WPF requires no such thing. If no new functionality is required, no new class is required, either. Just changing the content or more drastically, the control template does the trick. More on that in a future post.

What else?

WPF has many more features worth mentioning, such as data binding, flexible layout system, graphic capabilities and others. We’ll explore them in due course.

In the next part we’ll look at a new language that was created for WPF (but others use it today): XAML. We’ll ask the most important question: Why?