WPF XAML 名稱範圍

XAML 名稱範圍是識別 XAML 中所定義物件的概念。 XAML 名稱範圍中的名稱可以用來建立物件的 XAML 定義名稱與其在物件樹狀結構中的執行個體對等項目之間的關聯性。 一般而言,在載入 XAML 應用程式的個別 XAML 頁面根目錄時,會建立 WPF Managed 程式碼中的 XAML 命名範圍。 XAML 命名範圍,因為程式設計物件是由 INameScope 介面所定義,而且也會由實體類別 NameScope 實作。

所載入 XAML 應用程式中的名稱範圍

在更廣泛的程式設計或電腦科學內容中,程式設計概念通常包括可用來存取物件之唯一識別碼或名稱的原則。 針對使用識別碼或名稱的系統,在要求該名稱的物件時,名稱範圍會定義程序或技術將在其內搜尋的界限,或是在其中強制執行識別名稱唯一性的界限。 這些一般原則適用於 XAML 名稱範圍。 在 WPF 中,載入 XAML 頁面時,會在頁面的根項目上建立 XAML 名稱範圍。 在頁面根開始之 XAML 頁面內所指定的每個名稱都會新增至適當的 XAML 名稱範圍。

在 WPF XAML 中,通用根項目 (例如 PageWindow ) 的專案一律會控制 XAML 命名範圍。 如果 或 之類的 FrameworkElementFrameworkContentElement 專案是標記中頁面的根項目,XAML 處理器會隱含地新增 Page 根目錄,以便 Page 提供有效的 XAML 命名範圍。

注意

WPF 建置動作會為 XAML 生產環境建立 XAML 命名範圍,即使 XAML 標記中的任何元素上未 Name 定義 或 x:Name 屬性也一樣。

如果您嘗試在任何 XAML 名稱範圍中使用相同的名稱兩次,則會引發例外狀況。 針對具有程式碼後置且為已編譯應用程式一部分的 WPF XAML,在初始標記編譯期間建立頁面的已產生類別時,WPF 建置動作會在建置期間引發例外狀況。 針對未透過任何建置動作進行標記編譯的 XAML,在載入 XAML 時,可能會引發 XAML 名稱範圍問題的相關例外狀況。 XAML 設計工具也可能預期會在設計階段發生 XAML 名稱範圍問題。

將物件新增至執行階段物件樹狀結構

剖析 XAML 的時間點代表建立和定義 WPF XAML 名稱範圍的時間點。 如果您在剖析已產生該樹狀結構的 XAML 之後的某個時間點,將物件新增至物件樹狀結構,則新物件上的 Namex:Name 值不會自動更新 XAML 名稱範圍中的資訊。 若要在載入 XAML 之後,將物件的名稱新增至 WPF XAML 命名範圍,您必須在定義 XAML 命名範圍的物件上呼叫適當的 實 RegisterName 作,這通常是 XAML 頁面根目錄。 如果未註冊名稱,則無法透過 之類的 FindName 方法參考新增的物件,而且您無法使用該名稱進行動畫目標設定。

應用程式開發人員最常見的案例是,您將用來 RegisterName 將名稱註冊到頁面目前根目錄的 XAML 名稱範圍。 RegisterName 是針對以動畫物件為目標之分鏡腳本的重要案例的一部分。 如需詳細資訊,請參閱分鏡腳本概觀

如果您在定義 XAML 命名範圍之物件以外的物件上呼叫 RegisterName ,該名稱仍會登錄至呼叫物件所保存的 XAML 命名範圍,就像您在 XAML 命名範圍定義物件上呼叫 RegisterName 一樣。

程式碼中的 XAML 名稱範圍

您可以在程式碼中建立 XAML 名稱範圍後來加以使用。 即使純程式碼使用方式,XAML 命名範圍建立所涉及的 API 和概念也一樣,因為 WPF 的 XAML 處理器會在處理 XAML 本身時使用這些 API 和概念。 概念和 API 的存在目的主要是可以依名稱在物件樹狀結構內找到物件,而物件樹狀結構一般是在 XAML 中部分或完整定義。

對於以程式設計方式建立,而不是從載入的 XAML 建立的應用程式,定義 XAML 命名範圍的物件必須實 INameScope 作 或 FrameworkElementFrameworkContentElement 或 衍生類別,以支援在其實例上建立 XAML 命名範圍。

此外,針對 XAML 處理器未載入和處理的任何項目,預設都不會建立或初始化物件的 XAML 名稱範圍。 您必須針對任何您要註冊名稱的物件,明確建立新的 XAML 名稱範圍。 若要建立 XAML 命名範圍,您可以呼叫靜態 SetNameScope 方法。 指定將擁有它做為 參數的物件 dependencyObject ,並將新的 NameScope 建構函式呼叫指定為 value 參數。

如果提供的 dependencyObjectSetNameScope 物件不是 實 INameScope 作,或 FrameworkContentElementFrameworkElement 則在任何子專案上呼叫 RegisterName 將不會有任何作用。 如果您無法明確建立新的 XAML 命名範圍,則 對 RegisterName 的呼叫將會引發例外狀況。

