WPF のツリーTrees in WPF

多くのテクノロジでは、要素とコンポーネントはツリー構造で構成されており、開発者はツリー内のオブジェクトノードを直接操作して、アプリケーションのレンダリングや動作に影響を与えます。In many technologies, elements and components are organized in a tree structure where developers directly manipulate the object nodes in the tree to affect the rendering or behavior of an application. Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF)では、プログラム要素間の関係を定義するために、いくつかのツリー構造のメタファが使用されます。also uses several tree structure metaphors to define relationships between program elements. ほとんどの場合、WPF 開発者は、オブジェクトツリーの比喩について概念的に考えると同時に、コードでアプリケーションを作成したり、アプリケーションの一部を XAML で定義したりできますが、特定の API を呼び出すか、特定のマークアップを使用して汎用的なものではありません。などのオブジェクトツリー操作 API は、XML DOM でを使用する場合があります。For the most part WPF developers can create an application in code or define portions of the application in XAML while thinking conceptually about the object tree metaphor, but will be calling specific API or using specific markup to do so rather than some general object tree manipulation API such as you might use in XML DOM. WPF は、 LogicalTreeHelperツリーの比喩ビューとVisualTreeHelperを提供する2つのヘルパークラスを公開します。WPF exposes two helper classes that provide a tree metaphor view, LogicalTreeHelper and VisualTreeHelper. これらの同じツリーが特定の主要な WPF 機能の動作を理解するのに役立ちます。そのため、ビジュアルツリーと論理ツリーは WPF ドキュメントでも使用されます。The terms visual tree and logical tree are also used in the WPF documentation because these same trees are useful for understanding the behavior of certain key WPF features. このトピックでは、ビジュアルツリーと論理ツリーが表す内容を定義し、そのようなツリーがオブジェクトツリー全体のLogicalTreeHelper概念VisualTreeHelperにどのように関連しているかを説明します。およびは、とを紹介します。This topic defines what the visual tree and logical tree represent, discusses how such trees relate to an overall object tree concept, and introduces LogicalTreeHelper and VisualTreeHelpers.

WPF のツリーTrees in WPF

WPFWPF最も完全なツリー構造は、オブジェクトツリーです。The most complete tree structure in WPFWPF is the object tree. XAMLXAMLアプリケーションページを定義し、 XAMLXAMLを読み込むと、マークアップ内の要素の入れ子の関係に基づいてツリー構造が作成されます。If you define an application page in XAMLXAML and then load the XAMLXAML, the tree structure is created based on the nesting relationships of the elements in the markup. アプリケーションまたはアプリケーションの一部をコードで定義した場合、特定のオブジェクトのコンテンツモデルを実装するプロパティのプロパティ値の割り当て方法に基づいて、ツリー構造が作成されます。If you define an application or a portion of the application in code, then the tree structure is created based on how you assign property values for properties that implement the content model for a given object. Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF)は、完全なオブジェクトツリーが概念化され、そのパブリック API (論理ツリーとして、およびビジュアルツリー) にレポートできる方法が2つあります。In Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF), there are two ways that the complete object tree is conceptualized and can be reported to its public API: as the logical tree and as the visual tree. 論理ツリーとビジュアルツリーの違いは必ずしも重要であるとは限りませんが、特定WPFWPFのサブシステムで問題が発生し、マークアップまたはコードで行った選択に影響することがあります。The distinctions between logical tree and visual tree are not always necessarily important, but they can occasionally cause issues with certain WPFWPF subsystems and affect choices you make in markup or code.

論理ツリーまたはビジュアルツリーを直接操作しているわけではありませんが、ツリーの相互作用の概念を理解することは、WPF をテクノロジとして理解するうえで役に立ちます。Even though you do not always manipulate either the logical tree or the visual tree directly, understanding the concepts of how the trees interact is useful for understanding WPF as a technology. WPF は、いくつかの種類のツリーの比喩と考えることも重要です。これは、でのWPFWPFプロパティの継承とイベントルーティングのしくみを理解する上で重要です。Thinking of WPF as a tree metaphor of some kind is also crucial to understanding how property inheritance and event routing work in WPFWPF.

注意

