WPF XAML 名前スコープWPF XAML Namescopes

XAML 名前スコープは、XAML で定義されているオブジェクトを識別する概念です。XAML namescopes are a concept that identifies objects that are defined in XAML. XAML 名前スコープ内の名前を使用すると、オブジェクトの XAML で定義された名前と、オブジェクト ツリー内でそれに対応するインスタンスの間の関係を確立できます。The names in a XAML namescope can be used to establish relationships between the XAML-defined names of objects and their instance equivalents in an object tree. 通常、XAMLアプリケーションの個々の XAML ページ ルートが読み込まれると、WPFWPF マネージド コード内に XAML 名前スコープが作成されます。Typically, XAML namescopes in WPFWPF managed code are created when loading the individual XAML page roots for a XAML application. プログラミング オブジェクトとしての XAML 名前スコープは、INameScope インターフェイスによって定義されており、実際のクラス NameScope によっても実装されます。XAML namescopes as the programming object are defined by the INameScope interface and are also implemented by the practical class NameScope.

読み込まれた XAML アプリケーションでの名前スコープNamescopes in Loaded XAML Applications

広範なプログラミングまたはコンピューター サイエンスのコンテキストでは、プログラミングの概念に、オブジェクトにアクセスするために使用できる一意の識別子または名前の原則が含まれることがよくあります。In a broader programming or computer science context, programming concepts often include the principle of a unique identifier or name that can be used to access an object. 識別子または名前を使用するシステムでは、名前スコープによって、その名前のオブジェクトが要求された場合にプロセスまたは技法によって検索する境界、または識別名の一意性が強制される境界が定義されます。For systems that use identifiers or names, the namescope defines the boundaries within which a process or technique will search if an object of that name is requested, or the boundaries wherein uniqueness of identifying names is enforced. これらの一般的な原則は、XAML 名前スコープにも当てはまります。These general principles are true for XAML namescopes. WPF での XAML 名前スコープは、ページが読み込まれるときに、XAML ページのルート要素に対して作成されます。In WPF, XAML namescopes are created on the root element for a XAML page when the page is loaded. ページ ルートから始まって、XAML ページ内で指定されている各名前が、関連する XAML 名前スコープに追加されます。Each name specified within the XAML page starting at the page root is added to a pertinent XAML namescope.

WPF XAML では、常に、一般的なルート要素 (PageWindow など) である要素によって、XAML 名前スコープが制御されます。In WPF XAML, elements that are common root elements (such as Page, and Window) always control a XAML namescope. FrameworkElementFrameworkContentElement などの要素がマークアップ内のページのルート要素である場合は、Page で動作する XAML 名前スコープを提供できるように、XAMLXAML プロセッサによって Page ルートが暗黙的に追加されます。If an element such as FrameworkElement or FrameworkContentElement is the root element of the page in markup, a XAMLXAML processor adds a Page root implicitly so that the Page can provide a working XAML namescope.

注意

XAMLXAML マークアップ内のどの要素でも Name または x:Name 属性が定義されていない場合でも、WPF のビルド アクションでは、XAML 運用環境に対する XAML 名前スコープが作成されます。WPF build actions create a XAML namescope for a XAML production even if no Name or x:Name attributes are defined on any elements in the XAMLXAML markup.

XAML 名前スコープ内で同じ名前を 2 回使用しようとすると、例外が発生します。If you try to use the same name twice in any XAML namescope, an exception is raised. コードビハインドを持ち、コンパイルされたアプリケーションの一部である WPF XAML の場合、初期マークアップ コンパイルの間にページに対して生成されたクラスを作成すると、WPF ビルド アクションによってビルド時に例外が発生します。For WPF XAML that has code-behind and is part of a compiled application, the exception is raised at build time by WPF build actions, when creating the generated class for the page during the initial markup compile. ビルド アクションによってマークアップ コンパイルされない XAML の場合は、XAML 名前スコープの問題に関連する例外が、XAML の読み込み時に発生する可能性があります。For XAML that is not markup-compiled by any build action, exceptions related to XAML namescope issues might be raised when the XAML is loaded. XAML デザイナーの場合、デザイン時にも XAML 名前スコープの問題が発生する可能性があります。XAML designers might also anticipate XAML namescope issues at design time.

ランタイム オブジェクト ツリーへのオブジェクトの追加Adding Objects to Runtime Object Trees

