【发布时间】:2018-07-15 05:49:27
【问题描述】:
我将Canvas 高度绑定到第一个孩子的高度,以便可以正确布局,布局示例:
<StackPanel>
<Canvas Height="{Binding Children[0].ActualHeight , RelativeSource={RelativeSource Self}}">
<Rectangle Height="100" Width="100" Fill="Red" />
</Canvas>
<TextBlock Text="Text" />
</StackPanel>
不绑定Canvas.Height值为0,这样“Text”重叠,有绑定——文本在indesigner下(你可以自己试试)。
但是在运行时绑定失败并且文本重叠。
System.Windows.Data 错误:17:无法从“Children”(类型“UIElementCollection”)获取“Item[]”值(类型“UIElement”)。 BindingExpression:Path=Children[0].ActualHeight;数据项='画布'(名称='');目标元素是 'Canvas' (Name='');目标属性为“Height”(类型“Double”) ArgumentOutOfRangeException:'System.ArgumentOutOfRangeException: 指定的参数超出了有效值的范围。
为什么?我可以在运行时有设计器时的行为吗?
我希望不给孩子一个x:Name 并使用ElementName 进行绑定。
这里有更好的 MCVE:
<ListBox>
<TextBlock Text="1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1" />
<TextBlock Text="2" />
<TextBlock Text="3" />
<Canvas Height="100">
<TextBlock Canvas.Left="{Binding HorizontalOffset, RelativeSource={RelativeSource AncestorType=ScrollViewer}}"
Text="Frozen" />
</Canvas>
<TextBlock Text="4" />
<TextBlock Text="5" />
</ListBox>
它是这样工作的:
"Frozen" 停留在屏幕上忽略水平滚动,但仍被视为一个项目(垂直滚动可以将其移出视图)。这可以通过Canvas 属性来实现:它具有0 高度和宽度,并且不会对布局造成任何影响。注意绑定到HorizontalOffset。
将Height="100" 替换为Height="{Binding Children[0].ActualHeight, RelativeSource={RelativeSource Self}}"。它适用于设计器,但不适用于运行时!
【问题讨论】:
-
这一切的目的是什么?通常可以通过使用适当的布局元素来避免绑定宽度和高度。例如。用网格或边框替换画布。
-
@Clemens,创建布局。画布将成为
ListViewItem的一部分(模拟冻结内容,不考虑水平滚动),但内容在数据模板中,我虽然我可以像这样自动调整Canvas,否则@987654338 @ 太小(Canvas.Height是0,正如我所说)。 -
但是当其他面板已经实现自动调整大小时,为什么要“自动调整”画布?
-
Canvas很特别。任何其他容器都会影响ListView列/行,Canvas- 不会。它允许创建飞在ListViewItem之上的内容。 -
我认为问题在于运行时的
Binding在孩子实际存在之前被评估。为什么不能为此使用ElementName绑定?这似乎很合适