オブジェクトツリーは実際の API よりも概念が多いため、概念を考えるもう1つの方法はオブジェクトグラフです。Because the object tree is more of a concept than an actual API, another way to think of the concept is as an object graph. 実際には、ツリーの比喩が分割される、実行時のオブジェクト間のリレーションシップがあります。In practice, there are relationships between objects at run time where the tree metaphor will break down. それにもかかわらず、特に XAML で定義された UI の場合、ツリーの比喩は、この一般的な概念を参照するときにほとんどの WPF ドキュメントがオブジェクトツリーという用語を使用することに関係しています。Nevertheless, particularly with XAML-defined UI, the tree metaphor is relevant enough that most WPF documentation will use the term object tree when referencing this general concept.

論理ツリーThe Logical Tree

WPFWPFは、これらの要素を返すオブジェクトのプロパティを設定することによって、UI 要素にコンテンツを追加します。In WPFWPF, you add content to UI elements by setting properties of the objects that back those elements. たとえば、 ListBoxコントロールに項目を追加するには、そのItemsプロパティを操作します。For example, you add items to a ListBox control by manipulating its Items property. これにより、 ItemCollection Itemsプロパティ値であるに項目を配置します。By doing this, you are placing items into the ItemCollection that is the Items property value. 同様に、オブジェクトDockPanelをに追加するには、 Childrenプロパティ値を操作します。Similarly, to add objects to a DockPanel, you manipulate its Children property value. ここでは、 UIElementCollectionにオブジェクトを追加します。Here, you are adding objects to the UIElementCollection. コード例については、「方法:要素を動的に追加します。For a code example, see How to: Add an Element Dynamically.

Extensible Application Markup Language (XAML)Extensible Application Markup Language (XAML) ListBoxは、またはのコントロールまたはDockPanelその他の UI 要素にリスト項目を配置するときにItems 、次の例のように、明示的または暗黙的にプロパティとChildrenプロパティも使用します。In Extensible Application Markup Language (XAML)Extensible Application Markup Language (XAML), when you place list items in a ListBox or controls or other UI elements in a DockPanel, you also use the Items and Children properties, either explicitly or implicitly, as in the following example.

<DockPanel
  Name="ParentElement"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  >
  <!--implicit: <DockPanel.Children>-->
  <ListBox DockPanel.Dock="Top">
    <!--implicit: <ListBox.Items>-->
    <ListBoxItem>
      <TextBlock>Dog</TextBlock>
    </ListBoxItem>
    <ListBoxItem>
      <TextBlock>Cat</TextBlock>
    </ListBoxItem>
    <ListBoxItem>
      <TextBlock>Fish</TextBlock>
    </ListBoxItem>
  <!--implicit: </ListBox.Items>-->
  </ListBox>
  <Button Height="20" Width="100" DockPanel.Dock="Top">Buy a Pet</Button>
  <!--implicit: </DockPanel.Children>-->
</DockPanel>

この XAML をドキュメントオブジェクトモデルの下で XML として処理していて、タグを暗黙的に (有効な場合は) 除外すると、結果の XML DOM ツリーにとその他の暗黙的な<ListBox.Items>項目の要素が含まれるようになります。If you were to process this XAML as XML under a document object model, and if you had included the tags commented out as implicit (which would have been legal), then the resulting XML DOM tree would have included elements for <ListBox.Items> and the other implicit items. ただし、XAML では、マークアップを読み取り、オブジェクトに書き込むときに、このような処理は行われませListBox.Itemsん。結果として得られるオブジェクトグラフには、が含まれません。But XAML does not process that way when you read the markup and write to objects, the resulting object graph does not literally include ListBox.Items. ただしListBox 、をListBox含むとItemCollectionいう名前Itemsのプロパティがあります。このプロパティは、XAMLの処理時に初期化されますが、空になります。ItemCollectionIt does however have a ListBox property named Items that contains a ItemCollection, and that ItemCollection is initialized but empty when the ListBox XAML is processed. 次に、のコンテンツListBoxとして存在する各子オブジェクト要素が、パーサーにItemCollectionよるへItemCollection.Addの呼び出しによってに追加されます。Then, each child object element that exists as content for the ListBox is added to the ItemCollection by parser calls to ItemCollection.Add. このように、XAML をオブジェクトツリーに処理する例では、作成されたオブジェクトツリーが基本的に論理ツリーであるという一見のように見えます。This example of processing XAML into an object tree is so far seemingly an example where the created object tree is basically the logical tree.