XAML が解析されるときに、WPF XAML 名前スコープが作成されて定義されます。The moment that XAML is parsed represents the moment in time that a WPF XAML namescope is created and defined. オブジェクト ツリーを生成した XAML が解析された後で、そのオブジェクト ツリーにオブジェクトを追加した場合、新しいオブジェクトの Name または x:Name の値によって、XAML 名前スコープの情報が自動的に更新されることはありません。If you add an object to an object tree at a point in time after the XAML that produced that tree was parsed, a Name or x:Name value on the new object does not automatically update the information in a XAML namescope. XAML が読み込まれた後でオブジェクトの名前を WPF XAML 名前スコープに追加するには、XAML 名前スコープが定義されているオブジェクトで (通常は XAML ページ ルート) RegisterName の適切な実装を呼び出す必要があります。To add a name for an object into a WPF XAML namescope after XAML is loaded, you must call the appropriate implementation of RegisterName on the object that defines the XAML namescope, which is typically the XAML page root. 名前が登録されていない場合は、追加されたオブジェクトを FindName などのメソッドから名前で参照することはできず、その名前をアニメーションの対象として使用することはできません。If the name is not registered, the added object cannot be referenced by name through methods such as FindName, and you cannot use that name for animation targeting.

アプリケーション開発者にとって最も一般的なシナリオは、RegisterName を使用してページの現在のルートの XAML 名前スコープに名前を登録することです。The most common scenario for application developers is that you will use RegisterName to register names into the XAML namescope on the current root of the page. RegisterName は、オブジェクトをアニメーションの対象とするストーリーボードの重要なシナリオの一部です。RegisterName is part of an important scenario for storyboards that target objects for animations. 詳細については、「ストーリーボードの概要」を参照してください。For more information, see Storyboards Overview.

XAML 名前スコープが定義されているオブジェクト以外のオブジェクトで RegisterName を呼び出した場合でも、オブジェクトが定義されている XAML 名前スコープで RegisterName を呼び出した場合と同じように、その名前は、呼び出し元オブジェクトが保持されている XAML 名前スコープに登録されます。If you call RegisterName on an object other than the object that defines the XAML namescope, the name is still registered to the XAML namescope that the calling object is held within, as if you had called RegisterName on the XAML namescope defining object.

コードでの XAML 名前スコープXAML Namescopes in Code

コードで XAML 名前スコープを作成して使用することができます。You can create and then use XAML namescopes in code. XAML 名前スコープの作成に関係する API と概念は、純粋なコードを使用する場合でも同じです。これは、WPFWPF の XAML プロセッサでは、XAML 自体を処理するときにこれらの API と概念が使用されるためです。The APIs and the concepts involved in XAML namescope creation are the same even for a pure code usage, because the XAML processor for WPFWPF uses these APIs and concepts when it processes XAML itself. この概念と API は主に、通常は一部または全部が XAML で定義されているオブジェクト ツリー内で、名前によってオブジェクトを検索できるようにするために存在します。The concepts and API exist mainly for the purpose of being able to find objects by name within an object tree that is typically defined partially or entirely in XAML.

読み込まれた XAML からではなく、プログラムによって作成されるアプリケーションの場合、インスタンスでの XAML 名前スコープの作成をサポートするには、XAML 名前スコープが定義されているオブジェクトで INameScope を実装するか、オブジェクトが FrameworkElement または FrameworkContentElement の派生クラスである必要があります。For applications that are created programmatically, and not from loaded XAML, the object that defines a XAML namescope must implement INameScope, or be a FrameworkElement or FrameworkContentElement derived class, in order to support creation of a XAML namescope on its instances.

また、XAML プロセッサによって読み込まれず、処理されない要素については、オブジェクトに対する XAML 名前スコープが既定で作成または初期化されることはありません。Also, for any element that is not loaded and processed by a XAML processor, the XAML namescope for the object is not created or initialized by default. 後で名前を登録するオブジェクトについては、新しい XAML 名前スコープを明示的に作成する必要があります。You must explicitly create a new XAML namescope for any object that you intend to register names into subsequently. XAML 名前スコープを作成するには、静的な SetNameScope メソッドを呼び出します。To create a XAML namescope, you call the static SetNameScope method. それを所有するオブジェクトを dependencyObject パラメーターとして指定し、新しい NameScope コンストラクターの呼び出しを value パラメーターとして指定します。Specify the object that will own it as the dependencyObject parameter, and a new NameScope constructor call as the value parameter.

