[英]Binding to Children does not work at run-time
I am binding Canvas
height to first children height so that it can be layed out properly, an example of layout: 我将“
Canvas
高度”绑定到第一个孩子的高度,以便可以正确地布局它,例如布局:
<StackPanel>
<Canvas Height="{Binding Children[0].ActualHeight , RelativeSource={RelativeSource Self}}">
<Rectangle Height="100" Width="100" Fill="Red" />
</Canvas>
<TextBlock Text="Text" />
</StackPanel>
Without binding Canvas.Height
value is 0
, so that the "Text" overlaps, with binding - text is under in designer (you can try it yourself). 不绑定
Canvas.Height
值为0
,因此绑定时“文本”重叠-文本位于设计器中 (您可以自己尝试)。
However during run-time binding fails and text overlaps. 但是,在运行时绑定失败,并且文本重叠。
System.Windows.Data Error: 17 : Cannot get 'Item[]' value (type 'UIElement') from 'Children' (type 'UIElementCollection').
System.Windows.Data错误:17:无法从“儿童”(类型“ UIElementCollection”)获取“ Item []”值(类型“ UIElement”)。 BindingExpression:Path=Children[0].ActualHeight;
BindingExpression:Path = Children [0] .ActualHeight; DataItem='Canvas' (Name='');
DataItem ='Canvas'(Name =''); target element is 'Canvas' (Name='');
目标元素是'Canvas'(Name =''); target property is 'Height' (type 'Double') ArgumentOutOfRangeException:'System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
目标属性为'Height'(类型为'Double')ArgumentOutOfRangeException:'System.ArgumentOutOfRangeException:指定的参数超出有效值范围。
Why? 为什么? Can I have designer-time behavior at run-time?
我可以在运行时具有设计时行为吗?
I would like not to give child a x:Name
and to bind using ElementName
. 我想不给孩子一个
x:Name
,并使用绑定ElementName
。
Here is better MCVE: 这是更好的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>
It works like this: 它是这样的:
"Frozen"
stays on screen disregards horizontal scrolling, while still treated as an item (vertical scrolling can move it away from view). "Frozen"
停留在屏幕上,不考虑水平滚动,而仍被视为一项(垂直滚动可将其移离视图)。 This is possible to achieve due to Canvas
properties: it has 0
height and width and doesn't cause any effect on layout. 由于
Canvas
属性的缘故,这是可以实现的:高度和宽度为0
,并且对布局没有任何影响。 Note binding to HorizontalOffset
. 注意绑定到
HorizontalOffset
。
Replace Height="100"
with Height="{Binding Children[0].ActualHeight, RelativeSource={RelativeSource Self}}"
. 用
Height="{Binding Children[0].ActualHeight, RelativeSource={RelativeSource Self}}"
替换Height="100"
Height="{Binding Children[0].ActualHeight, RelativeSource={RelativeSource Self}}"
。 It works in designer, but not at run-time! 它可以在设计器中工作,但不能在运行时使用!
As @MartinZikmund comment 作为@MartinZikmund评论
the problem is that the Binding at runtime is evaluated before the child actually exists
问题是,运行时的绑定是在子项实际存在之前进行评估的
the second example can be rewritten as 第二个例子可以改写成
<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
binding is set after content. Height
绑定在内容之后设置。 Which makes it working at run-time. 这使其在运行时工作。
Still the question why designer-time has no problems. 仍然是为什么设计师时间没有问题的问题。 Some wpf-magic I guess.
我猜有些wpf魔术。
You could put this to a behavior: 您可以将这种行为:
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 } });
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.