ただし、論理ツリーは、XAML の暗黙的な構文項目が考慮されていない場合でも、実行時にアプリケーション UI に存在するオブジェクトグラフ全体ではありません。主な理由は、ビジュアルとテンプレートです。However, the logical tree is not the entire object graph that exists for your application UI at run time, even with the XAML implicit syntax items factored out. The main reason for this is visuals and templates. たとえば、を考えてButtonみます。For example, consider the Button. 論理ツリーは、 Buttonオブジェクトとその文字列Contentも報告します。The logical tree reports the Button object and also its string Content. ただし、実行時のオブジェクトツリーには、このボタンが追加されています。But there is more to this button in the run-time object tree. 特に、特定Buttonのコントロールテンプレートが適用されたため、ボタンは画面に表示されるだけです。In particular, the button only appears on screen the way it does because a specific Button control template was applied. 実行時に論理ツリーを表示している場合でも、適用Borderされたテンプレート (ビジュアルボタンの周囲に濃い灰色のテンプレート定義など) から取得したビジュアルは、論理ツリーでは報告されません。表示されている UI を参照し、次に論理ツリーを読み取ります)。The visuals that come from an applied template (such as the template-defined Border of dark gray around the visual button) are not reported in the logical tree, even if you are looking at the logical tree during run time (such as handling an input event from the visible UI and then reading the logical tree). テンプレートビジュアルを検索するには、代わりにビジュアルツリーを調べる必要があります。To find the template visuals, you would instead need to examine the visual tree.

構文と、作成されたオブジェクトグラフ、および xaml の暗黙的な構文の対応については、「 xaml 構文の詳細」または「 xaml の概要 (WPF)」を参照してください。 XAMLXAMLFor more information about how XAMLXAML syntax maps to the created object graph, and implicit syntax in XAML, see XAML Syntax In Detail or XAML Overview (WPF).

論理ツリーの目的The Purpose of the Logical Tree

論理ツリーは、コンテンツモデルが可能な子オブジェクトを簡単に反復処理できるようにし、コンテンツモデルを拡張できるようにするためのものです。The logical tree exists so that content models can readily iterate over their possible child objects, and so that content models can be extensible. また、論理ツリーは、論理ツリー内のすべてのオブジェクトが読み込まれるときなど、特定の通知のためのフレームワークを提供します。Also, the logical tree provides a framework for certain notifications, such as when all objects in the logical tree are loaded. 基本的に、論理ツリーは、フレームワークレベルでの実行時のオブジェクトグラフの近似値です。ビジュアルは除外されますが、独自の実行時アプリケーションの構成に対する多くのクエリ操作には適しています。Basically, the logical tree is an approximation of a run time object graph at the framework level, which excludes visuals, but is adequate for many querying operations against your own run time application's composition.

さらに、静的リソース参照と動的リソース参照の両方が解決されます。そのResourcesためには、最初に要求しているオブジェクトのコレクションの論理ツリーをFrameworkElement上方向に検索し、次に論理ツリーを続行し、それぞれのチェックボックスをオンにします (または、FrameworkContentElement)ResourcesResourceDictionary含まれている別の値 (そのキーを含む可能性があります)。In addition, both static and dynamic resource references are resolved by looking upwards through the logical tree for Resources collections on the initial requesting object, and then continuing up the logical tree and checking each FrameworkElement (or FrameworkContentElement) for another Resources value that contains a ResourceDictionary, possibly containing that key. 論理ツリーは、論理ツリーとビジュアルツリーの両方が存在する場合に、リソース検索に使用されます。The logical tree is used for resource lookup when both the logical tree and the visual tree are present. リソースディクショナリと参照の詳細については、「 XAML リソース」を参照してください。For more information on resource dictionaries and lookup, see XAML Resources.

論理ツリーの構成Composition of the Logical Tree

