LA.NET [EN]

XAMLArchive

Nov 23

Markup extensions

Posted in Silverlight, XAML       Comments Off on Markup extensions

Markup extensions allows you to extend the expressibility of XAML. You use markup extensions to escape the general treatment that attribute values get (by default, we’ve seen that they are treated as strings or that a type converter is used to convert them to the adequate type). Markup extension expressions are always delimited by the pair { }.

Currently, the Silverlight’s XAML parser understands only four markup extensions:

  • Binding: used in data bound scenarios for getting the value of an object at run time. This extension is implemented by the Binding class and you can set several of its property from XAML (ie, from the markup extension expression itself). We’ll return to this class in future posts, when we talk about data binding operations;
  • StaticResource: used for setting the value of a property to a resource  already defined in a resource dictionary (resource dictionaries are used for saving objects by key and it can be used in both XAML and code). The current release of Silverlight does not have any managed code class for supporting this type of markup extension (in other words, this is implemented in unmanaged code);
  • TemplateBinding: another binding which is implemented in unmanaged code only. You’ll use this binding in your templates when you want to link the value of a control’s property to the value of another object’s property of the templated control (once again, this is only intro stuff and we’ll come back to this topic in future posts);
  • Null: used for setting the value of a property to null. You might find this markup extension odd at first, but the truth is that there’s no other way to set a property to null in XAML (don’t forget that passing string would probably result in using a type converter). Another interesting thing you should keep in mind is that not all properties have a default value of null (to understand this, we’ll need to go into dependency properties – and yes, that will be the topic of a future post).

If you’ve been doing some WPF development, you’ll probably be thinking that Silverlight is not as extensible as WPF. For starters, there is no MarkupExtension base class (which is extended by all markup extensions). In practice,this means that you cannot create your own markup extensions. Finally,you should also notice that unlike WPF, you can only use markup extensions with the attribute value syntax. Again, this is happening due to the limitations I’ve mentioned before (Silverlight must be small and we can’t forget that it runs across several platforms/browsers)

I guess that it’s time to see an example. We’ll get started with the StaticResource markup extension:

<Canvas>
    <Canvas.Resources>
        <SolidColorBrush x:Key="brush" Color="Green" />
    </Canvas.Resources>
    <Button Content="Say hi"
        Background="{StaticResource brush}" />
</Canvas>

In the previous snippet, I’ve started by creating a new Canvas resource brush and I’ve identified it with the name brush. This is all you need to be able to reuse that resource in all the Canvas’ children objects’ properties that expect a brush (in the previous example, I’ve used that resource to fill the background color of a button). Resource dictionary usage has some gotchas, but I’ll leave that for a future post (after all, the main objective of this post is to look at markup extensions).

StaticResource and Binding markup extensions expect only a single value. However, Binding is implemented through a managed class and if you check its definition, you’ll see that it has several properties which you can also set from XAML. In this case, the syntax is simple: you can specify a value for the “default” property (which is Path, in the case of the Binding markup extension) and you should indicate all the other properties through the key=value pair entries (separated by comma). For instance, here’s an example of how you can set a binding:

<TextBlock Text="{Binding Content, ElementName=origin}" />

In the previous snippet, I’m binding the value of the Text property to another element defined through XAML which is named origin (I guess it could be a button since it has  a Content property). There’s lot of things to say about bindings but for now I’m only worried in showing you how to use them from XAML (through the markup extension syntax).

Before ending up, there’s still time for one more topic: escaping the { } in attributes. By default, whenever you pass the pair { } to an attribute value, the XAML parser will interpret it as a markup extension. If you need to set the value of an attribute to a value which contains that { } pair, you’ll need to escape it. Here’s how:

<TextBlock Text="{}{Binding Content, ElementName=origin}" />

As you can see, using the {} pair at the beginning of the attribute’s value is all that it takes to escape the rest of the expression. If you put the previous XAML in a user control, you’ll see the {Binding….} text on the browser when you load that  control.

