2009-11-08 36 views
35

我有一個Grid這樣定義的Canvas內:爲什麼在這種情況下ActualWidth和ActualHeight 0.0?

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

我的問題是,在窗口的構造,後InitializeComponents()要麼Grid.ColumnDefinitions[0].ActualWidth或「任何矩形」。 ActualWidth都設置爲0.0(高度相同)。我不知道該怎麼做才能獲得這些信息。任何幫助?

觀察:

  1. 我不definig外畫布寬度和高度,但如果我這樣做,但這並沒有解決我的問題。
  2. 在運行時,我可以看到這個Canvas/Grid佔據了整個窗口空間,所以它裏面的每個矩形的ActualWidth S和ActualHeight小號
  3. 網格的寬度/高度綁定到畫布,但我試圖消除這種結合,我的問題持續

回答

69

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

謝謝!只是一點點更正:window.Measure返回void。它改變了DesiredWidth/DesiredHeight屬性:)但你的想法是正確的。 – 2009-11-08 18:10:24

+1

這就是當您在沒有仔細檢查API的情況下輸入代碼時發生的情況。感謝您的更正。 MeasureOverride返回大小,但Measure只是存儲它們。答案已更正。 – 2009-11-08 22:27:20

+11

不確定「DesiredWidth」之前是否有效,但較新版本的.NET使用DesiredSize.Width和DesiredSize。身高 – 2015-06-18 23:40:31

52

雷是正確的(+1),這是由於事實措施和安排通行證尚未執行。然而,而不是迫使另一佈局傳遞(昂貴的),你可以只是等待,直到你的控制已經訪問ActualXxx性能之前加載:

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

} 
+2

同意。等待加載是更好的方法恕我直言。 – 2009-11-08 14:46:11

+0

謝謝!只是好奇...爲什麼Window上沒有OnLoaded方法? – 2009-11-08 18:11:25

+3

等待加載是一個好主意(+1),並且在大多數情況下都可以使用。但請注意,當您從未連接到PresentationSource(即,您從不顯示窗口)時,Loaded永遠不會被調用。我之前遇到過這種情況,例如,在決定是否在頁面上添加控件時。所以我會說在可能的情況下使用Loaded會更好,並覆蓋所有情況,否則使用Measure/Arrange更好。也就是說,在90%的情況下,最佳做法是徹底遠離ActualWidth/ActualHeight。 (例如更多/雜色面板,綁定到高度/寬度,MeasureOverride) – 2009-11-08 22:34:38

-7

ActualWidthActualHeight看上XAML加載完成後可用,加載之前你怎麼能找到這些參數?

使用加載事件,並在其中找到ActualWidthActualHeight

private void me_Loaded(object sender, RoutedEventArgs e) 
{ 
    // do your stuffs here. 
} 
+6

這是從肯特以上答案 – kenny 2013-05-30 09:54:20

+0

概念是相同的不答案 – 2013-05-30 11:42:26

-1

在我們的情況下,解決辦法很簡單,因爲大家都說ActualWidth的和的ActualHeight需要得到所謂的加載,即使完成後, 所以我們只是包裹在一個調度程序代碼和優先級設置爲加載如下:

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