Почему ActualWidth и ActualHeight 0.0 в этом случае?

У меня есть 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 занимает все пространство окна, поэтому каждый прямоугольник внутри него имеет ActualWidthс и ActualHeights
  3. Ширина / высота сетки привязана к холсту, но я попытался удалить эту привязку, и моя проблема все еще сохраняется.

4 ответа

Решение

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

Рэй прав (+1), что это связано с тем, что мера и аранжировка еще не выполнены. Однако вместо принудительного выполнения другого прохода макета (дорого) вы можете просто подождать, пока ваш элемент управления загрузится, прежде чем получить доступ к ActualXxx свойства:

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

}

В нашем случае решение было простым, поскольку все говорили, что ActualWidth и ActualHeight необходимо вызывать после завершения Loaded, поэтому мы просто обернули код в диспетчер и установили приоритет Loaded, как показано ниже:

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

ActualWidth а также ActualHeight доступны только после завершения загрузки XAML, до загрузки, как вы можете найти эти параметры?

Используйте событие Loaded и внутри него найдите ActualWidth а также ActualHeight,

private void me_Loaded(object sender, RoutedEventArgs e)
{
  // do your stuffs here.
}
Другие вопросы по тегам