Skip Navigation LinksHome > View Post

Using Binding to position a Collection of elements - Take 2

Back in October 2007 (wow, that long ago!) I blogged about how to use binding to position a collection of elements within an ItemsControl.

I talked about how Canvas.Top and Canvas.Left wouldn't work when applied directly to the element because of that isn't the child of the ItemPanel - a contentpresenter gets in the way.

I love it when you work with a technology for a long time, think you know most there is to know and come across something so stupidly obvious you're stunned and delighted. This happened the other day.

I was aware of ItemsControl's ItemContainerStyle property that would be applied to the resulting ContentPresenters, but I'd never considered using Binding in that style. Guess what? It just totally works. Of course it does. D'oh.

Here's a much better solution to the one proposed in that previous post:

<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:draw="clr-namespace:System.Drawing;assembly=System.Drawing">

    <Page.Resources>
        <x:Array x:Key="myArray" Type="{x:Type draw:Point}">
            <draw:Point X="10" Y="20"/>
            <draw:Point X="20" Y="10"/>
            <draw:Point X="30" Y="50"/>
        </x:Array>
    </Page.Resources>

    <ItemsControl ItemsSource="{Binding Source={StaticResource myArray}, Path=.}">
        <ItemsControl.ItemContainerStyle>
            <Style>
                <Setter Property="Canvas.Top" Value="{Binding Y}" />
                <Setter Property="Canvas.Left" Value="{Binding X}" />
            </Style>
        </ItemsControl.ItemContainerStyle>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Rectangle Fill="Red" Width="10" Height="10" />
            </DataTemplate>
        </ItemsControl.ItemTemplate>
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas IsItemsHost="True" />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>

</Page>

The example above is Kaxaml-ready for your delectation.

Tags: WPF

 
Josh Post By Josh Twist
1:09 AM
25 Jun 2009

» Next Post: Exciting changes afoot in Ukadc.Diagnostics
« Previous Post: Windows Search and the file scheme

Comments are closed for this post.

Posted by Mark Heath @ 25 Jun 2009 3:05 AM
Nice post, this technique will be very useful for something I am trying to build. Not quite kaxaml ready yet though - I needed to add the draw namespace:

xmlns:draw="clr-namespace:System.Drawing;assembly=System.Drawing"

Posted by josh @ 25 Jun 2009 3:09 AM
Ta - updated.

Posted by Mike Fox @ 13 Jan 2010 7:12 PM
this is great, and i'm using josh smiths dragpanel because it implements this logic nicely. However, I run into a bug with both sets of code - the binding only works one way. I need the drag to change the x value of the underlying object. Have you come across a solution?

© 2005 - 2014 Josh Twist - All Rights Reserved.