SetNameScope に対して dependencyObject として指定されたオブジェクトが、INameScope の実装、FrameworkElement、または FrameworkContentElement ではない場合、任意の子要素で RegisterName を呼び出しても何の効果もありません。If the object provided as dependencyObject for SetNameScope is not a INameScope implementation, FrameworkElement or FrameworkContentElement, calling RegisterName on any child elements will have no effect. 新しい XAML 名前スコープの明示的な作成に失敗した場合、RegisterName を呼び出すと例外が発生します。If you fail to create the new XAML namescope explicitly, then calls to RegisterName will raise an exception.

コードで XAML 名前スコープ API を使用する例については、「名前のスコープを定義する」を参照してください。For an example of using XAML namescope APIs in code, see Define a Name Scope.

スタイルとテンプレートでの XAML 名前スコープXAML Namescopes in Styles and Templates

WPFWPF のスタイルとテンプレートを使用すると、簡単な方法でコンテンツを再利用したり、再適用したりすることができます。Styles and templates in WPFWPF provide the ability to reuse and reapply content in a straightforward way. ただし、スタイルやテンプレートには、テンプレート レベルで XAML 名が定義されている要素が含まれる場合もあります。However, styles and templates might also include elements with XAML names defined at the template level. その同じテンプレートが 1 ページで複数回使用される可能性があります。That same template might be used multiple times in a page. このため、スタイルとテンプレートのどちらでも、スタイルまたはテンプレートが適用されるオブジェクト ツリー内の場所に関係がないように、独自の XAML 名前スコープを定義します。For this reason, styles and templates both define their own XAML namescopes, independent of whatever location in an object tree where the style or template is applied.

次に例を示します。Consider the following example:

<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>

ここでは、同じテンプレートを 2 つの異なるボタンに適用します。Here, the same template is applied to two different buttons. テンプレートに個別の XAML 名前スコープがない場合は、テンプレートで使用されている名前 TheBorder により、XAML 名前スコープで名前の競合が発生します。If templates did not have discrete XAML namescopes, the TheBorder name used in the template would cause a name collision in the XAML namescope. テンプレートのインスタンス化ごとに独自の XAML 名前スコープがあるため、この例では、インスタンス化されるテンプレートの各 XAML 名前スコープには、名前が 1 つだけ含まれます。Each instantiation of the template has its own XAML namescope, so in this example each instantiated template's XAML namescope would contain exactly one name.

また、スタイルでも独自の XAML 名前スコープを定義します。これは主に、ストーリーボードの一部に特定の名前を割り当てることができるようにするためです。Styles also define their own XAML namescope, mostly so that parts of storyboards can have particular names assigned. これらの名前を使用すると、テンプレートがコントロールのカスタマイズの一部として再定義された場合でも、その名前の要素を対象とするコントロール固有の動作が有効になります。These names enable control specific behaviors that will target elements of that name, even if the template was re-defined as part of control customization.

個別の XAML 名前スコープがあるため、テンプレートでの名前付き要素の検索は、ページ内でテンプレート化されていない名前付き要素を見つける場合より困難です。Because of the separate XAML namescopes, finding named elements in a template is more challenging than finding a non-templated named element in a page. 最初に、テンプレートが適用されているコントロールの Template プロパティ値を取得することで、適用されているテンプレートを特定する必要があります。You first need to determine the applied template, by getting the Template property value of the control where the template is applied. 次に、テンプレート バージョンの FindName を呼び出し、テンプレートが適用されたコントロールを 2 番目のパラメーターとして渡します。Then, you call the template version of FindName, passing the control where the template was applied as the second parameter.

コントロールの作成者が、適用されるテンプレートの特定の名前付き要素は、コントロール自体で定義されている動作のターゲットであるという規則を設けている場合は、コントロールの実装コードから GetTemplateChild メソッドを使用できます。If you are a control author and you are generating a convention where a particular named element in an applied template is the target for a behavior that is defined by the control itself, you can use the GetTemplateChild method from your control implementation code. GetTemplateChild メソッドは保護されているので、コントロールの作成者だけがアクセスできます。The GetTemplateChild method is protected, so only the control author has access to it.

テンプレート内から作業していて、テンプレートが適用されている XAML 名前スコープにアクセスする必要がある場合は、TemplatedParent の値を取得し、そこで FindName を呼び出します。If you are working from within a template, and need to get to the XAML namescope where the template is applied, get the value of TemplatedParent, and then call FindName there. テンプレート内での作業の例としては、適用されるテンプレートの要素からイベントが発生するイベント ハンドラーの実装を作成している場合があります。An example of working within the template would be if you are writing the event handler implementation where the event will be raised from an element in an applied template.

