共用方式為


認識 XAML 節點資料流結構和概念

.NET Framework XAML 服務中實作的 XAML 讀取器和 XAML 寫入器是以 XAML 節點資料流的設計概念為基礎。 XAML 節點資料流是將一組 XAML 節點進行概念化的結果。 在此概念化過程中,XAML 處理器會走過整個 XAML 中的節點關聯性結構一遍 (一次走過一個節點關聯性)。 不論何時,開啟的 XAML 節點資料流內都只有一個目前記錄或目前位置存在,而且 API 的許多部分都只報告可從該位置取得的資訊。 XAML 節點資料流中的目前節點可以解讀為物件、成員或值。 藉由以 XAML 節點資料流的形式處理 XAML,XAML 讀取器可以與 XAML 寫入器溝通,並且讓程式在執行牽涉到 XAML 的載入路徑或儲存路徑作業期間,檢視、變更 XAML 節點資料流的內容,或與 XAML 節點資料流的內容互動。 XAML 讀取器和寫入器 API 設計以及 XAML 節點資料流概念,類似於過去相關的讀取器/寫入器設計和概念,例如 XML Document Object Model (DOM) 以及 XmlReaderXmlWriter。 本主題將討論 XAML 節點資料流概念,並說明如何撰寫可在 XAML 節點層級與 XAML 表示互動的常式。

這個主題包含下列章節。

  • 將 XAML 載入至 XAML 讀取器中
  • 基本的節點讀取迴圈
  • 處理目前節點
  • 周遊及進入物件節點
  • 值轉換器與 XAML 節點資料流
  • XAML 節點資料流中的 XML 與 XAML 語言定義成員
  • 節點順序
  • 相關主題

將 XAML 載入至 XAML 讀取器中

基底 XamlReader 類別不會宣告將初始 XAML 載入至 XAML 讀取器時使用的特定技術。 然而,衍生類別會宣告及實作載入技術,包括其 XAML 輸入來源的一般特性和限制。 例如,XamlObjectReader 會讀取物件圖形 (從代表根目錄或基底之單一物件的輸入來源開始)。 XamlObjectReader 會接著從物件圖形產生 XAML 節點資料流。

在 .NET Framework XAML 服務定義的 XamlXmlReader 子類別中,以 XamlReader 最為重要。 XamlXmlReader 會藉由直接透過資料流或檔案路徑載入文字檔,或是間接透過 TextReader 之類的相關讀取器類別,來載入初始 XAML。 在完成載入後,即可將 XamlReader 視為包含完整的 XAML 輸入來源。 但 XamlReader 基底 API 是設計成讓讀取器與 XAML 的單一節點互動。 在首次載入時,您所遇到的第一個單一節點即是 XAML 的根與其起始物件。

XAML 節點資料流概念

如果就存取 XML 技術而言,您通常比較熟悉 DOM、樹狀結構比喻或查詢式方法,則以下是將 XAML 節點資料流概念化的實用方法。 請將載入的 XAML 想像成是 DOM 或樹狀結構,其中每個可能的節點已全然展開,然後以線性方式呈現。 當您向前推進節點時,會不斷周遊「進」或周遊「出」與 DOM 相關的層級,但 XAML 節點資料流並不會明確進行追蹤,因為這些層級概念與節點資料流無關。 節點資料流具有「目前」位置,但除非您自己已儲存資料流的其他部分做為參考,否則節點資料流中除目前節點位置外的其他每個部分都不在檢視範圍。

XAML 節點資料流概念有一項重要優點:跑遍整個節點資料流即代表整個 XAML 表示都受到處理;您不需要擔心查詢、DOM 作業或其他非線性資訊處理方法錯過了整個 XAML 表示的某些部分。 基於這個理由,XAML 節點資料流表示很適合用於連接 XAML 讀取器和 XAML 寫入器,以及用於提供一套系統,讓您在其中插入會在 XAML 處理作業的讀取與寫入階段之間執行的自訂處理序。 在許多情況下,XAML 讀取器會刻意最佳化或重新排列 XAML 節點資料流中的節點順序,而不保留來源文字、二進位或物件圖形中原本的順序。 此行為的目的在於增強 XAML 處理結構,讓 XAML 寫入器永遠不需要「回到」節點資料流中先前的位置。 在理想狀況下,所有 XAML 寫入作業都應能夠根據結構描述內容以及節點資料流中的目前位置來運作。