I’ve only been playing with Silverlight for a few days (and I really haven’t done any real work with it). Even though it has lots of potentials, I must confess that I’m a little disappointed with the gotchas I’ve already found. I guess that they won’t matter much if you’re using a tool like Blend for creating the interface, but I must say that all these little things which don’t always work as expected are starting to make me think that I should probably be working with WPF instead where everything makes sense and works as expected…

And that’s it for now. Stay tuned for more on Silverlight.

Nov 19

XAML: what about events?

Posted in Silverlight, XAML       Comments Off on XAML: what about events?

A friend of mine asked me about events and XAML: can we setup event handlers in XAML? And the answer is, yes, you can. Here’s a quick example of how you can handle the click event of a button:

<Button Click="Button_Click"></Button>

And yes, you must define the Button_Click method in your code-behind file (note that you could do it inline – ie, in the XAML file – if you’re using WPF). I must confess that I’m not really a fan of this approach since I prefer to put all my code in the code-behind file. For making it work, I’ll need to change the previous code slightly by adding a name to the button:

<Button x:Name="bt"></Button>

And now, from within the constructor, I can setup my event handler like this:

bt.Click += Button_Click;

Final note: in the real world, I’ll probably end up with a Lambda expression for simple handlers. As you can see, setting up handlers from the XAML is possible (the syntax is the same as you’ve got for props) but I don’t really recommend it. And that’s it for now. In the next post, we’ll talk about Silverlight’s markup extension support. Stay tuned.

Nov 19

Protected: How to build types that can be consumed from XAML

Posted in Silverlight, XAML       Comments Off on Protected: How to build types that can be consumed from XAML

This content is password protected. To view it please enter your password below:

Nov 19

Associating XAML namespaces to CLR namespaces

Posted in Silverlight, XAML       Comments Off on Associating XAML namespaces to CLR namespaces

Take a look at the following (simple) XAML:

<UserControl x:Class="SilverlightApplication1.MainPage"
    xmlns=
"http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Canvas x:Name="myCanvas"> </Canvas> </UserControl>

When I started talking about XAML, I said that the default XAML namespace is associated to several controls. You might be a little curious on how this is done. By using Reflector, you’ll see that many of the Silverlight assemblies associate CLR namespaces to XAML namespaces through the XmlnsDefinitionAttribute:

xmlnsdefinitionattribute

You’ll typically find this attribute in most assemblies that have been thought with Silverlight and WPF in mind. Notice, though, that its use isn’t mandatory to map a CLR namespace to XAML namespace because Silverlight (and WPF) supports a special mechanism for doing that. For instance, suppose you’ve got a type called BeautifulGrid, defined in the CLR Test namespace, in a Dumb assembly. Now, when you build the assembly, you didn’t knew anything about the XmlnDefinitionAttribute. How can you use the BeautifulGrid in your XAML file? Here’s the answer:

<UserControl x:Class="SilverlightApplication1.MainPage"
    xmlns=
"http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:my="clr-namespace:Test;assembly=Dumb"> <Canvas x:Name="myCanvas"> <my:BeautifulGrid> </my:BeautifulGrid> </Canvas> </UserControl>

There are some interesting gotchas  you should keep in mind when using this syntax:

  • the clr-namespace key is separated from its associated value by a semi-colon (:) while the assembly part of the expression uses an equal sign (=)
  • this is one of those places where you *can’t* use white spaces for improved readability;
  • you can omit the assembly part if the namespace you want to use is in the same assembly as the “current” XAML file.

Even though Silverlight supports the XmlnsDefinitionAttribute, the truth is that it doesn’t really play an important role for using custom types in Silverlight. The recommended approach for using custom types in XAML is to use the clr-namespace approach I’ve showed above.

And that’s it for now. Stay tuned for more in Silverlight.

Nov 18

XAML languages features

Posted in Silverlight, XAML       Comments Off on XAML languages features

