【问题标题】:Why are ActualWidth and ActualHeight 0.0 in this case?在这种情况下,为什么 ActualWidth 和 ActualHeight 是 0.0?
【发布时间】:2009-11-08 02:04:09
【问题描述】:

我在Canvas 中有一个Grid,定义如下:

<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. 网格的宽度/高度已绑定到画布,但我尝试删除此绑定,但问题仍然存在。

【问题讨论】:

    标签: wpf xaml grid actualwidth actualheight


    【解决方案1】:

    ActualHeightActualWidth 直到控件被测量和排列后才被设置。通常InitializeComponent() 中没有任何东西会导致测量,所以当它返回时,这些仍然是零。

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

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

    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));
    

    【讨论】:

    • 谢谢!稍微更正一下:window.Measure 返回 void。它改变了 DesiredWidth/DesiredHeight 属性 :) 但你的想法是对的。
    • 当您在没有仔细检查 API 的情况下输入代码时会发生这种情况。感谢您的指正。 MeasureOverride 返回大小,但 Measure 只存储它们。答案已更正。
    【解决方案2】:

    Ray 是正确的 (+1),这是因为测量和排列通道尚未执行。但是,您可以等到控件加载完毕后再访问ActualXxx 属性,而不是强制另一个布局传递(昂贵):

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

    【讨论】:

    • 同意。等待加载是更好的方法恕我直言。
    • 谢谢!只是好奇...为什么 Window 上没有 OnLoaded 方法?
    • 等待加载是个好主意(+1),并且在大多数情况下都可以使用。但请注意,当您从不连接到 PresentationSource(即,您从不显示窗口)时,永远不会调用 Loaded。我以前遇到过这种情况,例如在决定是否在页面上包含控件时。所以我会说在可能的情况下使用 Loaded 会更好并且涵盖所有情况,否则使用 Measure/Arrange 会更好。也就是说,在 90% 的情况下,最佳实践是完全远离 ActualWidth/ActualHeight。 (例如,更多/更好的面板,绑定到高度/宽度,MeasureOverride)
    • 两个都试过了,WAAAAAAYYYYYYYY 更好。
    • @RayBurns,我的加载没有被调用,因为我遇到了 10%。有没有办法调用它(比在 IMO 中重写)。
    【解决方案3】:

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

    Dispatcher.Invoke(new Action(() =>
    {
       graphHeight = ActualHeight;
       graphWidth = ActualWidth;
    }), DispatcherPriority.Loaded);
    

    【讨论】:

    • 这个解决方案对我有帮助。我从同一个线程获得实际大小,它返回零和 NaN。我把这段代码放在线程之后,它会相应地显示结果。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-04
    相关资源
    最近更新 更多