如需在程式碼中使用 XAML 名稱範圍 API 的範例,請參閱定義名稱範圍

樣式和範本中的 XAML 名稱範圍

WPF 中的樣式和範本可讓您以直接的方式重複使用和重新套用內容。 不過,樣式和範本可能也包括具有範本層級所定義之 XAML 名稱的項目。 可能會在頁面中多次使用這個相同的範本。 因此,樣式和範本都會定義其專屬 XAML 名稱範圍,這與物件樹狀結構中套用樣式或範本的位置無關。

請考慮下列範例:

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  >
  <Page.Resources>
    <ControlTemplate x:Key="MyButtonTemplate" TargetType="{x:Type Button}">
      <Border BorderBrush="Red" Name="TheBorder" BorderThickness="2">
        <ContentPresenter/>
      </Border>      
    </ControlTemplate>
  </Page.Resources>
  <StackPanel>
    <Button Template="{StaticResource MyButtonTemplate}">My first button</Button>
    <Button Template="{StaticResource MyButtonTemplate}">My second button</Button>
  </StackPanel>
</Page>

在這裡,相同的範本會套用至兩個不同的按鈕。 如果範本沒有離散 XAML 名稱範圍,則範本中所使用的 TheBorder 名稱會導致 XAML 名稱範圍中的名稱衝突。 範本的每個具現化都有其專屬的 XAML 名稱範圍;因此,在此範例中,每個具現化範本的 XAML 名稱範圍都只會包含一個名稱。

樣式也會定義其專屬的 XAML 名稱範圍;因此,分鏡腳本的各部分一般可以獲指派特定名稱。 即使已在控制項自訂時重新定義範本,這些名稱還是可以啟用將目標設為該名稱之項目的控制項特定行為。

因為不同的 XAML 名稱範圍,所以在範本中尋找具名項目會比在頁面中尋找非範本具名項目更具挑戰。 您必須先取得 Template 套用範本之控制項的屬性值,以判斷套用的範本。 然後,您呼叫 的 FindName 範本版本,傳遞範本套用為第二個參數的控制項。

如果您是控制項作者,而且正在產生慣例,其中套用範本中的特定具名元素是控制項本身所定義之行為的目標,您可以使用 GetTemplateChild 控制項實作程式碼中的 方法。 方法 GetTemplateChild 受到保護,因此只有控制項作者可以存取它。

如果您要從範本內工作,而且需要取得套用範本的 XAML 命名範圍,請取得 的值 TemplatedParent ,然後 FindName 呼叫該處。 在範本內運作的範例就是您要撰寫事件處理常式實作,其中,將從已套用範本中的項目引發事件。

FrameworkElement 具有 FindNameRegisterNameUnregisterName 方法。 如果您在其上呼叫這些方法的物件擁有 XAML 名稱範圍,則方法會呼叫相關 XAML 名稱範圍的方法。 否則,會檢查父項目,確認它是否擁有 XAML 名稱範圍,而且此程序會遞迴地執行,直到找到 XAML 名稱範圍 (因為 XAML 處理器行為,所以根一定會有 XAML 名稱範圍)。 FrameworkContentElement 具有類似的行為,但例外狀況是永遠不會 FrameworkContentElement 擁有 XAML 命名範圍。 方法存在於 上 FrameworkContentElement ,以便最終可以將呼叫轉送至 FrameworkElement 父元素。

SetNameScope 是用來將新的 XAML 命名範圍對應至現有的物件。 您可以多次呼叫 SetNameScope ,以重設或清除 XAML 命名範圍,但這不是常見的用法。 此外, GetNameScope 通常不會從程式碼使用。

XAML 名稱範圍實作

下列類別會直接實 INameScope 作:

ResourceDictionary 不使用 XAML 名稱或名稱範圍;它會改用索引鍵,因為它是字典實作。 實作 INameScope 的唯一原因是 ResourceDictionary ,它可以對使用者程式碼引發例外狀況,以協助厘清真正的 XAML 命名範圍與 ResourceDictionary 處理索引鍵的方式,以及確保 XAML 命名範圍不會套用至 ResourceDictionary 父元素的 。

FrameworkTemplateStyle 透過明確的介面定義來實 INameScope 作。 明確實作可讓這些 XAML 命名範圍在透過 介面存取 INameScope 時,以傳統方式運作,也就是 WPF 內部進程如何傳達 XAML 命名範圍。 但是明確的介面定義不是 和 的傳統 API 介面的 FrameworkTemplate 一部分,因為您不需要 INameScope 直接呼叫 和 Style 上的 FrameworkTemplate 方法,而是會改用其他 API,例如 GetTemplateChildStyle

下列類別會使用 System.Windows.NameScope 協助程式類別,並透過 NameScope.NameScope 附加屬性連線到其 XAML 命名範圍實作,以定義自己的 XAML 命名範圍:

另請參閱