装飾の概要

装飾は特別な種類の FrameworkElement で、ユーザーに視覚的手掛かりを提供するために使用されます。 装飾は、要素への機能ハンドル追加やコントロールに関する状態情報の提供など、さまざまな用途に使用できます。

装飾について

Adorner は、UIElement にバインドされるカスタム FrameworkElement です。 装飾は、AdornerLayer に描画されます。これは、常に装飾対象の要素またはそのコレクションの最上層に位置するレンダリング面です。 装飾のレンダリングは、装飾がバインドされる UIElement のレンダリングとは独立しています。 通常、装飾は、装飾対象の要素の左上に位置する標準の 2 次元座標の原点を使用して、バインド先の要素に対して相対的な位置に配置されます。

装飾の一般的な用途は、次のとおりです。

  • ユーザーが要素を操作 (サイズ変更、回転、位置の変更など) するための機能ハンドルを UIElement に追加する。
  • 視覚的なフィードバックによって、さまざまな状態を表示し、各種のイベントに応答する。
  • UIElement に視覚的装飾をオーバーレイする。
  • UIElement の一部または全部を視覚的にマスクするか、オーバーライドする。

Windows Presentation Foundation (WPF) からは、視覚要素を装飾するための基本的なフレームワークが提供されます。 次の表に示すのは、オブジェクトの装飾に使用する主な種類と、その用途の一覧です。 その後に、使用例をいくつか示します。

クラス 説明
Adorner 具体的な装飾の実装すべての継承元になる抽象基本クラス。
AdornerLayer 装飾される 1 つ以上の要素に対する、装飾のレンダリング層を表すクラス。
AdornerDecorator 1 つの装飾層を要素のコレクションに関連付けることを可能にするクラス。

カスタム装飾の実装

Windows Presentation Foundation (WPF) が提供する装飾フレームワークは、カスタム装飾の作成をサポートすることを主な目的としています。 抽象型 Adorner クラスから継承されるクラスを実装することにより、カスタム装飾が作成されます。

注意

Adorner の親は、装飾される要素ではなく、Adorner をレンダリングする AdornerLayer です。

次の例では、簡単な装飾を実装するクラスを示します。 この例の装飾では、UIElement の四隅が円で装飾されるだけです。

// Adorners must subclass the abstract base class Adorner.
public class SimpleCircleAdorner : Adorner
{
  // Be sure to call the base class constructor.
  public SimpleCircleAdorner(UIElement adornedElement)
    : base(adornedElement)
  {
  }

  // A common way to implement an adorner's rendering behavior is to override the OnRender
  // method, which is called by the layout system as part of a rendering pass.
  protected override void OnRender(DrawingContext drawingContext)
  {
    Rect adornedElementRect = new Rect(this.AdornedElement.DesiredSize);

    // Some arbitrary drawing implements.
    SolidColorBrush renderBrush = new SolidColorBrush(Colors.Green);
    renderBrush.Opacity = 0.2;
    Pen renderPen = new Pen(new SolidColorBrush(Colors.Navy), 1.5);
    double renderRadius = 5.0;

    // Draw a circle at each corner.
    drawingContext.DrawEllipse(renderBrush, renderPen, adornedElementRect.TopLeft, renderRadius, renderRadius);
    drawingContext.DrawEllipse(renderBrush, renderPen, adornedElementRect.TopRight, renderRadius, renderRadius);
    drawingContext.DrawEllipse(renderBrush, renderPen, adornedElementRect.BottomLeft, renderRadius, renderRadius);
    drawingContext.DrawEllipse(renderBrush, renderPen, adornedElementRect.BottomRight, renderRadius, renderRadius);
  }
}
Public Class SimpleCircleAdorner
    Inherits Adorner
    Sub New(ByVal adornedElement As UIElement)
        MyBase.New(adornedElement)
    End Sub

    Protected Overrides Sub OnRender(ByVal drawingContext As System.Windows.Media.DrawingContext)
        MyBase.OnRender(drawingContext)
        Dim adornedElementRect As New Rect(AdornedElement.DesiredSize)
        Dim renderBrush As New SolidColorBrush(Colors.Green)
        renderBrush.Opacity = 0.2
        Dim renderPen As New Pen(New SolidColorBrush(Colors.Navy), 1.5)
        Dim renderRadius As Double
        renderRadius = 5.0

        'Draw a circle at each corner.
        drawingContext.DrawEllipse(renderBrush, renderPen, adornedElementRect.TopLeft, renderRadius, renderRadius)
        drawingContext.DrawEllipse(renderBrush, renderPen, adornedElementRect.TopRight, renderRadius, renderRadius)
        drawingContext.DrawEllipse(renderBrush, renderPen, adornedElementRect.BottomLeft, renderRadius, renderRadius)
        drawingContext.DrawEllipse(renderBrush, renderPen, adornedElementRect.BottomRight, renderRadius, renderRadius)
    End Sub
