EditCategory
XAML
EditQuestion
How do I declaratively create an object collection in XAML?
EditAnswer
First, if you want to declare a collection of custom class types, you'll have to create the custom class in code. You cannot define a new class in XAML.
There are four ways to declare a CLR object collection in XAML: x:Array, ArrayList, standard XAML declarations, and the CollectionViewSource class. We'll discuss each one here.
As stated previously, if you want to create a collection of a custom type, you will have to define it beforehand in code. The code snippets of this article assume that the following class is defined:
namespace WindowsApplication1
{
public class Composer
{
public Composer()
{
}
public string Name
{
get { return m_name; }
set { m_name = value; }
}
public int Birth
{
get { return m_birth; }
set { m_birth = value; }
}
private string m_name;
private int m_birth;
}
}
x:Array
This class is a markup extension of the XAML namespace that specifically allows the creation of an object list in XAML without having to define a Collection class in code. Note, however, that it is usually wiser to have such a class, particularly if you want a strongly typed collection that supports the INotifyPropertyChanged (to advise the binding of changes in the collection). Typically, that would be an ObservableCollection-derived class.
Using "x:Array" is quite straigthforward. Here's an example:
<Window x:Class="WindowsApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:custom="clr-namespace:WindowsApplication1"
Title="WindowsApplication1"
Height="300"
Width="300"
>
<Window.Resources>
<x:Array x:Key="ComposerList" Type="{x:Type custom:Composer}">
<custom:Composer Name="Mozart, Wolfgang Amadeus" Birth="1756"/>
<custom:Composer Name="Górecki, Henryk Mikolaj" Birth="1933"/>
<custom:Composer Name="Massenet, Jules" Birth="1842"/>
</x:Array>
<DataTemplate x:Key="ComposerTemplate">
<TextBlock Text="{Binding Path=Name}"/>
</DataTemplate>
</Window.Resources>
<StackPanel>
<ListBox ItemTemplate="{StaticResource ComposerTemplate}">
<ListBox.ItemsSource>
<Binding Source="{StaticResource ComposerList}" Path="Items"/>
</ListBox.ItemsSource>
</ListBox>
</StackPanel>
</Window>
ArrayList
The well-known ArrayList CLR class could also be used similarly to x:Array, but it is somewhat less concise to use.
First, add the following namespace mapping:
xmlns:coll="clr-namespace:System.Collections;assembly=mscorlib"Then, we only need to modify the previous snippet slightly:
<coll:ArrayList x:Key="ComposerCollection">
<custom:Composer Name="Mozart, Wolfgang Amadeus" Birth="1756"/>
<custom:Composer Name="Górecki, Henryk Mikolaj" Birth="1933"/>
<custom:Composer Name="Massenet, Jules" Birth="1842"/>
</coll:ArrayList>
And modify the binding:
<Binding Source="{StaticResource ComposerCollection}"/>Standard XAML
If you have a custom collection definition, you could use it directly in XAML syntax. This produces more readable XAML. Here, a ComposerCollection has been defined in code and is used as follows:
<custom:ComposerCollection x:Key="ComposerCollection">
<custom:Composer Name="Mozart, Wolfgang Amadeus" Birth="1756"/>
<custom:Composer Name="Górecki, Henryk Mikolaj" Birth="1933"/>
<custom:Composer Name="Massenet, Jules" Birth="1842"/>
</custom:ComposerCollection>
CollectionViewSource
CollectionViewSource is entirely different. It is not used to create a collection but rather to allow sorting, filtering and grouping on an existing collection. Naturally, this collection can be created in code-behind or can use an x:Array as demonstrated above.
To have a collection view sorted by composer name using the same code as the "x:Array" example, we only have to do the following:
- Add the following reference
xmlns:compModel="clr-namespace:System.ComponentModel;assembly=WindowsBase" - Add the following resource
<CollectionViewSource Source="{Binding Source={StaticResource ComposerList}, Path=Items}"
x:Key="ComposerViewSource">
<CollectionViewSource.SortDescriptions>
<compModel:SortDescription PropertyName="Name"/>
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
- Modify the Binding of the ListBox
<Binding Source="{StaticResource ComposerViewSource}"/>Of course, you are not limited to "x:Array" and can create a CollectionViewSource based on a list created by any of the three previously presented methods.
Geometry Homework