FrameworkElement には、FindNameRegisterNameUnregisterName の各メソッドがあります。FrameworkElement has FindName, RegisterName and UnregisterName methods. これらのメソッドを呼び出すオブジェクトが XAML 名前スコープを所有している場合、メソッドでは、関連する XAML 名前スコープのメソッドが呼び出されます。If the object you call these methods on owns a XAML namescope, the methods call into the methods of the relevant XAML namescope. それ以外の場合は、親要素で XAML 名前スコープを所有しているかどうかがチェックされ、XAML 名前スコープが見つかるまで、このプロセスが再帰的に繰り返されます (XAML プロセッサの動作により、ルートには XAML 名前スコープがあることが保証されます)。Otherwise, the parent element is checked to see if it owns a XAML namescope, and this process continues recursively until a XAML namescope is found (because of the XAML processor behavior, there is guaranteed to be a XAML namescope at the root). FrameworkContentElement の動作も似ていますが、XAML 名前スコープを所有する FrameworkContentElement がないという点が異なります。FrameworkContentElement has analogous behaviors, with the exception that no FrameworkContentElement will ever own a XAML namescope. 呼び出しを最終的に FrameworkElement の親要素に転送できるよう、メソッドは FrameworkContentElement に存在します。The methods exist on FrameworkContentElement so that the calls can be forwarded eventually to a FrameworkElement parent element.

SetNameScope は、新しい XAML 名前スコープを既存のオブジェクトにマップするために使用されます。SetNameScope is used to map a new XAML namescope to an existing object. SetNameScope を複数回呼び出して XAML 名前スコープをリセットまたはクリアすることができますが、これは一般的な使用方法ではありません。You can call SetNameScope more than once in order to reset or clear the XAML namescope, but that is not a common usage. また、通常、GetNameScope はコードからは使用されません。Also, GetNameScope is not typically used from code.

XAML 名前スコープの実装XAML Namescope Implementations

次のクラスでは、INameScope が直接実装されています。The following classes implement INameScope directly:

ResourceDictionary では、XAML の名前または名前スコープは使用されません。ディクショナリの実装であるため、代わりにキーが使用されます。ResourceDictionary does not use XAML names or namescopes ; it uses keys instead, because it is a dictionary implementation. ResourceDictionaryINameScope が実装されている唯一の理由は、実際の XAML 名前スコープと ResourceDictionary によるキーの処理方法の違いを明確にするのに役立つ例外をユーザー コードに対して生成することができることと、XAML 名前スコープが親要素によって ResourceDictionary に適用されないようにするためです。The only reason that ResourceDictionary implements INameScope is so it can raise exceptions to user code that help clarify the distinction between a true XAML namescope and how a ResourceDictionary handles keys, and also to assure that XAML namescopes are not applied to a ResourceDictionary by parent elements.

FrameworkTemplateStyle では、明示的なインターフェイス定義によって INameScope が実装されています。FrameworkTemplate and Style implement INameScope through explicit interface definitions. 明示的に実装することで、これらの XAML 名前スコープは INameScope インターフェイスからアクセスされたときに従来のように動作することができます。これは、XAML 名前スコープと WPFWPF 内部プロセスの通信方法です。The explicit implementations allow these XAML namescopes to behave conventionally when they are accessed through the INameScope interface, which is how XAML namescopes are communicated by WPFWPF internal processes. ただし、明示的なインターフェイス定義は、FrameworkTemplate および Style の従来の API サーフェイスの一部ではありません。これは、FrameworkTemplateStyleINameScope メソッドを直接呼び出す必要はほとんどなく、代わりに GetTemplateChild などの他の API を使用するためです。But the explicit interface definitions are not part of the conventional API surface of FrameworkTemplate and Style, because you seldom need to call the INameScope methods on FrameworkTemplate and Style directly, and instead would use other API such as GetTemplateChild.

次のクラスでは、System.Windows.NameScope ヘルパー クラスを使用し、NameScope.NameScope 添付プロパティを使用してその XAML 名前スコープの実装に接続することにより、独自の XAML 名前スコープが定義されています。The following classes define their own XAML namescope, by using the System.Windows.NameScope helper class and connecting to its XAML namescope implementation through the NameScope.NameScope attached property:

関連項目See also