Auf Englisch lesen

Freigeben über


Initialisierung für Objektelemente außerhalb einer Objektstruktur

Einige Aspekte der WPF-Initialisierung (Windows Presentation Foundation) werden für Prozesse zurückgestellt, die in der Regel darauf angewiesen sind, dass Elemente entweder mit einer logischen oder einer visuellen Struktur verbunden sind. In diesem Thema werden die Schritte beschrieben, die möglicherweise erforderlich sind, um ein Element zu initialisieren, das mit keinem der beiden Bäume verbunden ist.

Elemente und der logische Baum

Wenn Sie eine Instanz einer Windows Presentation Foundation (WPF)-Klasse im Code erstellen, sollten Sie beachten, dass mehrere Aspekte der Objektinitialisierung für eine Windows Presentation Foundation (WPF)-Klasse absichtlich nicht Teil des Codes sind, der beim Aufrufen des Klassenkonstruktors ausgeführt wird. Insbesondere für eine Steuerelementklasse wird der Großteil der visuellen Darstellung dieses Steuerelements nicht vom Konstruktor definiert. Stattdessen wird die visuelle Darstellung durch die Vorlage des Steuerelements definiert. Die Vorlage stammt möglicherweise aus einer Vielzahl von Quellen, ganz oft wird die Vorlage jedoch aus Designstilen. Vorlagen sind eine effektive späte Bindung; die erforderliche Vorlage wird dem fraglichen Steuerelement nicht angefügt, solange das Steuerelement nicht für Layout bereit ist. Das Steuerelement ist so lange nicht für Layout bereit, bis es einer logischen Struktur angefügt wird, die eine Verbindung mit einer Renderingoberfläche auf der Stammebene eingeht. Es ist das Rootebenenelement, dass das Rendering aller untergeordneten Elemente initiiert, so wie in der logischen Struktur definiert.

Die visuelle Struktur beteiligt sich auch an diesem Prozess. Elemente, die aufgrund der Vorlagen Teil der visuellen Struktur sind, werden ebenfalls nicht vollständig instanziiert, bis sie verbunden sind.

Die Folgen dieses Verhaltens sind, dass bestimmte Vorgänge, die auf den abgeschlossenen visuellen Merkmalen eines Elements basieren, zusätzliche Schritte erfordern. Dies ist zum Beispiel der Fall, wenn Sie versuchen, visuelle Merkmale einer Klasse abzurufen, die erstellt, aber noch keiner Struktur angefügt wurde. Wenn Sie z. B. Render für RenderTargetBitmap aufrufen möchten und das übergebene visuelle Element nicht mit einer Struktur verbunden ist, ist dieses Element nicht visuell vollständig, bis zusätzliche Initialisierungsschritte abgeschlossen wurden.

Verwenden von BeginInit und EndInit zum Initialisieren des Elements

Verschiedene Klassen in WPF implementieren die ISupportInitialize Schnittstelle. Sie verwenden die methoden BeginInit und EndInit der Schnittstelle, um einen Bereich in Ihrem Code anzugeben, der Initialisierungsschritte enthält (z. B. Festlegen von Eigenschaftswerten, die sich auf das Rendering auswirken). Nachdem EndInit in der Sequenz aufgerufen wurde, kann das Layoutsystem das Element verarbeiten und mit der Suche nach einem impliziten Stil beginnen.

Wenn das Element, für das Sie Eigenschaften festlegen, eine Klasse abgeleitet von FrameworkElement oder FrameworkContentElement ist, können Sie die Klassenversionen von BeginInit und EndInit aufrufen, anstatt zu ISupportInitializezu konvertieren.

Beispielcode

Das folgende Beispiel ist ein Codebeispiel für eine Konsolenanwendung, die Rendering-APIs sowie XamlReader.Load(Stream) aus einer losen XAML-Datei verwendet, um die korrekte Platzierung von BeginInit und EndInit im Zusammenhang mit anderen API-Aufrufen zu veranschaulichen, die Eigenschaften anpassen, die das Rendering beeinflussen.

Das Beispiel veranschaulicht nur die Hauptfunktion. Die Rasterize- und Save-Funktionen (nicht dargestellt) sind Hilfsfunktionen, die sich um die Verarbeitung und die E/A kümmern.

C#
[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");
}

Weitere Informationen