論理ツリーは、wpf フレームワークレベルで定義されます。これは、論理ツリー操作に最も関連する wpf ベース要素がまたはFrameworkElement FrameworkContentElementのいずれかであることを意味します。The logical tree is defined at the WPF framework-level, which means that the WPF base element that is most relevant for logical tree operations is either FrameworkElement or FrameworkContentElement. ただし、実際にLogicalTreeHelper API を使用しているかどうかを確認できるので、論理ツリーにFrameworkElementはまたFrameworkContentElementはではないノードが含まれる場合があります。However, as you can see if you actually use the LogicalTreeHelper API, the logical tree sometimes contains nodes that are not either FrameworkElement or FrameworkContentElement. たとえば、論理ツリーは、文字列でTextあるTextBlockの値を報告します。For instance, the logical tree reports the Text value of a TextBlock, which is a string.

論理ツリーの上書きOverriding the Logical Tree

高度なコントロールの作成者は、一般的なオブジェクトまたはコンテンツモデルが論理ツリー内のオブジェクトを追加または削除する方法を定義するいくつかの Api をオーバーライドすることにより、論理ツリーをオーバーライドできます。Advanced control authors can override the logical tree by overriding several APIs that define how a general object or content model adds or removes objects within the logical tree. 論理ツリーを上書きする方法の例については、「論理ツリーの上書き」を参照してください。For an example of how to override the logical tree, see Override the Logical Tree.

プロパティ値の継承Property Value Inheritance

プロパティ値の継承は、ハイブリッドツリーを介して動作します。Property value inheritance operates through a hybrid tree. プロパティのInherits継承を有効にするプロパティを含む実際のメタデータは、WPF FrameworkPropertyMetadataフレームワークレベルのクラスです。The actual metadata that contains the Inherits property that enables property inheritance is the WPF framework-level FrameworkPropertyMetadata class. したがって、元の値を保持する親と、その値を継承する子オブジェクトの両方FrameworkElementFrameworkContentElementまたはである必要があり、両方とも論理ツリーの一部である必要があります。Therefore, both the parent that holds the original value and the child object that inherits that value must both be FrameworkElement or FrameworkContentElement, and they must both be part of some logical tree. ただし、プロパティの継承をサポートする既存の WPF プロパティについては、プロパティ値の継承は、論理ツリーに存在しない介在するオブジェクトを介して perpetuate できます。However, for existing WPF properties that support property inheritance, property value inheritance is able to perpetuate through an intervening object that is not in the logical tree. これは主に、テンプレート要素で、テンプレート化されたインスタンスで設定されている継承されたプロパティ値を使用する場合、またはより高いレベルのページレベルの構成で、論理ツリー内で上位に設定する場合に関連します。Mainly this is relevant for having template elements use any inherited property values set either on the instance that is templated, or at still higher levels of page-level composition and therefore higher in the logical tree. プロパティ値の継承をこのような境界を越えて一貫して機能させるには、継承プロパティを添付プロパティとして登録する必要があります。また、プロパティを使用してカスタム依存関係プロパティを定義する場合は、このパターンに従う必要があります。継承動作。In order for property value inheritance to work consistently across such a boundary, the inheriting property must be registered as an attached property, and you should follow this pattern if you intend to define a custom dependency property with property inheritance behavior. プロパティの継承に使用される正確なツリーは、実行時でも、ヘルパークラスのユーティリティメソッドで完全には期待できません。The exact tree used for property inheritance cannot be entirely anticipated by a helper class utility method, even at run time. 詳細については、「プロパティ値の継承」を参照してください。For more information, see Property Value Inheritance.

ビジュアルツリーThe Visual Tree

