Share via


初始化物件樹狀結構以外的物件元素

Windows Presentation Foundation (WPF) 初始化的某些層面會延後至通常依賴該元素連線到邏輯樹狀結構或視覺化樹狀結構的進程。 本主題說明為了初始化未連接到任一樹狀結構的項目所需的步驟。

項目和邏輯樹狀結構

當您在程式碼中建立 Windows Presentation Foundation (WPF) 類別的實例時,您應該注意 Windows Presentation Foundation (WPF) 類別的物件初始化幾個層面刻意不是呼叫類別建構函式時所執行之程式碼的一部分。 特別是控制項類別,該控制項的視覺表示大部分不是由建構函式定義, 而是由控制項的範本來定義視覺表示。 範本可能來自各種不同的來源,但最常會從佈景主題樣式取得範本。 範本實際上是晚期繫結;必須等到相關控制項可以開始配置之後,才能將所需的範本附加至該控制項。 此外,控制項必須等到附加至連接到根目錄之呈現介面的邏輯樹狀結構之後,才能開始配置。 根層級項目會依照邏輯樹狀結構中的定義,來啟始其所有子項目的呈現。

視覺化樹狀結構也會參與此程序。 透過範本成為視覺化樹狀結構一部分的項目,也必須等到連接之後才能完全具現化。

此行為的結果是,依賴某個項目之完整視覺特性的特定作業需要額外的步驟。 其中一個範例是您嘗試取得某個類別的視覺特性,而此類別已建構但尚未附加至樹狀結構。 例如,如果您想要在 上 RenderTargetBitmap 呼叫 Render ,而您傳遞的視覺效果是未連接到樹狀結構的專案,則在完成其他初始化步驟之前,該元素不會以視覺化方式完成。

使用 BeginInit 和 EndInit 來初始化項目

WPF 中的各種類別會實作 ISupportInitialize 介面。 您可以使用 BeginInit 介面的 和 EndInit 方法來表示程式碼中包含初始化步驟的區域(例如設定會影響轉譯的屬性值)。 在序列中呼叫 之後 EndInit ,配置系統可以處理 元素並開始尋找隱含樣式。

如果您要在 上設定屬性的專案是 FrameworkElementFrameworkContentElement 衍生類別,則可以呼叫 的 BeginInit 類別版本, EndInit 而不是轉換成 ISupportInitialize

範例程式碼

下列範例是主控台應用程式的範例程式碼,其使用轉譯 API 和 XamlReader.Load(Stream) 鬆散的 XAML 檔案,來說明適當放置 BeginInitEndInit 圍繞其他可調整影響轉譯之屬性的 API 呼叫。

此範例只會說明 main 函式。 RasterizeSave 函式 (未顯示) 是負責影像處理和 IO 的公用程式函式。

[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

另請參閱