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

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

Éléments et arborescence logique

Lorsque vous créez une instance d’une classe Windows Presentation Foundation (WPF) dans le code, vous devez savoir que plusieurs aspects de l’initialisation d’objet pour une classe Windows Presentation Foundation (WPF) ne font délibérément pas partie du code exécuté lors de l’appel du constructeur de classe. En particulier pour une classe de contrôle, la majeure partie de la représentation visuelle de ce contrôle n’est pas définie par le constructeur. Au lieu de cela, la représentation visuelle est définie par le modèle du contrôle. Le modèle peut provenir de diverses sources, mais le plus souvent il est obtenu à partir de styles de thème. Les modèles sont en fait à liaison tardive ; le modèle nécessaire n’est attaché au contrôle en question qu’une fois le contrôle prêt pour la disposition. Et le contrôle est prêt pour la disposition seulement une fois qu’il est attaché à une arborescence logique qui se connecte à une surface de rendu à la racine. C’est cet élément de niveau racine qui démarre le rendu de tous ses éléments enfants tels que définis dans l’arborescence logique.

L’arborescence d’éléments visuels participe également à ce processus. De plus, les éléments qui font partie de l’arborescence d’éléments visuels par l’intermédiaire des modèles ne sont totalement instanciés que quand ils sont connectés.

Les conséquences de ce comportement sont que certaines opérations qui reposent sur l’achèvement des caractéristiques visuelles d’un élément nécessitent des étapes supplémentaires. (par exemple si vous essayez d’obtenir les caractéristiques visuelles d’une classe qui a été construite mais pas encore attachée à une arborescence). Par exemple, si vous souhaitez appeler Render un RenderTargetBitmap visuel et que vous passez est un élément qui n’est pas connecté à une arborescence, cet élément n’est pas terminé visuellement tant que des é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 . Vous utilisez les méthodes et EndInit les BeginInit méthodes de l’interface pour désigner une région dans votre code qui contient des étapes d’initialisation (telles que la définition de valeurs de propriété qui affectent le rendu). Une fois EndInit appelé dans la séquence, le système de disposition peut traiter l’élément et commencer à rechercher un style implicite.

Si l’élément sur lequel vous définissez des propriétés est une FrameworkElement classe ou FrameworkContentElement une classe dérivée, vous pouvez appeler les versions de classe de BeginInit et EndInit plutôt que passer à ISupportInitialize.

Exemple de code

L’exemple de code suivant est 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 approprié d’autres appels d’API BeginInitEndInit qui ajustent les propriétés qui affectent le rendu.

L’exemple illustre uniquement la fonction principale. Les fonctions Rasterize et Save (non illustrées) sont des fonctions utilitaires qui assurent le traitement d’image et les 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");
}
<STAThread>
Shared Sub Main(ByVal args() As String)
    Dim e As UIElement
    Dim _file As String = Directory.GetCurrentDirectory() & "\starting.xaml"
    Using stream As Stream = File.Open(_file, FileMode.Open)
        ' loading files from current directory, project settings take care of copying the file
        Dim pc As New ParserContext()
        pc.BaseUri = New Uri(_file, UriKind.Absolute)
        e = CType(XamlReader.Load(stream, pc), UIElement)
    End Using

    Dim paperSize As 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
    '             
    Dim image1 As RenderTargetBitmap = Rasterize(e, paperSize.Width, paperSize.Height, 96, 96)
    Save(image1, "render1.png")

    Dim b As New Button()
    b.BeginInit()
    b.Background = Brushes.Blue
    b.Height = 200
    b.Width = b.Height
    b.EndInit()
    b.Measure(paperSize)
    b.Arrange(New Rect(paperSize))
    b.UpdateLayout()

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

    Dim image2 As RenderTargetBitmap = Rasterize(b, paperSize.Width, paperSize.Height, 96, 96)
    Save(image2, "render2.png")
End Sub

Voir aussi