title: Measuring controls created at runtime in WPF
body: <p>I recognise this is a popular question but I couldn't find anything that answered it exactly, but I apologise if I've missed something in my searches.</p>
  
  <p>I'm trying to create and then measure a control at runtime using the following code (the measurements will then be used to marquee-style scroll the controls - each control is a different size):</p>
  
  <pre><code>Label lb = new Label();
  lb.DataContext= task;
  Style style = (Style)FindResource("taskStyle");
  lb.Style = style;
  
  cnvMain.Children.Insert(0,lb);
  
  width = lb.RenderSize.Width;
  width = lb.ActualWidth;
  width = lb.Width;
  </code></pre>
  
  <p>The code creates a Label control and applies a style to it. The style contains my control template which binds to the object "task". When I create the item it appears perfectly, however when I try to measure the control using any of the properties above I get the following results (I step through and inspect each property in turn):</p>
  
  <pre><code>lb.Width = NaN
  lb.RenderSize.Width = 0
  lb.ActualWidth = 0
  </code></pre>
  
  <p>Is there any way to get the rendered height and width of a control you create at runtime?</p>
  
  <p><strong>UPDATE:</strong></p>
  
  <p>Sorry for deselecting your solutions as answers. They work on a basic example system I set up, but seemingly not with my complete solution.</p>
  
  <p>I think it may be something to do with the style, so sorry for the mess, but I'm pasting the entire thing here.</p>
  
  <p>First, resources:
          
              
          </p>
  
  <pre><code>    &lt;Storyboard x:Key="mouseOverGlowLeave"&gt;
          &lt;DoubleAnimation From="8" To="0" Duration="0:0:1" BeginTime="0:0:2" Storyboard.TargetProperty="GlowSize" Storyboard.TargetName="Glow"/&gt;
      &lt;/Storyboard&gt;
  
      &lt;Storyboard x:Key="mouseOverTextLeave"&gt;
          &lt;ColorAnimation From="{StaticResource buttonLitColour}" To="Gray" Duration="0:0:3" Storyboard.TargetProperty="Color" Storyboard.TargetName="ForeColour"/&gt;
      &lt;/Storyboard&gt;
  
      &lt;Color x:Key="buttonLitColour" R="30" G="144" B="255" A="255" /&gt;
  
      &lt;Storyboard x:Key="mouseOverText"&gt;
          &lt;ColorAnimation From="Gray" To="{StaticResource buttonLitColour}" Duration="0:0:1" Storyboard.TargetProperty="Color" Storyboard.TargetName="ForeColour"/&gt;
      &lt;/Storyboard&gt;
  </code></pre>
  
  <p>And the style itself:</p>
  
  <pre><code>    &lt;Style x:Key="taskStyle" TargetType="Label"&gt;
          &lt;Setter Property="Template"&gt;
              &lt;Setter.Value&gt;
                  &lt;ControlTemplate&gt;
                      &lt;Canvas x:Name="cnvCanvas"&gt;
                          &lt;Border  Margin="4" BorderBrush="Black" BorderThickness="3" CornerRadius="16"&gt;
                              &lt;Border.Background&gt;
                                  &lt;LinearGradientBrush StartPoint="0,0" EndPoint="0,1"&gt;
                                      &lt;GradientStop Offset="1" Color="SteelBlue"/&gt;
                                      &lt;GradientStop Offset="0" Color="dodgerBlue"/&gt;
                                  &lt;/LinearGradientBrush&gt;
                              &lt;/Border.Background&gt;
                              &lt;DockPanel Margin="8"&gt;
                                  &lt;DockPanel.Resources&gt;
                                      &lt;Style TargetType="TextBlock"&gt;
                                          &lt;Setter Property="FontFamily" Value="corbel"/&gt;
                                          &lt;Setter Property="FontSize" Value="40"/&gt;
                                      &lt;/Style&gt;
                                  &lt;/DockPanel.Resources&gt;
                                  &lt;TextBlock VerticalAlignment="Center" Margin="4" Text="{Binding Path=Priority}"/&gt;
                                  &lt;DockPanel DockPanel.Dock="Bottom"&gt;
                                      &lt;Border Margin="4" BorderBrush="SteelBlue" BorderThickness="1" CornerRadius="4"&gt;
                                          &lt;TextBlock Margin="4" DockPanel.Dock="Right" Text="{Binding Path=Estimate}"/&gt;
                                      &lt;/Border&gt;
                                      &lt;Border Margin="4" BorderBrush="SteelBlue" BorderThickness="1" CornerRadius="4"&gt;
                                          &lt;TextBlock Margin="4" DockPanel.Dock="Left" Text="{Binding Path=Due}"/&gt;
                                      &lt;/Border&gt;
                                  &lt;/DockPanel&gt;
                                  &lt;DockPanel DockPanel.Dock="Top"&gt;
                                      &lt;Border Margin="4" BorderBrush="SteelBlue" BorderThickness="1" CornerRadius="4"&gt;
                                          &lt;TextBlock  Margin="4" Foreground="LightGray" DockPanel.Dock="Left" Text="{Binding Path=List}"/&gt;
                                      &lt;/Border&gt;
                                      &lt;Border Margin="4" BorderBrush="SteelBlue" BorderThickness="1" CornerRadius="4"&gt;
                                          &lt;TextBlock Margin="4" Foreground="White" DockPanel.Dock="Left" Text="{Binding Path=Name}"/&gt;
                                      &lt;/Border&gt;
                                  &lt;/DockPanel&gt;
                              &lt;/DockPanel&gt;
                          &lt;/Border&gt;
                      &lt;/Canvas&gt;
                  &lt;/ControlTemplate&gt;
              &lt;/Setter.Value&gt;
          &lt;/Setter&gt;
      &lt;/Style&gt;
  </code></pre>
  
  <p>Also, the code I'm using:</p>
  
  <pre><code>Label lb = new Label(); //the element I'm styling and adding
    lb.DataContext= task; //set the data context to a custom class
    Style style = (Style)FindResource("taskStyle"); //find the above style
    lb.Style = style;
  
    cnvMain.Children.Insert(0,lb); //add the style to my canvas at the top, so other overlays work
    lb.UpdateLayout(); //attempt a full layout update - didn't work
    Dispatcher.Invoke(DispatcherPriority.Render, new Action(() =&gt;
    {
        //Synchronize on control rendering
        double width = lb.RenderSize.Width;
        width = lb.ActualWidth;
        width = lb.Width;
    })); //this didn't work either
    lb.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); //nor did this
    double testHeight = lb.DesiredSize.Height;
    double testWidth = lb.RenderSize.Width; //nor did this
    width2 = lb.ActualWidth; //or this
    width2 = lb.Width; //or this
  
  //positioning for my marquee code - position off-screen to start with
    Canvas.SetTop(lb, 20);
    Canvas.SetTop(lb, -999);
  
  //tried it here too, still didn't work
    lb.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
    testHeight = lb.DesiredSize.Height;
  //add my newly-created label to a list which I access later to operate the marquee
    taskElements.AddLast(lb);
  //still didn't work
    lb.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
    testHeight = lb.DesiredSize.Height;
  //tried a mass-measure to see if that would work - it didn't
    foreach (UIElement element in taskElements)
    {
        element.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
    }
  </code></pre>
  
  <p>Each time any of those is called the value is returned as either 0 or not a number, yet when the label is rendered it clearly has a size as it is visible. I have tried running this code from a button press when the label is visible on-screen, but that produces the same results.</p>
  
  <p>Is it because of the style I'm using? Databindings perhaps? Is what I've done wrong  blindingly obvious or do the WPF Gremlins just <em>really</em> hate me?</p>
  
  <p><strong>Second Update:</strong></p>
  
  <p>After further searching I've discovered that Measure() only applies to the original element size. If a control template modifies this by actually adding controls then the best method would probably be to measure each one, but I admit that's more than a little messy. </p>
  
  <p>The compiler must have some way of measuring all of the contents of a control as it must use that to place items in, for example, stack-panels. There must be some way to access it, but for now I'm entirely out of ideas.</p>