UPDATE - here's a much better way to solve this:
Using Binding to position a Collection of elements - Take 2
I was recently looking at a WPF query with my new colleague
Simon Ince (check out his first MSDN blog post on
CTE in SQL 2005).
The question was along the lines of
"How can I position a collection of elements on a canvas using databinding? The number of elements is unknown at design time".
Wherever we have an unknown number of items in a collection your attention is normally going to turn to using an ItemsControl. In this case we'd probably want to swap the ItemsPanel for a Canvas and then we can databind away, right?
Here's an example in pure Xaml. Note that we create an array of System.Drawing.Points in Xaml to bind to.
<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.ItemTemplate>
<DataTemplate>
<Rectangle Canvas.Top="{Binding Y}" Canvas.Left="{Binding X}" Fill="Red" Width="10" Height="10"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas IsItemsHost="True" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Page>
However, as you can see from the render in XamlPad, this isn't working. The visual tree shows why...

The ItemsControl wraps each item in a ContentPresenter and, as you know, Canvas's attached Top and Left properties only work on direct children of the canvas. Time for another approach.
Let's use a transform, a translate transform to be specific.
<Rectangle Fill="Red" Width="10" Height="10">
<Rectangle.RenderTransform>
<TranslateTransform X="{Binding X}" Y="{Binding Y}" />
</Rectangle.RenderTransform>
</Rectangle>

That's better.
Another option would be to modify the Margin of the rectangle something like this:
<Rectangle Fill="Red" Width="10" Height="10">
<Rectangle.Margin>
<Thickness Left="{Binding X}" Top="{Binding Y}" />
</Rectangle.Margin>
</Rectangle>
Of course
this won't work because the Thickness's Left and Top properties aren't DependencyProperties and therefore can't be the target of a binding. That doesn't rule this out as an option, you'd just have to write an IMultiValueConverter and a MultiBinding as discussed at the end of
Reason 2. Databinding.

Post By
Josh Twist
5:39 AM
31 Oct 2007
» Next Post:
Reason 6. Layout
« Previous Post:
Binding to Attached Properties
Comments are closed for this post.
Posted by
Peter
@
08 Sep 2008
2:54 PM
Do you know of any code that illustrates a bar graph that uses adorners to adjust the bars by dragging? Additionally, I would like the polys bound so as they adjust, their positions can be used via convertors to determine their X/Y values?
Thanks!