2009-11-08 37 views
35

Tôi có một Grid bên trong một Canvas định nghĩa như thế này:Tại sao ActualWidth và ActualHeight 0.0 trong trường hợp này?

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

Vấn đề của tôi là, trên các nhà xây dựng Window, sau InitializeComponents() hoặc Grid.ColumnDefinitions[0].ActualWidth hoặc "bất kỳ hình chữ nhật". ActualWidth đều được đặt thành 0.0 (tương đương với chiều cao). Tôi không biết phải làm gì để có được thông tin này. bất kỳ giúp đỡ?

Quan sát:

  1. Tôi không definig chiều rộng vải bên ngoài và chiều cao nhưng nếu tôi làm, nó does't giải quyết vấn đề của tôi.
  2. Khi chạy tôi có thể thấy rằng Canvas/Grid này chiếm toàn bộ không gian cửa sổ, như vậy mỗi hình chữ nhật bên trong nó có ActualWidth s và ActualHeight s
  3. của lưới rộng/chiều cao được ràng buộc với vải nhưng tôi đã cố gắng loại bỏ ràng buộc này và vấn đề của tôi tồn tại

Trả lời

69

ActualHeightActualWidth không được đặt cho đến khi được kiểm soát và sắp xếp. Thông thường, không có gì trong số InitializeComponent() gây ra một số đo, vì vậy khi nó trả về các giá trị này vẫn sẽ bằng 0.

Bạn có thể buộc các tính năng này được tính trước đó bằng cách chỉ cần gọi phương thức Measure()Arrange() của cửa sổ theo cách thủ công sau khi trả về InitializeComponent() của cửa sổ.

Nếu bạn đang cỡ nội dung:

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

Nếu bạn đang sử dụng một kích thước cửa sổ rõ ràng:

window.Measure(new Size(Width, Height)); 
window.Arrange(new Rect(0, 0, window.DesiredSize.Width, window.DesiredSize.Height)); 
+1

Cảm ơn! Chỉ cần một chút chỉnh sửa: window.Measure trả về void. Nó thay đổi các thuộc tính DesiredWidth/DesiredHeight :) Nhưng ý tưởng của bạn là đúng. –

+1

Đó là những gì xảy ra khi bạn nhập mã ra khỏi đầu của bạn mà không cần kiểm tra lại các API. Cảm ơn vì sự đúng đắn của bạn. MeasureOverride trả về kích thước, nhưng Measure chỉ lưu trữ chúng. Đã sửa câu trả lời. –

+11

Không chắc chắn nếu "DesiredWidth" làm việc trước đây, nhưng phiên bản mới hơn của .NET sử dụng DesiredSize.Width và DesiredSize.Chiều cao –

52

Ray là chính xác (1) rằng đây là do thực tế rằng đo lường và sắp xếp vượt qua vẫn chưa thực hiện. Tuy nhiên, thay vì buộc khác vượt qua layout (đắt tiền), bạn có thể chỉ cần chờ đợi cho đến khi kiểm soát của bạn đã được nạp trước khi truy cập các ActualXxx tính:

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

} 
+2

Đồng ý. Đang chờ tải là cách tiếp cận tốt hơn IMHO. –

+0

Cảm ơn! Chỉ tò mò ... Tại sao không có phương thức OnLoaded trên Window? –

+3

Đang chờ tải là một ý tưởng hay (+1) và sẽ hoạt động trong hầu hết các trường hợp. Nhưng lưu ý rằng khi bạn không bao giờ kết nối với một PresentationSource (nghĩa là bạn không bao giờ hiển thị cửa sổ), Loaded sẽ không bao giờ được gọi. Tôi đã chạy vào điều này trước đây, ví dụ như khi quyết định có hay không bao gồm một điều khiển trên một trang. Vì vậy, tôi sẽ nói bằng cách sử dụng Loaded là tốt hơn khi nó có thể và bao gồm tất cả các trường hợp, nếu không sử dụng Measure/Arrange thì tốt hơn. Điều đó nói rằng, trong 90% các trường hợp thực hành tốt nhất sẽ được ở lại đi từ ActualWidth/ActualHeight hoàn toàn. (ví dụ: nhiều tấm/beter, gắn với chiều cao/chiều rộng, MeasureOverride) –

-7

ActualWidthActualHeight có sẵn chỉ sau XAML tải hoàn tất, trước khi tải như thế nào có thể bạn tìm thấy các thông số này?

Sử dụng sự kiện đã tải và bên trong sự kiện sẽ tìm thấy ActualWidthActualHeight.

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

đó là câu trả lời ở trên từ khái niệm Kent – kenny

+0

cũng không giống câu trả lời –

-1

Trong trường hợp của chúng tôi là giải pháp rất đơn giản, như tất cả mọi người nói ActualWidth và ActualHeight cần thiết để có được gọi sau khi nạp thậm chí hoàn tất, Vì vậy, chúng tôi chỉ quấn mã trong một điều phối và thiết lập ưu tiên cho Loaded như sau:

Dispatcher.Invoke(new Action(() => 
{ 
    graphHeight = ActualHeight; 
    graphWidth = ActualWidth; 
}), DispatcherPriority.Loaded); 
Các vấn đề liên quan