As I’ve said before, Silverlight supports only a subset of the existing XAML keywords you can use in WPF. Here’s the list of keywords you can use in your Silverlight:

  • x:Class: you can apply this attribute to the root element of the XAML file (or object tree) that is going to be “compiled”. When you apply this attribute, you’ll end up creating a partial class (named after the value you’ve passed to the attribute) which is joined with the associated code-behind file. Even though you don’t really have to use this attribute, the truth is that you’ll probably use them in 99% of your XAML files;
  • x:Key: as you’ve seen in the previous post, you can use this attribute to set the key of a dictionary’s entry of a resource dictionary;
  • x:Name: used for identifying an object so that it can be easily recovered from the code-behind file. The “practical effect” of using this attribute is that you’ll end up having a field in the code-behind file which references the element you’ve defined on the XAML file. As you can see on the docs, you’re limited in the values you can pass to this attribute. It goes without saying that you must ensure uniqueness through the names you give to the elements;
  • x:Null: this *extension* is used for setting the value of a property to null. You can use this extension with the property element or attribute syntax.

The best way to understand these attributes is to build a demo user control and see what happens after everything is compiled. For instance, lets assume that we’re adding a new Silverlight User Control to an existing Silverlight application (this will let me show what happens when you use the x:Class and x:Name attributes). By doing that, we end up with two files: a XAML and its corresponding code-behind CS file (shown in the next figure).

xamlandcodebehind

Here’s the default generated XAML (I’ve removed the unnecessary namespaces):

<UserControl
 x:Class="SilverlightApplication1.SilverlightControl1"
 xmlns=
"http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400"> <Grid x:Name="LayoutRoot" Background="White"> </Grid> </UserControl>

If you look at the properties of the XAML file, you’ll see that it looks like this:

xamlprops

The default configuration ends up embedding the XAML file in the assembly (check the next image):

xamlresources

You’ll also get a new C# file (.g.cs) from the XAML “compilation” (onde again, I’ve edited the code before pasting it here):

namespace SilverlightApplication1 {
 public partial class SilverlightControl1 : 
System.Windows.Controls.UserControl { internal System.Windows.Controls.Grid LayoutRoot; private bool _contentLoaded; [System.Diagnostics.DebuggerNonUserCodeAttribute()] public void InitializeComponent() { if (_contentLoaded) { return; } _contentLoaded = true; System.Windows.Application.LoadComponent(
this, new System.Uri(
"/SilverlightApplication1;” +
“component/SilverlightControl1.xaml"
,
System.UriKind.Relative)); this.LayoutRoot = ((System.Windows.Controls.Grid)
(
this.FindName("LayoutRoot"))); } } }

There are several interesting things going on here:

  • the x:Class attribute is responsible for the creation of the partial class defined in the .g.cs file;
  • all the named elements (ie,all the elements that use the x:Name attribute) get added to this partial class as fields. Notice that the FindName method is used for grabbing a reference to an element that is defined through the XAML file;
  • the LoadComponent method is used for loading the XAML defined in the XAML file. In this case,the generated code is getting the embedded XAML file from the SiverlightApplication 1 assembly.

by now, you should be able to understand why you can use the same name you’ve used for the x:Name attribute to access that element from a code-behind file. 

As you’ve seen, you can access the XAML elements from your code behind because building a Silverlight project ends up generating a partial class which introduces fields with the same name as the ones you used for the elements defined through XAML. THis is only possible due to the use of the x:Class and x:Name attributes.

And that’s it for now. Stay tuned for more on Silverlight.

Nov 18

XAML and collections

Posted in Silverlight, XAML       Comments Off on XAML and collections

We’ve already talked about several features related to XAML. In this post, we’ll keep going and we’ll see how to specify collections in XAML. There are two basic types of collections you can use in XAML: lists and dictionaries. Before going on, it’s important to understand that you’re not really creating new collections in XAML; instead, we’re adding items to existing collections (in other words, if you’re building an object which has a collection like property and you want it to be set from XAML, then don’t forget to make sure that the getter returns a valid reference to a collection object).

