Megosztás a következőn keresztül:


Nem objektumfában lévő objektumelemek inicializálása

A Windows Presentation Foundation (WPF) inicializálásának bizonyos aspektusai olyan folyamatokra halaszthatók, amelyek általában arra támaszkodnak, hogy az elem a logikai fához vagy a vizualizációfához csatlakozik. Ez a témakör azokat a lépéseket ismerteti, amelyek szükségesek lehetnek egy olyan elem inicializálásához, amely nem kapcsolódik egyik fához sem.

Elemek és a logikai fa

Amikor létrehoz egy Windows Presentation Foundation (WPF) osztályt a kódban, vegye figyelembe, hogy a Windows Presentation Foundation (WPF) osztály objektum-inicializálásának több aspektusa szándékosan nem része annak a kódnak, amelyet az osztálykonstruktor meghívásakor hajtanak végre. Különösen egy vezérlőosztály esetében a vezérlő vizuális ábrázolásának nagy részét nem a konstruktor határozza meg. Ehelyett a vizualizációt a vezérlő sablonja határozza meg. A sablon számos forrásból származik, de leggyakrabban témastílusokból származik. A sablonok valójában késői kötéseket használnak; a szükséges sablon csak akkor csatolódik a kérdéses vezérlőhöz, amikor a vezérlő készen áll az elrendezés elkészítésére. A vezérlő pedig nem áll készen az elrendezésre, amíg egy logikai fához nem csatlakozik, amely a gyökérfelületen lévő renderelő felülethez csatlakozik. Ez az a gyökérszintű elem, amely a logikai fában meghatározott összes gyermekelem renderelését kezdeményezi.

A vizuális fa is részt vesz ebben a folyamatban. A sablonok útján a vizuális fa részét képező elemek sem lesznek teljesen példányosítva, amíg nincsenek csatlakoztatva.

Ennek a viselkedésnek az a következménye, hogy bizonyos műveletek, amelyek egy elem befejezett vizuális jellemzőire támaszkodnak, további lépéseket igényelnek. Ilyen például, ha egy olyan osztály vizuális jellemzőit próbálja meg lekérni, amelyet létrehoztak, de még nem csatoltak egy fához. Ha például szeretné meghívni a Render-et egy RenderTargetBitmap-en, és az átadott vizualizáció egy olyan elem, amely nem kapcsolódik egy fához, az elem vizuálisan nem teljes, amíg a további inicializálási lépéseket nem hajtják végre.

Az elem inicializálása a BeginInit és az EndInit használatával

A WPF különböző osztályai implementálják a ISupportInitialize felületet. A felület BeginInit és EndInit metódusával inicializálási lépéseket tartalmazó régiót jelölhet a kódban (például a megjelenítést befolyásoló tulajdonságértékek beállításához). Miután a EndInit szerepel a sorrendben, az elrendezési rendszer feldolgozhatja az elemet, és elkezdheti keresni a nem kifejezetten megadott stílust.

Ha az elem, amelyre tulajdonságokat állít be, egy FrameworkElement vagy FrameworkContentElement származtatott osztály, akkor a BeginInit és EndInit osztályverzióit kell meghívnia ahelyett, hogy ISupportInitialize-re konvertálna.

Mintakód

Az alábbi példa egy olyan konzolalkalmazás mintakódja, amely renderelő API-kat és a XamlReader.Load(Stream) egy laza XAML-fájl használatát alkalmazza, hogy szemléltesse a BeginInit és a EndInit megfelelő elhelyezését más API-hívások körül, amelyek a renderelést befolyásoló tulajdonságok módosítására szolgálnak.

A példa csak a fő függvényt szemlélteti. A Rasterize és Save függvények (nem jelennek meg) olyan segédprogramfüggvények, amelyek a képfeldolgozást és az I/O-t kezelik.

[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

Lásd még