Nico Vuyge's blog

Taking the blue AND the red pill

Databinding a position in Avalon.

Nico Vuyge

If you try to position an list of Avalon elements via databinding on an ItemsControl, you may find out that the obvious thing to do doesn't work: If you create a DataTemplate and databind to the Canvas.Top and Canvas.Left properties in the DataTemplate, you'll see that these properties are effectively ignored. The trick to solve this is to set these properties via the ItemContainerStyle of your ItemsControl, as you can see in the following sample:

(Update 28 Jan 2007: Rob Relyea notified me that the sample still contained references to the beta WPF namespaces, this has now been corrected.)

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Page3">
  <Page.Resources>
    <XmlDataProvider x:Key="myData" XPath="/Data">
      <Data xmlns="">
        <Item>
          <X>100</X>
          <Y>100</Y>
          <Width>50</Width>
          <Height>50</Height>
        </Item>
        <Item>
          <X>200</X>
          <Y>200</Y>
          <Width>50</Width>
          <Height>50</Height>
        </Item>
        <Item>
          <X>300</X>
          <Y>300</Y>
          <Width>50</Width>
          <Height>50</Height>
        </Item>
      </Data>
    </XmlDataProvider>
    <DataTemplate x:Key="myDataTemplate">
      <Border Width="{Binding XPath=Width}" Height="{Binding XPath=Height}" BorderBrush="Black" BorderThickness="1,1,1,1">
      </Border>
    </DataTemplate>
  </Page.Resources>
  <StackPanel Orientation="Vertical">
    <ItemsControl ItemTemplate="{StaticResource myDataTemplate}" ItemsSource="{Binding Source={StaticResource myData}, XPath=Item}">
      <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
          <Canvas Height="500"></Canvas>
        </ItemsPanelTemplate>
      </ItemsControl.ItemsPanel>

      <ItemsControl.ItemContainerStyle>
        <Style TargetType="{x:Type ContentPresenter}">
          <Setter Property="Canvas.Left" Value="{Binding XPath=X}">
          <Setter Property="Canvas.Top" Value="{Binding XPath=Y}">
        </Style>
      </ItemsControl.ItemContainerStyle>
    </ItemsControl>

  </StackPanel>
</Page>

This sample draws 3 rectangles diagonally on the canvas by databinding the X and Y position to the Canvas.Left and Canvas.Top properties. You can see the end result in the following screenshot:

Databinding the X and Y position