“List collections” are collections which expose an Add method (generally, we’re speaking about objects which implement the IList interface). In these cases, you’ll typically put the elements within the collection property and the XAML parser will create an object that represents each item before adding them to that collection through the Add method:

<Rectangle Width="300" Height="150">
    <Rectangle.Fill>
      <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
        <LinearGradientBrush.GradientStops>
          <GradientStop Color="White" Offset="0" />
          <GradientStop Color="Black" Offset="1" />
        </LinearGradientBrush.GradientStops>
      </LinearGradientBrush>
    </Rectangle.Fill>
</Rectangle>

Btw, we could have simplified the XAML because GradientStops is the content property for the LinearGradientBrush object:

<Rectangle Width="300" Height="150">
    <Rectangle.Fill>
      <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
       <GradientStop Color="White" Offset="0" />
       <GradientStop Color="Black" Offset="1" />
      </LinearGradientBrush>
    </Rectangle.Fill>
</Rectangle>

You can always write the previous code in C# (assume rect is a reference to the rectangle):

rect.Fill = new LinearGradientBrush()
{
    StartPoint = new Point(0,0),
    EndPoint = new Point(1, 1),
    GradientStops = {
             new GradientStop()
            {
                Color = Colors.White,
                Offset = 0
            }
            ,
            new GradientStop()
            {
                Color = Colors.Black,
                Offset = 1
            }
    }
};

Dictionaries are a different kind of collection: in these cases, each entry is a pair composed by a key and a value. The important thing here is understanding that you specify the key through the x:key attribute:

<UserControl.Resources>
    <Color x:Key="Black" A="0" B="0" G="0" />
</UserControl.Resources>

For now, lets forget that we’re specifying resources and we’ll only concentrate on the syntax. As you can see, we added a tag which identifies the resource as a color and we’re identifying it with the word Black (ie, Black is the key that identifies this entry). Once again, you could translate the previous code into C# (Resources is an object of type ResourceDictionary), but I’ll leave it to you (if you don’t have anything better to do, that is 🙂 )

Notice x:Key is one of the few XAML keywords Silverlight supports. Besides it, there’s also the x:Class, the x:Name and x:Null attributes (we’ll come back to them in a future post). If you’re coming from WPF, then this might seem limited at first, but it’s all we have in Silverlight.

And I guess this sums it up for now. Stay tuned for more on Silverlight.

Nov 18

Type converter on Silverlight

Posted in Silverlight, XAML       Comments Off on Type converter on Silverlight

Today we’ll talk a little bit about the role played by type converters in “transforming” XAML into C# objects. Here’s a quick example:

<Button xmlns=
"http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="bt" Click="bt_Click" Width="100" Content="Say Hi" Background="Red" />

If you look carefully, you’ll see that Background expects a Brush object. All XAML attribute are strings by default. In  other words, you’d need the following C# code to set the background of the button:

bt.Background = new SolidColorBrush(Colors.Yellow);

So, what’s going on here? Well, it’s simple: the parser uses a type converter to convert the string into the correct object. In practice, type converters are objects which inherit from TypeConverter class. You can associate a type converter to a type or to a property by using the TypeConverterAttribute. The parser will respect that option and will use the indicated type converter to translate the string into the expected object type.

Now, unlike WPF, where everything is really based on managed type converters, in Silverlight, there is an *unmanaged* type converter which is used for performing most of the common conversions you’d expect to happen (take a look at the internal SilverlightTypeConverter class and you’ll notice that you’ll end up using the “unmanaged” XcpImports type).

So, don’t expect to find many type converters by firing up .NET Reflector. Btw, you should keep in mind that you can still build and use your own type converters for your types. The XAML parser will always check the current property and/or type and if it’s associated with a managed type converter,it will honor that relationship and your converter will be used.

And I guess it’s all for now. Stay tuned for more on Silverlight.

Nov 17

XAML: using content properties

