ListBox绑定DataTemplate项目到ItemsPanel Canvas.Left / Top

时间:2011-10-05 08:56:46

标签: wpf binding datatemplate

我有一个带有Canvas ItemsPanel的ListBox。此列表中的项目为LabeledArrows:Labeled arrow example

LabeledArrow只是一个视图模型类(非可视化),它暴露了Start_X,Start_Y(箭头开始),End_X,End_Y(箭头)和Box_X,Box_Y(box possition)等属性LabeledArrow的ListBoxItem DataTemplate如下所示。
ArrowLine X1,Y1,x2,Y2与LabeledArrow Start_X,Start_Y等属性的绑定工作正常,因为ArrowLine具有公开的坐标属性(X1等)。然而,这个盒子只是TextBlock,所以我必须以某种方式设置Canvas.Top和Canvas.Left附加属性才能实现它 - 但是如下所示的绑定不起作用。
有任何想法吗? 我是否需要将LabeledArrow包装为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>

2 个答案:

答案 0 :(得分:2)

您在TextBox上设置附加属性Canvas.LeftCanvas.Top,但TextBox的父级是Grid。附加属性有时用于告诉控件的父级如何布局此元素。例如,Canvas,Grid和DockPanel就是这样做的。你想要的是在项容器上设置两个属性,它是Canvas的直接子项。容器使用DataTemplate显示其内容。

为此,请将此添加到ListBox

<ListBox.ItemContainerStyle>
    <Style>
        <Setter Property="Canvas.Left" Value="{Binding Path=Box_X}"/>
        <Setter Property="Canvas.Top" Value="{Binding Path=Box_Y}"/>
    </Style>
</ListBox.ItemContainerStyle>

答案 1 :(得分:0)

只是猜测......

  1. 您可以将LabledArrow个孩子包裹在Canvas而不是Grid
  2. 然后通过减去...... TextBlockCanvas以及Box_XStart_X,将您的坐标设为Box_Y相对于当地Start_Y的坐标 (使用多重绑定和转换器来执行此操作)
  3. 我认为它将被安装在你渴望的坐标上的相对画布上......不是吗?