我将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
,因此“文本”重叠,绑定 - 文本位于设计器中的 (您可以自己尝试)。< / p>
但是,运行时绑定失败且文本重叠。
System.Windows.Data错误:17:无法从'Children'获取'Item []'值(类型'UIElement')(类型'UIElementCollection')。 BindingExpression:路径=儿童[0] .ActualHeight; DataItem ='Canvas'(Name =''); target元素是'Canvas'(Name =''); target属性为'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}}"
。它适用于设计师,但不适用于运行时!
答案 0 :(得分:1)
作为@MartinZikmund评论
问题是在孩子实际存在之前评估运行时绑定
第二个例子可以改写为
<Canvas>
<TextBlock Canvas.Left="{Binding HorizontalOffset, RelativeSource={RelativeSource AncestorType=ScrollViewer}}"
Text="Frozen" />
<Canvas.Height>
<Binding Path="Children[0].ActualHeight" RelativeSource="{RelativeSource Self}" />
</Canvas.Height>
</Canvas>
Height
绑定在内容后设置为。这使它在运行时工作。
仍然是设计师时间为什么没有问题的问题。我想有些wpf-magic。
答案 1 :(得分:1)
你可以把它放在一个行为上:
private void Canvas_Loaded(object sender, RoutedEventArgs e)
{
(sender as Canvas)?.SetBinding(Canvas.HeightProperty, new Binding("Children[0].ActualHeight") { RelativeSource=new RelativeSource { Mode= RelativeSourceMode.Self } });
}