I have a ListBox with a Canvas ItemsPanel. Items in this list are LabeledArrows:
LabeledArrow is just a view model class (non visual) that exposes properties like Start_X, Start_Y (arrow start), End_X, End_Y (arrow head) and Box_X, Box_Y (box possition) The ListBoxItem DataTemplate for the LabeledArrow is shown below.
The binding of ArrowLine X1, Y1, x2, Y2 to LabeledArrow Start_X, Start_Y etc properties works fine because ArrowLine has exposed coordinate properties (X1 etc). The box however is just TextBlock so I have to somehow set Canvas.Top and Canvas.Left attatched properties to possition it – but the binding as its shown below doesn’t work.
Any ideas? Do I need to resort to wrapping LabeledArrow up as a UserControl?
<ListBox.Resources>
<DataTemplate DataType="{x:Type tp:LabledArrow}">
<Grid>
<tp:ArrowLine Stroke="Red" StrokeThickness="2"
X1="{Binding Path=Start_X}" Y1="{Binding Path=Start_Y}"
X2="{Binding Path=End_X}" Y2="{Binding Path=End_Y}" />
<TextBlock Text="{Binding Path=Value}"
**Canvas.Left="{Binding Path=Box_X}"
Canvas.Top="{Binding Path=Box_Y}"** />
</Grid>
</DataTemplate>
</ListBox.Resources>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<Canvas IsItemsHost="True" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
You set the attached properties
Canvas.LeftandCanvas.Topon your TextBox, but the parent of the TextBox is a Grid. Attached properties are sometimes used to tell the parent of the Control how to layout this element. Canvas, Grid and DockPanel do that for example. What you want is set both properties on the item container, which is the direct child of theCanvas. The container uses the DataTemplate to display its content.To do that add this to your ListBox