45

我有一个这样定义的Grid内部:Canvas

<Canvas x:Name="outerCanvas">
    <Grid Grid.Row="1" Name="cGrid" ShowGridLines="True" Width="{Binding Path=ActualWidth, RelativeSource={RelativeSource AncestorType={x:Type Canvas}}}" Height="{Binding Path=ActualHeight, RelativeSource={RelativeSource AncestorType={x:Type Canvas}}}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition  />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Rectangle Name="rectangle1" Stroke="Black" Fill="AntiqueWhite" />
        <Rectangle Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="1" Grid.RowSpan="1" Name="rectangle2" Stroke="Black" Fill="AliceBlue" />
        <Rectangle Grid.Row="0" Grid.Column="2" Grid.ColumnSpan="1" Grid.RowSpan="1" Name="rectangle3" Stroke="Black" Fill="Aqua" />
        <Rectangle Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" Grid.RowSpan="1" Name="rectangle4" Stroke="Black" Fill="DarkViolet" />
    </Grid>
</Canvas>

我的问题是,在 Window 构造函数中,在InitializeComponents()任一Grid.ColumnDefinitions[0].ActualWidth或“任何矩形”之后。ActualWidth都设置为 0.0(高度相同)。我不知道该怎么做才能获得这些信息。有什么帮助吗?

观察:

  1. 我没有定义外部画布的宽度和高度,但如果我这样做了,它并不能解决我的问题。
  2. 在运行时我可以看到它Canvas/Grid占据了整个窗口空间,所以它里面的每个矩形都有ActualWidths 和ActualHeights
  3. 网格的宽度/高度绑定到画布,但我尝试删除此绑定,但我的问题仍然存在。
4

3 回答 3

82

ActualHeight并且ActualWidth直到控制被测量和布置后才被设置。通常没有什么InitializeComponent()会导致测量,所以当它返回时,这些仍然是零。

您可以通过在窗口返回后手动调用窗口Measure()和方法来强制提前计算这些。Arrange()InitializeComponent()

如果您根据内容调整大小:

window.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
window.Arrange(new Rect(0, 0, window.DesiredSize.Width, window.DesiredSize.Height));

如果您使用显式窗口大小:

window.Measure(new Size(Width, Height));
window.Arrange(new Rect(0, 0, window.DesiredSize.Width, window.DesiredSize.Height));
于 2009-11-08T05:53:05.710 回答
69

Ray 是正确的 (+1),这是由于尚未执行测量和排列传递的事实。但是,与其强制另一个布局传递(昂贵),您可以等到控件加载后再访问ActualXxx属性:

public MyWindow()
{
    Loaded += delegate
    {
        // access ActualWidth and ActualHeight here
    };

}
于 2009-11-08T09:04:43.417 回答
3

在我们的例子中,解决方案很简单,因为每个人都说在 Loaded 甚至完成后需要调用 ActualWidth 和 ActualHeight,所以我们只是将代码包装在调度程序中并将优先级设置为 Loaded,如下所示:

Dispatcher.Invoke(new Action(() =>
{
   graphHeight = ActualHeight;
   graphWidth = ActualWidth;
}), DispatcherPriority.Loaded);
于 2017-03-21T15:24:12.853 回答