End Class

次の図に示すのは、TextBox に適用された SimpleCircleAdorner です。

Screenshot that shows an adorned text box.

装飾のレンダリング動作

装飾自体にはレンダリング動作が備わっていないので、装飾のレンダリングは装飾の実装側の責任で行う必要がある点に、注意が必要です。 レンダリング動作を実装する一般的な方法は、(この例で示すように) OnRender メソッドをオーバーライドし、1 つまたは複数の DrawingContext オブジェクトを使用して、必要に応じて装飾のビジュアルをレンダリングすることです。

注意

装飾層に配置されているすべてのものは、設定した他のすべてのスタイルの上に描画されます。 つまり、装飾は常に視覚的に最上位にあり、z オーダーを使用してオーバーライドすることはできません。

イベントおよびヒット テスト

他のすべての FrameworkElement と同様に、装飾は入力イベントを受け取ります。 装飾は、それが装飾する要素よりも常に高い z オーダーを持つため、下位にある装飾対象の要素に向けられた入力イベント (Drop または MouseMove など) であっても受け取ります。 装飾は、特定の入力イベントをリッスンし、それらのイベントを再度発生させることによって、下位にある装飾対象の要素に渡すことができます。

装飾の下にある要素に対するヒット テストをパススルーするには、その装飾でヒット テストの IsHitTestVisible プロパティを false に設定します。 ヒット テストの詳細については、「ビジュアル層でのヒット テスト」を参照してください。

単一の UIElement の装飾

特定の UIElement に装飾をバインドするには、次の手順を行います。

  1. 静的メソッド GetAdornerLayer を呼び出して、装飾対象の UIElementAdornerLayer オブジェクトを取得します。 GetAdornerLayer では、指定した UIElement を起点としてビジュアル ツリーが上方に探索され、最初に見つかった装飾層が返されます。 (装飾層が見つからない場合、メソッドにより null が返されます)。

  2. Add メソッドを呼び出し、装飾を対象の UIElement にバインドします。

次の例では、SimpleCircleAdorner (上図参照) を myTextBox という名前の TextBox にバインドします。

myAdornerLayer = AdornerLayer.GetAdornerLayer(myTextBox);
myAdornerLayer.Add(new SimpleCircleAdorner(myTextBox));
myAdornerLayer = AdornerLayer.GetAdornerLayer(myTextBox)
myAdornerLayer.Add(New SimpleCircleAdorner(myTextBox))

注意

Extensible Application Markup Language (XAML) を利用して装飾を別の要素にバインドすることは現在サポートされていません。

パネルの子の装飾

Panel の子に装飾をバインドするには、次の手順を行います。

  1. static メソッド GetAdornerLayer を呼び出し、子が装飾対象となる要素の装飾層を検出します。

  2. 親要素の子を列挙し、Add メソッドを呼び出して、装飾を各子要素にバインドします。

次の例では、SimpleCircleAdorner (上図参照) を myStackPanel という名前の StackPanel の子にバインドします。

foreach (UIElement toAdorn in myStackPanel.Children)
  myAdornerLayer.Add(new SimpleCircleAdorner(toAdorn));
For Each toAdorn As UIElement In myStackPanel.Children
    myAdornerLayer.Add(New SimpleCircleAdorner(toAdorn))
Next

関連項目