基本的節點讀取迴圈

用於檢查 XAML 節點資料流的基本節點讀取迴圈,涵蓋了下列概念。 為便於說明本主題中所討論的節點迴圈,假設您使用 XamlXmlReader 讀取文字架構、人們可讀取的 XAML 檔案。 本節中的連結所指的是由 XamlXmlReader 實作的特定 XAML 節點迴圈 API。

  • 確定您不在 XAML 節點資料流的結尾 (請查看 IsEof,或使用 Read() 傳回值)。 如果您在資料流的結尾,則不會有目前節點,而這就是您應該結束作業的時候。

  • 呼叫 NodeType,以檢查 XAML 節點資料流目前公開的節點是何種型別。

  • 如果您有直接連接的相關聯 XAML 物件寫入器,您通常會在這個時候呼叫 WriteNode

  • 根據所報告為目前節點或目前記錄的 XamlNodeType,呼叫下列其中一項,以取得有關節點內容的資訊:

    • 對於 StartMemberEndMemberNodeType,請呼叫 Member 以取得有關成員的 XamlMember 資訊。 請注意,成員可以是 XamlDirective,因此不一定是前附物件的傳統型別定義的成員。 例如,套用至物件的 x:Name 會顯示為 XAML 成員,其中 IsDirective 為 true 且成員的 Name 為 Name,而其他屬性指出此指示詞在 XAML 語言 XAML 命名空間之下。

    • 對於 StartObjectEndObjectNodeType,請呼叫 Type 以取得有關物件的 XamlType 資訊。

    • 對於 ValueNodeType,請呼叫 Value。 只有當節點是成員值的最簡單表示方式,或是物件的初始設定文字時,節點才算是值 (但是,您應留意本主題下一節中說明的型別轉換行為)。

    • 對於 NamespaceDeclarationNodeType,請呼叫 Namespace 以取得命名空間節點的命名空間資訊。

  • 呼叫 Read 讓 XAML 讀取器前進到 XAML 節點資料流中的下一個節點,然後重複前述步驟。

.NET Framework XAML 服務 XAML 讀取器所提供的 XAML 節點資料流,一律會完整深入地周遊一遍所有可能的節點。 XAML 節點迴圈的典型流程控制技巧,包括在 while (reader.Read()) 內定義主體,以及在節點迴圈中的每個節點上開啟 NodeType

如果節點資料流位於檔案的結尾,則目前節點為 null。

使用一個讀取器和一個寫入器的最簡單迴圈會類似下列範例。

XamlXmlReader xxr = new XamlXmlReader(new StringReader(xamlStringToLoad));
//where xamlStringToLoad is a string of well formed XAML
XamlObjectWriter xow = new XamlObjectWriter(xxr.SchemaContext);
while (xxr.Read()) {
  xow.WriteNode(xxr);
}

這個載入路徑 XAML 節點迴圈基本範例會明確地連接 XAML 讀取器與 XAML 寫入器,所執行之作業與您使用 XamlServices.Parse 時並無二致。 但此基本結構接下來會擴充,以套用至您的讀取或寫入情節。 以下是部分可能的情節:

  • NodeType 進行切換。 根據正在讀取的節點型別執行不同的動作。

  • 在任何情況下皆不呼叫 WriteNode。 只會在某些 NodeType 案例中呼叫 WriteNode

  • 在特定節點型別的邏輯中,分析該節點的特定項目並對其執行動作。 例如,您可能會僅寫入來自特定 XAML 命名空間的物件,然後捨棄或延後並非來自該 XAML 命名空間的物件。 或者,您可能會在部分成員進行處理時,捨棄或重新處理您的 XAML 系統不支援的任何 XAML 指示詞。

  • 定義會覆寫 Write* 方法的自訂 XamlObjectWriter,這時可能會執行會略過 XAML 結構描述內容的型別對應。

  • 建構 XamlXmlReader 以使用非預設 XAML 結構描述內容,讓讀取器和寫入器兩者都使用自訂的 XAML 行為差異。

存取 XAML 而不用到節點迴圈概念

除了 XAML 節點迴圈以外,可能還有其他方式可以處理 XAML 表示。 例如,可能有一種 XAML 讀取器可以存取索引節點,或甚至是直接以 x:Name、x:Uid 或其他識別碼存取節點。 .NET Framework XAML 服務不會提供完整實作,但會透過服務和支援型別提供建議模式。 如需詳細資訊,請參閱 IXamlIndexingReaderXamlNodeList

