Initialisation d'éléments objets ne figurant pas dans une arborescence d'éléments

Mise à jour : novembre 2007

Certains aspects de l'initialisation de Windows Presentation Foundation (WPF) sont différés à des processus qui reposent généralement sur la connexion de cet élément à l'arborescence logique ou à l'arborescence visuelle. Cette rubrique décrit les étapes qui peuvent s'avérer nécessaires pour initialiser un élément qui n'est connecté à aucune de ces arborescences.

Cette rubrique comprend les sections suivantes.

  • Éléments et arborescence logique
  • Rubriques connexes

Éléments et arborescence logique

Lorsque vous créez une instance d'une classe Windows Presentation Foundation (WPF) dans le code, gardez à l'esprit que plusieurs aspects de l'initialisation d'un objet pour une classe Windows Presentation Foundation (WPF) ne sont pas intégrés, à dessein, au code exécuté lors de l'appel du constructeur de classe. Dans le cas d'une classe de contrôle en particulier, la plus grande partie de la représentation visuelle de ce contrôle n'est pas définie par le constructeur, mais par le modèle du contrôle. Le modèle peut provenir de diverses sources, mais est le plus souvent obtenu à partir de styles de thème. La liaison des modèles est en fait tardive ; le modèle nécessaire n'est pas joint au contrôle tant que celui-ci n'est pas prêt pour la disposition. Et le contrôle n'est prêt pour la disposition que lorsqu'il est joint à une arborescence logique connectée à une surface de rendu à la racine. C'est cet élément de niveau racine qui initialise le rendu de tous ses éléments enfants définis dans l'arborescence logique.

L'arborescence visuelle prend également part à ce processus. Les éléments intégrés à l'arborescence visuelle par le biais des modèles ne sont eux aussi totalement instanciés que lorsqu'ils sont connectés.

En raison de ce comportement, certaines opérations reposant sur les caractéristiques visuelles complétées d'un élément requièrent des étapes supplémentaires. C'est le cas notamment si vous tentez d'obtenir les caractéristiques visuelles d'une classe qui a été générée mais pas encore attachée à une arborescence. Par exemple, si vous voulez appeler Render sur un RenderTargetBitmap et que le visuel que vous transmettez est un élément non connecté à une arborescence, cet élément est incomplet d'un point de vue visuel tant que les étapes d'initialisation supplémentaires ne sont pas terminées.

Utilisation de BeginInit et EndInit pour initialiser l'élément

Différentes classes de WPF implémentent l'interface ISupportInitialize. Les méthodes BeginInit et EndInit de l'interface vous permettent de désigner une région de votre code contenant des étapes d'initialisation (telles que la définition des valeurs de propriétés affectant le rendu). Après avoir appelé EndInit dans la séquence, le système de disposition peut traiter l'élément et commencer à rechercher un style implicite.

Si l'élément dont vous définissez les propriétés est une classe dérivée FrameworkElement ou FrameworkContentElement, vous pouvez appeler les versions de classe de BeginInit et EndInit au lieu d'effectuer un cast en ISupportInitialize.

Exemple de code

L'exemple suivant montre un exemple de code pour une application console qui utilise des API de rendu et XamlReader.Load(Stream) d'un fichier XAML libre pour illustrer le positionnement correct de BeginInit et EndInit autour d'autres appels d'API qui définissent des propriétés affectant le rendu.

Cet exemple illustre uniquement la fonction principale. Les fonctions Rasterize et Save (non affichées) sont des fonctions utilitaires qui prennent en charge le traitement d'image et l'E/S.

[STAThread]
static void Main(string[] args)
{
    UIElement e;
    string file = Directory.GetCurrentDirectory() + "\\starting.xaml";
    using (Stream stream = File.Open(file, FileMode.Open))
    {
        // loading files from current directory, project settings take care of copying the file
        ParserContext pc = new ParserContext();
        pc.BaseUri = new Uri(file, UriKind.Absolute);
        e = (UIElement)XamlReader.Load(stream, pc);
    }

    Size paperSize = new Size(8.5 * 96, 11 * 96);
    e.Measure(paperSize);
    e.Arrange(new Rect(paperSize));
    e.UpdateLayout();

    /*
     *   Render effect at normal dpi, indicator is the original RED rectangle
     */
    RenderTargetBitmap image1 = Rasterize(e, paperSize.Width, paperSize.Height, 96, 96);
    Save(image1, "render1.png");

    Button b = new Button();
    b.BeginInit();
    b.Background = Brushes.Blue;
    b.Width = b.Height = 200;
    b.EndInit();
    b.Measure(paperSize);
    b.Arrange(new Rect(paperSize));
    b.UpdateLayout();

    // now render the altered version, with the element built up and initialized

    RenderTargetBitmap image2 = Rasterize(b, paperSize.Width, paperSize.Height, 96, 96);
    Save(image2, "render2.png");
}

Voir aussi

Concepts

Arborescences dans WPF

Vue d'ensemble du rendu graphique de Windows Presentation Foundation

Vue d'ensemble du langage XAML