Question

How do I force a Window to measure its controls in the constructor so the values of ActualWidth and ActualHeight aren't zero? Here is the sample demonstrating my problem (I tried to call Measure and Arrange functions, but maybe in a wrong manner).

XAML:

<Window x:Class="WpfApplication7.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        WindowStartupLocation="CenterScreen"
        Title="WPF Diagram Designer"
        Background="#303030"
        Height="600" Width="880" x:Name="Root">

  <Grid x:Name="LayoutRoot">
        <DockPanel>
            <TextBox DockPanel.Dock="Top" Text="{Binding ElementName=Root, Mode=TwoWay, Path=Count}"/>
            <Button DockPanel.Dock="Top" Content="XXX"/>
            <Canvas x:Name="MainCanvas">

            </Canvas>
        </DockPanel>
    </Grid>
</Window>

code behind:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
using System;
using System.Windows.Media;

namespace WpfApplication7
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
            Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
            Arrange(new Rect(DesiredSize));
            Count = 6;
        }

        public static readonly DependencyProperty CountProperty = DependencyProperty.Register("Count",
            typeof(int), typeof(Window1), new FrameworkPropertyMetadata(5, CountChanged, CoerceCount));

        private static object CoerceCount(DependencyObject d, object baseValue)
        {
            if ((int)baseValue < 2) baseValue = 2;
            return baseValue;
        }

        public int Count
        {
            get { return (int)GetValue(CountProperty); }
            set { SetValue(CountProperty, value); }
        }

        private static void CountChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Window1 w = d as Window1;
            if (w == null) return;
            Canvas c = w.MainCanvas;
            if (c == null || c.Children == null) return;
            c.Children.Clear();
            if (c.ActualWidth == 0) MessageBox.Show("XXX");
            for (int i = 0; i < w.Count; i++)
                c.Children.Add(new Line()
                {
                    X1 = c.ActualWidth * i / (w.Count - 1),
                    X2 = c.ActualWidth * i / (w.Count - 1),
                    Y1 = 0,
                    Y2 = c.ActualHeight,
                    Stroke = Brushes.Red,
                    StrokeThickness = 2.0
                });
        }
    }
}

The point of this example is to have drawn Count number of vertical lines from left edge to right edge. It works well when I change the value in the TextBox, however I want the lines to be drawn in the beginning already.

So how do I need to update the code to have drawn the lines in the beginning already please? Or would a different approach than the mentioned code be more appropriate to achieve this goal?

Thanks for any efforts.

Était-ce utile?

La solution

Perhaps you could put the logic in OnContentRendered.

The Windows Content should be all layed out by then and the ActualWidth etc should be ready.

Example:

protected override void OnContentRendered(EventArgs e)
{
    base.OnContentRendered(e);

    // Logic
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top