秘訣秘訣

Microsoft 也製作了一套稱為 Microsoft XAML Toolkit 的非常態工具。這項非常態工具仍在發行前階段。但是,如果您願意使用發行前元件,Microsoft XAML Toolkit 會提供一些有趣的資源,以便用於 XAML 工具和 XAML 的靜態分析。Microsoft XAML Toolkit 包含 XAML DOM API、FxCop 分析支援,以及 Silverlight 適用的 XAML 結構描述內容。如需詳細資訊,請參閱 Microsoft XAML Toolkit

處理目前節點

在使用 XAML 節點迴圈的情節中,通常不會只讀取節點。 這些情節大多會處理目前節點,然後將每個節點逐一傳遞給 XamlWriter 的實作。

在典型的載入路徑情節中,XamlXmlReader 會產生 XAML 節點資料流,而 XAML 節點會在按照您的邏輯和 XAML 結構描述內容受到處理後,傳遞給 XamlObjectWriter。 然後,您就將產生的物件圖形整合至您的應用程式或架構中。

在典型的儲存路徑情節中,XamlObjectReader 會讀取物件圖形、個別的 XAML 節點會受到處理,然後 XamlXmlWriter 會輸出 XAML 文字檔格式的序列化結果。 重點是這兩種路徑和情節都只需要一次處理一個 XAML 節點,且 XAML 節點可依照 XAML 型別系統和 .NET Framework XAML 服務 API 所定義的標準化方式接受處理。

框架和範圍

XAML 節點迴圈會以線性方式走過整個 XAML 節點資料流一遍。 節點資料流會周遊至物件中、再周遊至包含其他物件的成員中,依此類推。 若要追蹤 XAML 節點資料流內的範圍,實作框架和堆疊概念通常會很有用。 尤其是當您要藉著還在節點資料流中的機會來主動調整節點資料流時,更是如此。 您在節點迴圈邏輯中實作的框架和堆疊支援,可以在您進入 XAML 節點結構時計算 StartObject (或 GetObject) 和 EndObject 範圍 (如果以 DOM 的觀點來看這個結構)。

周遊及進入物件節點

XAML 讀取器在節點資料流中開啟的第一個節點,即為根物件的起始物件節點。 根據定義,此物件一律為單一物件節點,且不具對等項目。 在所有實際的 XAML 範例中,根物件都會定義成具有一個或多個包含更多物件的屬性,且這些屬性將會有成員節點。 成員節點也會有一個或多個物件節點,或者可能會終止於某個值節點。 根物件通常會定義 XAML 命名範圍,這些命名範圍在語法上是指派做為 XAML 文字標記中的屬性,但是會對應於 XAML 節點資料流表示中的 Namescope 節點型別。

請考量下列 XAML 範例 (此為任意 XAML,不受 .NET Framework 中現有型別的支援)。 假設在此物件模型中,FavorCollection 是 Favor 的 List<T>、Balloon 與 NoiseMaker 可被指派給 Favor、Balloon.Color 屬性由 Color 物件支援 (類似於 WPF 將色彩定義做為已知色彩名稱的方式),而且 Color 支援屬性語法的型別轉換子。

XAML 標記

產生的 XAML 節點資料流

<Party

Party 的 Namespace 節點

xmlns="PartyXamlNamespace">

Party 的 StartObject 節點

  <Party.Favors>

Party.Favors 的 StartMember 節點

隱含 FavorCollection 的 StartObject 節點

隱含 FavorCollection 項目屬性的 StartMember 節點。

    <Balloon

Balloon 的 StartObject 節點

      Color="Red"

Color 的 StartMember 節點

  屬性值字串 "Red" 的 Value 節點

Color 的 EndMember

      HasHelium="True"

HasHelium 的 StartMember 節點

  屬性值字串 "True" 的 Value 節點

HasHelium 的 EndMember

    >

Balloon 的 EndObject

    <NoiseMaker>Loudest</NoiseMaker>

NoiseMaker 的 StartObject 節點

_Initialization 的  StartMember 節點

    初始設定值字串 "Loudest" 的 Value 節點

_Initialization 的  EndMember 節點

NoiseMaker 的 EndObject

