开发者

ListBox binding DataTemplate item to ItemsPanel Canvas.Left/Top

开发者 https://www.devze.com 2023-04-10 14:52 出处:网络
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

I have a ListBox with a Canvas ItemsPanel. Items in this list are LabeledArrows:

ListBox binding DataTemplate item to ItemsPanel Canvas.Left/Top

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="{B开发者_Python百科inding 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.Left and Canvas.Top on 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 the Canvas. The container uses the DataTemplate to display its content.

To do that add this to your 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>


Just a wild guess...

  1. You could wrap your LabledArrow children in a Canvas instead of Grid
  2. Then make your coordinates at TextBlock relative to that local Canvas by subtracting... Box_X and Start_X and Box_Y and Start_Y (using multibinding and a converter to do so)

I think it will be mounted to a relative canvas at the coordinates you aspire... isnt it?

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号