Mesurer les contrôles créés lors de l'exécution dans WPF

Je reconnais que c'est une question populaire, mais je ne pouvais pas trouver quelque chose qui répond exactement, mais je prie de m'excuser si j'ai raté quelque chose dans mes recherches.

Je suis en train de créer, puis de mesurer un contrôle au moment de l'exécution en utilisant le code suivant (les mesures seront ensuite utilisés pour chapiteau de style défiler les contrôles de chaque contrôle est d'une taille différente):

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;

Le code crée une Étiquette de contrôle et applique un style à elle. Le style contient mon modèle de contrôle qui se lie à l'objet de la "tâche". Lorsque je crée l'objet, il s'affiche parfaitement, cependant lorsque j'essaie de mesurer le contrôle à l'aide de l'un des biens ci-dessus j'obtiens les résultats suivants (je fais un pas de travers et inspecter chaque propriété):

lb.Width = NaN
lb.RenderSize.Width = 0
lb.ActualWidth = 0

Est-il possible d'obtenir le rendu de la hauteur et la largeur de contrôle que vous avez créés lors de l'exécution?

Mise à JOUR:

Désolé pour désélectionner les solutions que de réponses. Ils travaillent sur la base d'un système d'exemple j'ai mis en place, mais apparemment pas avec ma solution complète.

Je pense que c'est peut-être quelque chose à voir avec le style, donc désolé pour le désordre, mais je suis coller en entier ici.

D'abord, les ressources:

    <Storyboard x:Key="mouseOverGlowLeave">
        <DoubleAnimation From="8" To="0" Duration="0:0:1" BeginTime="0:0:2" Storyboard.TargetProperty="GlowSize" Storyboard.TargetName="Glow"/>
    </Storyboard>

    <Storyboard x:Key="mouseOverTextLeave">
        <ColorAnimation From="{StaticResource buttonLitColour}" To="Gray" Duration="0:0:3" Storyboard.TargetProperty="Color" Storyboard.TargetName="ForeColour"/>
    </Storyboard>

    <Color x:Key="buttonLitColour" R="30" G="144" B="255" A="255" />

    <Storyboard x:Key="mouseOverText">
        <ColorAnimation From="Gray" To="{StaticResource buttonLitColour}" Duration="0:0:1" Storyboard.TargetProperty="Color" Storyboard.TargetName="ForeColour"/>
    </Storyboard>

Et le style lui-même:

    <Style x:Key="taskStyle" TargetType="Label">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Canvas x:Name="cnvCanvas">
<Border  Margin="4" BorderBrush="Black" BorderThickness="3" CornerRadius="16">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="1" Color="SteelBlue"/>
<GradientStop Offset="0" Color="dodgerBlue"/>
</LinearGradientBrush>
</Border.Background>
<DockPanel Margin="8">
<DockPanel.Resources>
<Style TargetType="TextBlock">
<Setter Property="FontFamily" Value="corbel"/>
<Setter Property="FontSize" Value="40"/>
</Style>
</DockPanel.Resources>
<TextBlock VerticalAlignment="Center" Margin="4" Text="{Binding Path=Priority}"/>
<DockPanel DockPanel.Dock="Bottom">
<Border Margin="4" BorderBrush="SteelBlue" BorderThickness="1" CornerRadius="4">
<TextBlock Margin="4" DockPanel.Dock="Right" Text="{Binding Path=Estimate}"/>
</Border>
<Border Margin="4" BorderBrush="SteelBlue" BorderThickness="1" CornerRadius="4">
<TextBlock Margin="4" DockPanel.Dock="Left" Text="{Binding Path=Due}"/>
</Border>
</DockPanel>
<DockPanel DockPanel.Dock="Top">
<Border Margin="4" BorderBrush="SteelBlue" BorderThickness="1" CornerRadius="4">
<TextBlock  Margin="4" Foreground="LightGray" DockPanel.Dock="Left" Text="{Binding Path=List}"/>
</Border>
<Border Margin="4" BorderBrush="SteelBlue" BorderThickness="1" CornerRadius="4">
<TextBlock Margin="4" Foreground="White" DockPanel.Dock="Left" Text="{Binding Path=Name}"/>
</Border>
</DockPanel>
</DockPanel>
</Border>
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Aussi, le code que j'utilise:

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(() =>
{
//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));
}

Chaque fois que l'un de ceux qui est appelé la valeur est renvoyée sous forme de 0 ou n'est pas un nombre, mais lorsque l'étiquette est affichée clairement a une taille telle qu'elle est visible. J'ai essayé de lancer ce code à partir d'appuyer sur un bouton lorsque l'étiquette est visible à l'écran, mais qui produit les mêmes résultats.

Est-ce parce que le style que j'utilise? Databindings peut-être? Est ce que j'ai fait de mal évidentes ou faire du WPF Gremlins juste vraiment me détester?

Deuxième Mise À Jour:

Après recherche j'ai découvert que la Mesure (la) s'applique uniquement à l'original de la taille de l'élément. Si un modèle de contrôle modifie ce que le fait de l'ajout de contrôles alors la meilleure méthode serait probablement à la mesure de chacun, mais j'avoue que c'est plus qu'un peu désordonné.

Le compilateur doit disposer d'une méthode de mesure de la totalité du contenu d'un contrôle, comme il se doit l'utiliser pour placer des éléments, par exemple, la pile de panneaux. Il doit y avoir un moyen d'y accéder, mais pour l'instant je suis entièrement d'idées.

source d'informationauteur Nick Udell