隱含 FavorCollection 項目屬性的 EndMember 節點。

隱含 FavorCollection 的 EndObject 節點

  </Party.Favors>

Favors 的 EndMember

</Party>

Party 的 EndObject

在 XAML 節點資料流中,您可以倚賴下列行為:

  • 如果 Namespace 節點存在,則該節點會加入至資料流中緊接在以 xmlns 宣告 XAML 命名空間的 StartObject 之前。 請重新查看先前含有 XAML 與範例節點資料流的表格。 請注意,與文字標記中的宣告位置相比,StartObject 與 Namespace 節點的位置似乎互調了。 命名空間節點一律會出現在節點資料流中套用命名空間節點的節點之前,這是很具代表性的行為。 此設計的用意是命名空間資訊對於物件寫入器是至關重要的,因此必須在物件寫入器嘗試要執行型別對應或處理物件之前表明這項資訊。 在資料流中將 XAML 命名空間資訊放在其應用程式範圍之前,較容易一律以呈現的順序處理節點資料流。

  • 基於前述考量,當您從頭周遊節點時,您在實際的標記中首先讀取的會是一個或多個 Namespace 節點,而不是根的 StartObject。

  • StartObject 節點之後可以是 StartMember、Value,或直接使用 EndObject。 其後一律不可直接使用另一個 StartObject。

  • StartMember 之後可以是 StartObject、Value,或直接使用 EndMember。 如果成員的此值應當來自父物件的現有值而非來自會具現化新值的 StartObject,則後面可以使用 GetObject。 其後面也可以使用 Namespace 節點,該節點會套用至即將來臨的 StartObject。 其後一律不可直接使用另一個 StartMember。

  • Value 節點代表值本身;並沒有所謂的 "EndValue"。 其後只可以是 EndMember。

    • 用於建構的 XAML 物件初始設定文字不會產生「物件-值」結構。 但是會建立成員的專用成員節點,名為 _Initialization。 且該成員節點會包含初始設定值字串。 如果該字串存在,_Initialization 一律會是第一個 StartMember。 _Initialization 在某些具有 XAML 語言 XAML 名稱範圍的 XAML 服務表示中可能會受到限定,以闡明 _Initialization 不是支援型別中已定義的屬性。

    • 「成員-值」組合代表值的屬性設定。 最終處理此值時還可能會用到值轉換子,而值是一般字串。 但在 XAML 物件寫入器處理此節點資料流時,並不會計算該值。 XAML 物件寫入器具有必要的 XAML 結構描述內容、型別系統對應、以及轉換值時所需的其他支援。

  • EndMember 節點之後可以是後續成員的 StartMember 節點,或是成員擁有者的 EndObject 節點。

  • EndObject 節點之後可以是 EndMember 節點。 其後也可以跟隨 StartObject 節點,只要物件對等於集合的項目中。 或者,其後面也可以使用 Namespace 節點,該節點會套用至即將來臨的 StartObject。

    • 在關閉整個節點資料流的這種特殊情形中,根的 EndObject 之後沒有任何項目;讀取器此時為檔案結尾,且 Read 會傳回 false。

值轉換器與 XAML 節點資料流

值轉換器在標記延伸、型別轉換器 (包括值序列化程式) 或其他透過 XAML 型別系統報告為值轉換器的專用類別中,是常見的詞彙。 在 XAML 節點資料流中,型別轉換器用法與標記延伸用法會以截然不同的方式呈現。

XAML 節點資料流中的型別轉換子

最終導致必須使用型別轉換子的屬性集,在 XAML 節點資料流中會報告為成員的值。 XAML 節點資料流不會嘗試產生型別轉換器執行個體物件以及為其傳送值。 使用型別轉換子的轉換實作時,必須叫用 XAML 結構描述內容並將它用於型別對應。 即使是在決定應使用何種型別轉換器類別來處理值時,也會間接用到 XAML 結構描述內容。 當您使用預設 XAML 結構描述內容時,可以從 XAML 型別系統取得該資訊。 如果您在連接至 XAML 寫入器之前,需要 XAML 節點資料流層級的型別轉換子類別資訊,您可以從要設定之成員的 XamlMember 資訊取得這項資訊。 否則,您應該將型別轉換子輸入以一般值的形式保留在 XAML 節點資料流中,直到執行作業中其餘需要使用型別對應系統和 XAML 結構描述內容的部分 (例如,XAML 物件寫入器所執行的物件建立作業) 為止。