論理ツリーの概念に加えて、のビジュアルツリー WPFWPFの概念もあります。In addition to the concept of the logical tree, there is also the concept of the visual tree in WPFWPF. ビジュアルツリーには、 Visual基本クラスによって表されるビジュアルオブジェクトの構造が記述されています。The visual tree describes the structure of visual objects, as represented by the Visual base class. コントロールのテンプレートを作成するときは、そのコントロールに適用されるビジュアルツリーを定義または再定義します。When you write a template for a control, you are defining or redefining the visual tree that applies for that control. ビジュアルツリーは、パフォーマンスと最適化の理由により、描画を低レベルで制御する開発者にとっても重要です。The visual tree is also of interest to developers who want lower-level control over drawing for performance and optimization reasons. 従来WPFWPFのアプリケーションプログラミングの一部としてビジュアルツリーが公開されると、ルーティングイベントのイベントルートは、論理ツリーではなく、ほとんどの場合、ビジュアルツリーに沿って移動します。One exposure of the visual tree as part of conventional WPFWPF application programming is that event routes for a routed event mostly travel along the visual tree, not the logical tree. このはらみのルーティングイベントの動作は、コントロールの作成者でない限り、すぐには表示されない場合があります。This subtlety of routed event behavior might not be immediately apparent unless you are a control author. ビジュアルツリーを介してイベントをルーティングすると、ビジュアルレベルでコンポジションを実装するコントロールによって、イベントを処理したり、イベントセッターを作成したりできます。Routing events through the visual tree enables controls that implement composition at the visual level to handle events or create event setters.

ツリー、コンテンツ要素、およびコンテンツホストTrees, Content Elements, and Content Hosts

コンテンツ要素 (からContentElement派生するクラス) は、ビジュアルツリーの一部ではなく、からVisual継承されず、ビジュアル表現もありません。Content elements (classes that derive from ContentElement) are not part of the visual tree; they do not inherit from Visual and do not have a visual representation. を UI ContentElementに表示するには、を、論理ツリーの参加要素であるコンテンツホストVisualでホストする必要があります。In order to appear in a UI at all, a ContentElement must be hosted in a content host that is both a Visual and a logical tree participant. 通常、このようなオブジェクトFrameworkElementはです。Usually such an object is a FrameworkElement. コンテンツホストがコンテンツの "ブラウザー" のようなものであり、ホストが制御する画面領域内にそのコンテンツを表示する方法を選択するという概念があります。You can conceptualize that the content host is somewhat like a "browser" for the content and chooses how to display that content within the screen region that the host controls. コンテンツがホストされている場合、ビジュアルツリーに通常関連付けられている特定のツリープロセスでコンテンツを参加させることができます。When the content is hosted, the content can be made a participant in certain tree processes that are normally associated with the visual tree. 通常、host FrameworkElementクラスには、ホストされているContentElementコンテンツが true ビジュアルツリーの一部ではない場合でも、コンテンツ論理ツリーのサブノードを介して、イベントルートにホストされるを追加する実装コードが含まれます。Generally, the FrameworkElement host class includes implementation code that adds any hosted ContentElement to the event route through subnodes of the content logical tree, even though the hosted content is not part of the true visual tree. これは、 ContentElementがそれ自体以外の任意の要素にルーティングするルーティングイベントをソースに送信できるようにするために必要です。This is necessary so that a ContentElement can source a routed event that routes to any element other than itself.

ツリートラバーサルTree Traversal

クラスLogicalTreeHelperには、論理GetParentツリートラFindLogicalNodeバーサルの、、およびの各メソッドがGetChildren用意されています。The LogicalTreeHelper class provides the GetChildren, GetParent, and FindLogicalNode methods for logical tree traversal. ほとんどの場合、既存のコントロールの論理ツリーを走査する必要はありません。これらのコントロールはAdd、論理上の子要素を、インデクサーなどのコレクションアクセスをサポートする専用のコレクションプロパティとして常に公開するからです。などなど。In most cases, you should not have to traverse the logical tree of existing controls, because these controls almost always expose their logical child elements as a dedicated collection property that supports collection access such as Add, an indexer, and so on. ツリートラバーサルは、主に、、コレクションプロパティが既に定義されてItemsControlいる、またはPanel独自のコレクションを提供する予定のコントロールパターンから派生しないことを選択するコントロールの作成者によって使用されるシナリオです。プロパティのサポート。Tree traversal is mainly a scenario that is used by control authors who choose not to derive from intended control patterns such as ItemsControl or Panel where collection properties are already defined, and who intend to provide their own collection property support.

