XAML—Using Types from Other Namespaces


Jump to: navigation, search
CSharp-Online.NET:Articles
.NET Articles

XAML

© 2007 Matthew MacDonald

Using Types from Other Namespaces

So far, you’ve seen how to create a basic user interface in XAML using the classes that are a part of WPF. However, XAML is designed as an all-purpose way to instantiate .NET objects, including ones that are in other non-WPF namespaces and those you create yourself.

It might seem odd to consider creating objects that aren’t designed for onscreen display in a XAML window, but there are a number of scenarios where it makes sense. One example is when you use data binding and you want to draw information from another object to display in a control. Another example is if you want to set the property of a WPF object using a non-WPF object.

For example, you can fill a WPF ListBox with data objects. The ListBox will call the ToString() method to get the text to display for each item in the list. (Or for an even better list you can create a data template that extracts multiple pieces of information and formats them appropriately.)

In order to use a class that isn’t defined in one of the WPF namespaces, you need to map the .NET namespace to an XML namespace. XAML has a special syntax for doing this, which looks like this:

xmlns:Prefix=”clr-namespace:Namespace;assembly=AssemblyName”

Typically, you’ll place this namespace mapping in the root element of your XAML document, right after the attributes that declare the WPF and XAML namespaces. You’ll also fill in the three italicized bits with the appropriate information, as explained here:

  • Prefix is the XML prefix you want to use to indicate that namespace in your XAML markup. For example, the XAML language uses the x: prefix.
  • Namespace is the fully qualified .NET namespace name.
  • AssemblyName is the assembly where the type is declared, without the .dll extension. This assembly must be referenced in your project. If you want to use your project assembly, leave this out.

For example, here’s how you would gain access to the basic types in the System namespace and map them to the prefix sys:

xmlns:sys="clr-namespace:System;assembly=mscorlib"

Here’s how you would gain access to the types you’ve declared in the MyProject namespace of the current project and map them to the prefix local:

xmlns:local="clr-namespace:MyNamespace"

Now, to create an instance of a class in one of these namespaces, you use the namespace prefix:

<local:MyObject ...></local:MyObject>

Tip Remember, you can use any namespace prefix you want, as long as you are consistent throughout your XAML document. However, the sys and local prefixes are commonly used when importing the System namespace and the namespace for the current project. You’ll see them used throughout this book.


Ideally, every class you want to use in XAML will have a no-argument constructor. If it does, the XAML parser can create the corresponding object, set its properties, and attach any event handlers you supply. XAML doesn’t support parameterized constructors, and all the elements in WPF elements include a no-argument constructor. Additionally, you need to be able to set all the details you want using public properties. XAML doesn’t allow you to set public fields or call methods.

If the class you want to use doesn’t have a no-argument constructor, you’re in a bit of a bind. If you’re trying to create a simple primitive (such as a string, date, or numeric type), you can supply the string representation of your data as content inside your tag. The XAML parser will then use the type converter to convert that string into the appropriate object. Here’s an example with the DateTime structure:

<sys:DateTime>10/30/2010 4:30 PM</sys:DateTime>

This works because the DateTime class uses the TypeConverter attribute to link itself to the DateTimeConverter. The DateTimeConverter recognizes this string as a valid DateTime object and converts it. When you’re using this technique you can’t use attributes to set any properties for your object.

If you want to create a class that doesn’t have a no-argument constructor and there isn’t a suitable type converter to use, you’re out of luck.


Note Some developers get around these limitations by creating custom wrapper classes. For example, the FileStream class doesn’t include a no-argument constructor. However, you could create a wrapper class that does. Your wrapper class would create the required FileStream object in its constructor, retrieve the information it needs, and then close the FileStream. This type of solution is seldom ideal because it invites hard-coding information in your class constructor and it complicates exception handling. In most cases, it’s a better idea to manipulate the object with a little event handling code and leave it out of your XAML entirely.


The following example puts it all together. It maps the sys: prefix to the System namespace and uses the System namespace to create three DateTime objects, which are used to fill a list:

<Window x:Class="WindowsApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:sys="clr-namespace:System;assembly=mscorlib"
    Width="300" Height="300"
    >
  <ListBox>
    <ListBoxItem>
      <sys:DateTime>10/13/2010 4:30 PM</sys:DateTime>
    </ListBoxItem>
    <ListBoxItem>
      <sys:DateTime>10/29/2010 12:30 PM</sys:DateTime>
    </ListBoxItem>
    <ListBoxItem>
      <sys:DateTime>10/30/2010 2:30 PM</sys:DateTime>
    </ListBoxItem>
  </ListBox>
</Window>


Previous_Page_.gif Next_Page_.gif


Personal tools