例如,請考量下列類別定義大綱及其 XAML 用法:

    public class BoardSizeConverter : TypeConverter {
      //converts from string to an int[2] by splitting on an "x" char
    }
    public class GameBoard {
      [TypeConverter(typeof(BoardSizeConverter))]
      public int[] BoardSize; //2x2 array, initialization not shown
    }
    <GameBoard BoardSize="8x8"/>

XAML 節點資料流採取此用法時的文字表示可以是:

XamlType 代表 GameBoard 的 StartObject

XamlMember 代表 BoardSize 的 StartMember

Value 節點,具有文字字串 "8x8"

EndMember 符合 BoardSize

EndObject 符合 GameBoard

請注意,在此節點資料流中沒有型別轉換器執行個體。 但您可以對代表 BoardSize 的 XamlMember 呼叫 XamlMember.TypeConverter,以取得型別轉換子資訊。 如果您具備有效的 XAML 結構描述內容,您也可以從 ConverterInstance 取得執行個體,以叫用轉換子方法。

XAML 節點資料流中的標記延伸

標記延伸用法在 XAML 節點資料流中會報告為成員內的物件節點,其中,會以物件代表標記延伸執行個體。 因此,標記延伸用法在節點資料流表示中會比型別轉換子用法更明確地呈現,而且提供更多的資訊。 XamlMember 資訊無法事先向您告知任何關於標記延伸的事項,因為此用法會隨條件而變化,並且在每個可能的標記案例中都不同;它並不像型別轉換器的用法,會根據型別或成員而專用與隱含。

即使標記延伸在 XAML 文字標記中是以屬性的形式使用 (此為常用做法),節點資料流中還是會以物件節點的形式表示標記延伸。 使用明確物件項目格式的標記延伸用法,也會以相同的方式受到處理。

在標記延伸物件節點內,可能會有該標記延伸的成員。 XAML 節點資料流表示會保留該標記延伸的用法,無論是位置參數用法或使用明確具名參數的用法,都是如此。

使用位置參數用法時,XAML 節點資料流會包含可記錄用法的 XAML 語言定義屬性 _PositionalParameters。 此屬性是具有 Object 條件約束的泛型 List<T>。 此條件約束是物件而非字串,因為位置參數用法應可包含巢狀標記延伸用法。 若要存取此用法中的位置參數,您可以逐一查看清單,並使用索引子取得個別的清單值。

使用具名參數用法時,每個具名參數在節點資料流中都會呈現為具有該名稱的成員節點。 成員值不一定是字串,因為可能會有巢狀標記延伸用法。

來自標記延伸的 ProvideValue 尚未叫用。 但是,如果您連接 XAML 讀取器與 XAML 寫入器,而使標記延伸節點在您於節點資料流中加以檢查時會叫用 WriteEndObject,則會叫用此項。 因此,您通常需要在載入路徑上構成物件圖形時所使用的相同 XAML 結構描述內容。 否則,來自任何標記延伸的 ProvideValue 均可能在此擲回例外狀況,因為它不具備預期的可用服務。

XAML 節點資料流中的 XML 與 XAML 語言定義成員

某些成員會導入至 XAML 節點資料流中,是基於 XAML 讀取器的解譯與慣例的關係,而不是基於明確的 XamlMember 查閱或建構動作。 這些成員通常是 XAML 指示詞。 在某些情況下,使指示詞導入至 XAML 節點資料流中的是讀取 XAML 的動作。 換言之,原本輸入的 XAML 文字並未明確指定成員指示詞,但 XAML 讀取器會插入此指示詞,以便滿足 XAML 結構慣例,並在 XAML 節點資料流中報告資訊以防該資訊遺失。