ビジュアルツリーでは、 VisualTreeHelperビジュアルツリートラバーサルのヘルパークラスもサポートされています。The visual tree also supports a helper class for visual tree traversal, VisualTreeHelper. ビジュアルツリーは、コントロール固有のプロパティによって簡単に公開されVisualTreeHelperないため、プログラミングシナリオに必要な場合は、ビジュアルツリーを走査するためにクラスを使用することをお勧めします。The visual tree is not exposed as conveniently through control-specific properties, so the VisualTreeHelper class is the recommended way to traverse the visual tree if that is necessary for your programming scenario. 詳しくは、「WPF グラフィックス レンダリングの概要」をご覧ください。For more information, see WPF Graphics Rendering Overview.

注意

適用されているテンプレートのビジュアルツリーを調べることが必要になる場合があります。Sometimes it is necessary to examine the visual tree of an applied template. この手法を使用する場合は注意が必要です。You should be careful when using this technique. テンプレートを定義するコントロールのビジュアルツリーを走査している場合でも、コントロールのコンシューマーはインスタンスのTemplateプロパティを設定することによっていつでもテンプレートを変更できます。また、エンドユーザーは、適用されるテンプレートにシステムテーマ。Even if you are traversing a visual tree for a control where you define the template, consumers of your control can always change the template by setting the Template property on instances, and even the end user can influence the applied template by changing the system theme.

"ツリー" としてのルーティングイベントのルートRoutes for Routed Events as a "Tree"

前述のように、特定のルーティングイベントのルートは、ビジュアルおよび論理ツリー表現をハイブリッドにした、ツリーの1つの事前に定義されたパスに沿って移動します。As mentioned before, the route of any given routed event travels along a single and predetermined path of a tree that is a hybrid of the visual and logical tree representations. イベントルートは、ルーティングイベントとバブルルーティングイベントのどちらであるかに応じて、ツリー内の上下方向に移動できます。The event route can travel either in the up or down directions within the tree depending on whether it is a tunneling or bubbling routed event. イベントルートの概念には、実際にルーティングするイベントを発生させずにイベントルートを "ウォーク" するために使用できるヘルパークラスが直接サポートされていません。The event route concept does not have a directly supporting helper class that could be used to "walk" the event route independently of raising an event that actually routes. ルートEventRouteを表すクラスがありますが、そのクラスのメソッドは一般に内部でのみ使用されます。There is a class that represents the route, EventRoute, but the methods of that class are generally for internal use only.

リソースディクショナリとツリーResource Dictionaries and Trees

ページで定義されResourcesているすべてのリソースディクショナリの参照は、基本的に論理ツリーになります。Resource dictionary lookup for all Resources defined in a page traverses basically the logical tree. 論理ツリーに含まれていないオブジェクトは、キー付きリソースを参照できますが、リソース参照シーケンスは、そのオブジェクトが論理ツリーに接続されているポイントから開始されます。Objects that are not in the logical tree can reference keyed resources, but the resource lookup sequence begins at the point where that object is connected to the logical tree. WPF では、論理ツリーノードだけがをResources ResourceDictionary含むプロパティを持つことができるため、ビジュアルツリーを走査してからキー付きリソースResourceDictionaryを検索する利点はありません。In WPF, only logical tree nodes can have a Resources property that contains a ResourceDictionary, therefore there is no benefit in traversing the visual tree looking for keyed resources from a ResourceDictionary.

ただし、リソースルックアップは、直接の論理ツリーの範囲を超えて拡張することもできます。However, resource lookup can also extend beyond the immediate logical tree. アプリケーションマークアップの場合、リソースルックアップは、アプリケーションレベルのリソースディクショナリに続き、次に、静的なプロパティまたはキーとして参照されるテーマサポートとシステム値に進みます。For application markup, the resource lookup can then continue onward to application-level resource dictionaries and then to theme support and system values that are referenced as static properties or keys. また、リソース参照が動的である場合は、テーマの論理ツリーの外側のシステム値を参照することもできます。Themes themselves can also reference system values outside of the theme logical tree if the resource references are dynamic. リソースディクショナリと参照ロジックの詳細については、「 XAML Resources」を参照してください。For more information on resource dictionaries and the lookup logic, see XAML Resources.

関連項目See also