我正在尝试在WPF中创建一个View,并且很难弄清楚如何设置它。这是我正在努力建立的:
所以这对我来说似乎很复杂。似乎时间轴上的每个项目都必须呈现其自己的线段。没关系。但是项目顶部与线条之间的距离(以及项目底部与线条之间的距离)可能会有所不同。如果一个项目从顶部向下50 px,而下一个项目从顶部向下100 px,那么第一个项目需要50 px的填充,以便线段加起来。
我想我可以解决这个问题,但是,如果这两个项目在WrapPanel的同一行上,我们只需要添加填充!假设有5个项目,屏幕上只有3个空间... WrapPanel将把另外两个放在下一行。没关系,但这意味着只有前3个需要填充,最后2个需要填充。
这让我很头疼。还有其他方法我可以看一下吗?
编辑:我倾向于使用继承自Canvas的自定义面板替换WrapPanel,并覆盖MeasureOverride和ArrangeOverride方法。
答案 0 :(得分:2)
理想的解决方案可能是使用Adorners。在AdornerLayer上,您可以为Panel上的每个项目设置一个自定义Adorner(您可以在DataTemplate中定义它)。您将能够检索每个项目的位置(Adorner的Boundingbox)。同样在AdornerLayer上,您将在这些边界框之间绘制线条。 使用此解决方案,您可以按照您想要的任何方式布置项目(使用您想要的任何面板),项目仍将与线条连接。
很久以前我将这种方法用于图形可视化工具。可以以任何方式布置仲裁UIElements的节点。与行连接的项目。
要使所有项目完美对齐,您可以使用Canvas作为ItemTemplate中的根面板。 Canvas可以是0x0单位。然后,您将在Canvas周围排列元素。画布成为您的参考点。该行顶部的所有内容都将获得负面的Canvas.Top值。 另一种方法是使用负边距,该边距限制在线上的顶部和底部控件的高度。使用IValueConverter(高度* -1)反转高度。
答案 1 :(得分:1)
这不会解决你的问题,但我敢打赌它会简化它:
尝试定义看起来像这样的DataTemplate
:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" SharedSizeGroup="Top"/>
<RowDefinition Height="10"/>
<RowDefinition Height="Auto" SharedSizeGroup="Bottom"/>
</Grid.RowDefinitions>
<ContentControl Grid.Row="0" Content="{Binding TopAnnotations}/>
<Rectangle Fill="Black" Grid.Row="1" Margin="0,4,0,4"/>
<ContentControl Grid.Row="1" Height="10" Content="{Binding GraphicObject}"/>
<ContentControl Grid.Row="2" Content="{Binding BottomAnnotations}"/>
</Grid>
现在创建一个ItemsControl
,ItemsPanelTemplate
是一个水平WrapPanel
,Grid.IsSharedSizeScope
附加属性设置为True。当然,您还需要为注释和图形对象属性包含的内容定义数据模板。
你仍然遇到这样的问题:当WrapPanel
换行中的项目时,时间轴上方和下方的对象具有相同的填充,而不管它们实际需要在{{1 }}。因此,为了获得我认为你正在寻找的效果,你仍然需要谨慎对待并安排 - 基本上,你不会创建一个单独的WrapPanel
,而是创建一些将这些项放入{ {1}}在每个“行”上,每个“行”都是自己的共享大小范围。但实际上,测量和排列时间轴项目的高度并不是您需要担心的事情。您只需要它们的宽度(这样您的逻辑就可以确定何时换行)。 WrapPanel
会为您计算高度。