以下清單指出 XAML 讀取器預期會導入指示詞 XAML 成員節點的所有情況,以及在 .NET Framework XAML 服務實作中識別該成員節點的方式。

  • 物件節點的初始設定文字: 此成員節點的名稱為 _Initialization,代表的是 XAML 指示詞,且定義於 XAML 語言 XAML 命名空間中。 您可以從 Initialization 取得其靜態實體。

  • 標記延伸的位置參數: 此成員節點的名稱為 _PositionalParameters,定義於 XAML 語言 XAML 命名空間中。 其一律包含泛型的物件清單,其中每個物件都是以輸入 XAML 中提供的 , 分隔字元預先隔開的位置參數。 您可以從 PositionalParameters 取得位置參數指示詞的靜態實體。

  • 未知內容:此成員節點的名稱為 _UnknownContent。 嚴格來說,此為 XamlDirective,定義於 XAML 語言 XAML 命名空間中。 在來源 XAML 中的 XAML 物件項目包含內容,但在目前可用的 XAML 結構描述內容下無法判斷任何內容屬性的情況下,會以此指示詞做為 Sentinel。 您可以檢查是否有名為 _UnknownContent 的成員,以在 XAML 節點資料流中偵測此情況。 如果載入路徑 XAML 節點資料流中未採取其他動作,預設 XamlObjectWriter 在任何物件上發現 _UnknownContent 成員時,將會對嘗試的 WriteEndObject 擲回。 預設 XamlXmlWriter 並不會擲回,而會將該成員視為隱含成員。 您可以從 UnknownContent 取得 _UnknownContent 的靜態實體。

  • 集合的集合屬性:雖然用於 XAML 之集合類別的支援 CLR 型別通常有專用的具名屬性來指出集合項目,但是在支援型別獲得解析之前,XAML 型別系統並不認得該屬性。 不過,XAML 節點資料流會導入 Items 預留位置,做為集合 XAML 型別的成員。 在 .NET Framework XAML 服務實作中,節點資料流中此指示詞 / 成員的名稱為 _Items。 您可以從 Items 取得此指示詞的常數。

    請注意,XAML 節點資料流可能包含 Items 屬性,裡面的項目可能會依據支援型別解析結果和 XAML 結構描述內容,變成無法剖析的項目。 例如:

  • XML 定義的成員:在 .NET Framework XAML 服務實作中,XML 定義的 xml:base、xml:lang 和 xml:space 成員會分別報告為名為 base、lang 和 space 的 XAML 指示詞。 這些成員的命名空間是 XML 命名空間 http://www.w3.org/XML/1998/namespace。 前述每個成員的常數都可從 XamlLanguage 取得。

節點順序

在某些情況下,XamlXmlReader 會變更 XAML 節點資料流中的 XAML 節點順序,而不使用在標記中檢視或當做 XML 處理時顯示的節點順序。 進行這項排序的目的,是為了讓 XamlObjectWriter 可以用只進不退的方式處理節點資料流。 在 .NET Framework XAML 服務中,XAML 讀取器會重新排序節點,而不是將這項工作留給 XAML 寫入器,以便讓節點資料流的 XAML 物件寫入器取用者獲得最佳的效能。

某些指示詞專門是為了提供更多資訊而設,以便從物件項目建立物件。 這些指示詞為:Initialization、PositionalParameters、TypeArguments、FactoryMethod、Arguments。 .NET Framework XAML 服務 XAML 讀取器會嘗試將這些指示詞安排為節點資料流中之物件的 StartObject 後面的前幾個成員,下一節會說明原因。

XamlObjectWriter 行為和節點順序

XamlObjectWriter 的 StartObject 不一定代表 XAML 物件寫入器必須立即建構物件執行個體。 XAML 內含數項語言功能,可讓您以更多輸入來初始化物件,而不需完全依賴叫用預設建構函式來產生初始物件,然後才設定屬性。 這些功能包括:XamlDeferLoadAttribute、初始設定文字、x:TypeArguments、標記延伸的位置參數、Factory 方法和相關聯的 x:Arguments 節點 (XAML 2009)。 上述每種例子都會延後實際建構物件的時間,且因為節點資料流已重新排序,所以 XAML 物件寫入器每當遇到起始成員不是該物件型別的專屬建構指示詞時,便可以依賴實際建構執行個體這樣的行為。

GetObject

GetObject 代表一個 XAML 節點,此節點表示 XAML 物件寫入器在遇到這個節點時,應取得物件所在屬性的值,而不是建構新的物件。 在 XAML 節點資料流中遇到 GetObject 節點的典型情況是,支援型別的物件模型中刻意將集合物件或字典物件所在的屬性保持唯讀。 在此情節中,往往會依擁有端型別的初始化邏輯來建立及初始化集合或字典 (通常空白)。

請參閱

參考

XamlObjectReader

概念

XAML 服務

其他資源

.NET Framework XAML 服務的 XAML 命名空間