Posted in Silverlight, XAML       Comments Off on XAML: using content properties

In the previous post, we’ve seen that we can use one of two approaches for setting the value of a property: we can use the property element or the attribute syntax (and, as we’ve seen in the previous post, you can’t use them both interchangeably). In this post, we’ll keep going and we’ll see how content properties simplify even more the markup we need to write to setup the value of a property.

For instance, here’s how I’d set the Content of a button to an image:

<Button xmlns=
"http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="bt" Click="bt_Click" Width="100"> <Image Source="/p52.jpg" Stretch="UniformToFill" /> </Button>

If you compare this snippet with the one we had before, you’ll notice that we’re not using the <Button.Content> markup element to specify that we’re setting the Content property. Why?

To understand what’s going on, we need to talk a little bit about content properties. Any class can designate a property that should be set to whatever content is inside the XML element. As you’ve probably guessed, these properties are called content properties.

In the case of the Button class, its content property is the Content property. Specifying a content property is done through the ContentPropertyAttribute. For instance, in the case of the Button element, we need to look at the ContentControl class (used as base) to see how the content property is defined:

[ContentProperty("Content",true)]
public class ContentControl : Control
{

Whenever you see this attribute,you know that the content of element is directly “transformed” and copied to the indicated property. And that’s it for now. Stay tuned for more on Silverlight.

Nov 17

In the previous post, we’ve started looking at same basic XAML. At the time, we’ve defined a simple button by using the following syntax:

<Button xmlns=
"http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="bt" Content="Say hi" Click="bt_Click" />

In the previous snippet, we’re setting the Content property and the Click event. Btw, and in case you’re wondering, events are set up before the properties. This is the only thing you can take for granted (you can’t really depend on the order of the attributes in your XAML to influence the order by which properties are set). This makes sense because it means that eventual handlers will be called if an event is generated by setting a property to a specific value.

If you look at Content’s definition, you’ll see that it expects an object. That means we can, for instance, pass it an image instead of setting it to text:

<Button xmlns=
"http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="bt" Click="bt_Click" Width="100"> <Button.Content> <Image Source="/p52.jpg" Stretch="UniformToFill" /> </Button.Content> </Button>

The previous snippet is showing the property element syntax. You should use it whenever you can’t use a simple string to define the value of a property. Property element syntax is really simple: you define a property by combining the name of the element with the name of the property. Property element syntax and attribute syntax are the two options you’ve got for setting the value of a property in XAML (sort of: we’ll leave content properties and collection properties to a future post).

In case you’re wondering, you can’t use something like this in Silverlight:

<Button xmlns=
"http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="bt" Click="bt_Click" Width="100"> <Button.Content> Say Hi </Button.Content> </Button>

If you try loading the previous XAML, you should get an exception which says something like “Say Hi isn’t allowed as the button’s content”. In case you’re wondering, this does work in WPF. Unfortunately,in Silverlight you’ll have to use the attribute syntax for setting the value of the Content to a string.

In this cases,you do need to use another element. Here’s the code you can use for setting the Content’s property to text through the property element syntax:

<Button xmlns=
"http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="bt" Click="bt_Click" Width="100"> <Button.Content> <TextBlock>Say Hi</TextBlock> </Button.Content> </Button>

Fair enough: this isn’t really similar to what we had before, but it’s really the only way to set the button’s Content property to something that looks like text (notice that in this case, the Content is set to another FrameworkElement and not to a simple string).

Understanding why something works in WPF and not in Silverlight is not complicated: you just need to keep in mind that all the features considered not essential were removed in order to control the size of the Silverlight framework. And it looks like this was one of them…

You must be wondering which syntax you should use when you want to set the value of a property. Sometimes, the answer is simple since we’ve seen a case where you can’t use both syntaxes for setting a specific value. When both approaches are supported, I’ll tend to use the one which is more compact (typically, this means going with the attribute syntax whenever possible).

And I guess this wraps it up for now. Stay tuned for more on Silverlight.