WPF デザイナの機能拡張アーキテクチャ
更新 : 2007 年 11 月
Windows Presentation Foundation (WPF) Designer for Visual Studio は、UserControl 型によって実装される WPF 複合コントロールのビジュアル編集環境です。WPF デザイナは、機能拡張アーキテクチャを持つフレームワークに基づいており、独自のカスタム デザイン環境を作成するように拡張できます。
WPF デザイナ オブジェクト モデルを拡張することにより、WPF コンテンツのデザイン時の外観と動作を大幅にカスタマイズできます。たとえば、次のように WPF デザイナを拡張できます。
拡張グラフィックスで移動グリフとサイズ変更グリフをカスタマイズする。
マウスを移動すると、選択されているコントロールを傾斜させるグリフをデザイン サーフェイスに追加する。
複数のツール間でコントロールのデザイン時の外観と動作を変更する。
WPF デザイナのアーキテクチャは、WPF の表現能力を最大限にサポートします。これにより、以前は不可能だったビジュアル デザイン環境を構築できるようになりました。
WPF デザイナのオブジェクト モデル
WPF デザイナのオブジェクト モデルはモジュール形式であるため、デザイン時の機能拡張を行う際、機能に必要な要素のみを拡張できます。カスタム デザイン機能を有効にするために、多くのサポート コードを記述する必要はありません。
オブジェクト モデルは、次の表に示す 5 つの機能ユニットで構成されています。
機能ユニット |
説明 |
---|---|
編集モデル |
デザイナでのオブジェクトとのプログラミング インターフェイス。 |
機能プロバイダ |
デザイナ フレームワークでのメイン機能拡張ポイント。 |
編集コンテキスト |
デザイナの状態の中央ストア。 |
ツール |
ユーザー入力を処理するツール。 |
メタデータ ストア |
実行時ロジックとデザイナ ロジックを物理的に分けるためにコントロールのデザイン時動作を格納するストア。 |
次の図に、WPF デザイナ オブジェクト モデルを示します。
メモ : |
---|
WPF デザイナは、全面的に拡張可能なフレームワークをサポートしています。Expression Blend は、プロパティ エディタ、メタデータの読み込み、ライセンス処理だけをサポートしています。Blend は、メニュー アクションと装飾をサポートしていません。 |
編集モデル
デザイン環境は、編集モデルと呼ばれるプログラミング インターフェイスを介して実行時コントロールと対話します。編集モデルは、モデル、モデルを抽象化するパブリック ラッパー、およびモデルのユーザー インターフェイス (UI) を表すビューという、3 つの機能サブユニットで構成されます。
デザイン環境は、ModelItem 型を使用して、基本モデルと対話します。すべての変更は ModelItem ラッパーに対して行われ、これが基本モデルに影響を与えます。これによりモデルを簡略化できます。ModelItem ラッパーは、トランザクション サポート、元に戻す処理の追跡、変更通知など、複雑なデザイナ機能を処理します。
ModelService クラスは、編集モデルおよびグローバル イベント通知の開始ポイントを提供します。
ViewService クラスは、ビジュアル形式を基本モデルの項目に割り当てます。
デザイナが機能するためには、両方のサービスが必要です。DesignerView クラスは、ユーザー入力の処理とコマンドへのルーティングを行い、ユーザー入力をモデルに正確に割り当てるために両方のサービスを必要とします。
機能プロバイダ
型のデザイン時動作を拡張するには、FeatureProvider クラスまたは FeatureConnector<FeatureProviderType> クラスを使用します。FeatureConnector<FeatureProviderType> クラスは、FeatureProvider オブジェクトのリストを管理します。
FeatureProvider クラスは、最も基本的な機能拡張ポイントを提供します。機能プロバイダは、通常はデザイン環境から多くを必要としない簡易機能またはアドインで、特定のコンテキストで作成され、破棄されます。機能プロバイダは、デザイン サーフェイスに新しい UI を追加したり、基本的な動作を変更したりするのに使用されます。たとえば、機能プロバイダはグラブ ハンドルを追加したり、新しいマウス ドラッグ動作を提供したりします。
機能拡張性の最も深いレベルにアクセスするには、FeatureConnector<FeatureProviderType> クラスから派生クラスを作成します。このクラスはサービス プロバイダを公開し、そのサービス プロバイダを介して、機能コネクタの派生クラスはイベントの処理とサービスの要求および発行を行います。たとえば、機能コネクタを実装して、選択 UI またはオブジェクト固有のシリアル化を提供できます。
通常は、既存の概念を拡張するために機能を実装します。機能コネクタは、新しい概念を提供するために実装します。詳細については、「機能プロバイダと機能コネクタ」を参照してください。
編集コンテキスト
大量の状態情報が実行中のデザイナで計算されます。たとえば、デザイナの状態には、選択されているオブジェクトや、マウスの左ボタンが押されたときに発生した動作などが含まれます。デザイナの状態は、必要に応じて検出できるように、一括して格納されます。EditingContext クラスが、このデザイナ状態のリポジトリを表します。
EditingContext クラスは、状態をデータと動作の 2 つのカテゴリに分類します。データはコンテキスト項目のテーブルとして格納され、動作はサービスのテーブルとして格納されます。両方のテーブルは、型ベースのキーでインデックスが付けられ、列挙できます。
ContextItem クラスは、デザイナの 1 つの状態のみを保持します。コンテキスト項目は不変ですが、新しいコンテキスト項目が既存のコンテキスト項目に置き換わることによって変化が表現されます。
サービスはサービス プロバイダを介してアクセスされます。サービス プロバイダは、ServiceManager のインスタンスを返します。コンテキスト項目は Items プロパティを介してアクセスされます。Items プロパティは、ContextItemManager のインスタンスを返します。
コマンド、タスク、ツール
WPF デザイナ ツール アーキテクチャは、コマンド、タスク、およびツールで構成されます。
コマンドは、特定の動作を表す一意の識別子です。たとえば、"切り取り" は、現在のテキストを切り取って、クリップボードに追加するコマンドです。"切り取り" を実装するコードはアプリケーションごとに異なり、また同じアプリケーション内においても異なります。たとえば、Word 文書内のテキストの切り取りは、同じ文書の検索テキスト ボックス内のテキストの切り取りとは異なる実装になります。"切り取り" コマンドは、実装には関係なく同じです。
WPF デザイナは、ツール コマンドの概念を導入することによって、WPF コマンド システムを補強します。ツール コマンドは ICommand インターフェイスを実装します。これは、RoutedCommand クラスと似ています。
タスクは、コマンド バインディングのコレクションで、このタスクを使用してルーティング コマンドを追加できます。DesignerView クラスは、ツール コマンドと同じルーティング方法を使用するコードを含み、タスクで定義されているルーティング コマンドを検出および実行します。DesignerView クラスは、Copy などの一般的な WPF コマンドをサポートするタスクを有効にします。
ツールは、ユーザー入力を処理するクラスです。すべてのユーザー入力が、1 回以上の入力イベントとしてデザイナに入力されます。これらの入力イベントは、現在のアクティブ ツールに渡され、渡された入力イベントは入力バインディングに変換されます。入力バインディングが返されると、そのバインディング内のコマンドが実行されます。
ツールはデザイナのグローバル モードを表します。たとえば、ユーザーがデザイン サーフェイス上のコンポーネントを選択すると、現在のアクティブ ツールが選択を処理する入力バインディングとコマンドを提供するため、選択モードになります。ユーザーがコントロールのインスタンスを新しく作成すると、別のツールがアクティブになり、同じ入力バインディングにバインドされている別のコマンド セットが使用できるようになります。
メタデータ ストア
WPF デザイナ フレームワークでは、コントロールのデザイン時動作を定義するメタデータは別のアセンブリに組み込まれます。これはメタデータ ストアと呼ばれます。.NET Framework 3.5 では、メタデータ ストアは、デザイナ コードとプロファイルを参照する外部 XML ファイルと共に、分離コード属性テーブルに実装されます。異なるツールが、それぞれ異なるデザイナ実装でさまざまなメタデータ ストアを提供できます。これにより、実行時動作とデザイン時動作を分離して、デザイナとコントロールを個別に変更できます。詳細については、「メタデータ ストア」を参照してください。
デザイナ インスタンスの作成
ここでは、WPF デザイナ環境によってサンプルのデザイナの型がどのようにインスタンス化されるのかについて説明します。この例では、仮想デザイナがデザイン サーフェイス上で 1 つのボタン コントロールを選択したときの動作について説明します。
ユーザーが、カスタム デザイナ作成を要求するツール定義アクションを起動します。
デザイン環境は、機能と型の関連付けを XML ベースのリストに列挙します。
デザイン環境は、TypeDescriptor クラスを使用して、これらの型にカスタム メタデータを追加します。たとえば、GrabHandleProvider をすべての UIElement 型 (派生型も含む) と関連付けることができます。
編集ファクトリは、編集ストア、コンテキスト、および機能マネージャを作成し、編集ストアを設定します。
WPF デザイナはすべての UIElement オブジェクトを列挙します。これらのオブジェクトは編集ストアによって公開され、それぞれが InitializeFeatures メソッドを呼び出します。
Button 要素がこの階層内で宣言されているものとします。
FeatureManager はボタンの FeatureAttribute を探します。FeatureManager は GrabHandleProvider 型のボタンの FeatureAttribute を検出します。
FeatureManager は、GrabHandleProvider 型を検索し、これに関連付けられている FeatureConnectorAttribute を検出します。FeatureConnectorAttribute は SelectionConnector を指定しています。
FeatureManager は、このホストがまだ存在していないと判断します。FeatureManager は SelectionConnector を作成し、これをアクティブ機能ホストに追加します。
SelectionConnector オブジェクトは、選択の変更について、デザイナ サーフェイスの監視を始めます。SelectionConnector オブジェクトは、装飾層への参照も取得します。
ユーザーがボタンの選択を変更すると、デザイン時ツールは選択変更イベントを発行します。
SelectionConnector はこの通知を受け取り、選択されたオブジェクトに関連付けれられているすべての選択ベースの FeatureProvider インスタンスを作成します。これには GrabHandleProvider インスタンスも含まれます。
SelectionConnector は GrabHandleProvider に対して装飾リストを問い合わせ、これらを装飾層に追加します。これで、グラブ ハンドルが選択したボタンの周りに表示されます。
WPF デザイナのアセンブリ
WPF デザイナは、複数のアセンブリで構成されます。それぞれ、パブリック、プライベート、または Visual Studio 固有のいずれかのカテゴリのアセンブリです。
パブリック アセンブリは、デザイン時ロジックをコントロールに追加する際に使用できるクラスを公開します。
プライベート アセンブリと Visual Studio 固有のアセンブリは、WPF デザイナの機能セットと、Visual Studio との対話を定義します。次の表に、WPF デザイナ機能の展開方法を示します。
アセンブリ |
パブリック API |
説明 |
---|---|---|
Microsoft.VisualStudio.Xaml.dll |
× |
Visual Studio SDK 統合ロジック |
Microsoft.Windows.Design.Host.dll |
○ |
デザイナをホストするためのパブリック API (Visual Studio 固有) |
Microsoft.Windows.Design.Developer.dll |
× |
WPF デザイナの実装。パブリック API のみが属性テーブルです。 |
Microsoft.Windows.Design.Core.dll |
○ |
サービスおよびデータ バックプレーンを介して任意のデザイナに対する基本的な基盤を提供し、メタデータを処理します。これは、Expression Blend によってサポートされている唯一のアセンブリです。 |
Microsoft.Windows.Design.Extensibility.dll |
○ |
属性を介して機能拡張モデルを提供します。 |
Microsoft.Windows.Design.Interaction.dll |
○ |
ユーザー入力と表示クラスを提供します。 |
Microsoft.Windows.Design.Markup.dll |
○ |
Provides Extensible Application Markup Language (XAML) とドキュメント モデル機構を提供します。 |
メモ : |
---|
アセンブリは、名前空間の範囲を表しているのではなく、機能的な範囲を表しています。複数のアセンブリにまたがる名前空間も珍しくありません。 |
WPF デザイナと Windows フォーム デザイナのアーキテクチャ
WPF デザイナのアーキテクチャは、IComponent インターフェイスと System.ComponentModel 名前空間で識別される Windows フォーム デザイナのアーキテクチャとは大きく異なります。詳細については、「Windows フォーム デザイナのフレームワークと WPF デザイナのフレームワークの比較」を参照してください。