コントロールが内部にある WPF アドナー 質問する

コントロールが内部にある WPF アドナー 質問する

私は Adorner の珍しい使い方を試みています。RichTextBox の上にマウスを移動すると、その上に Adorner (下の図を参照) が表示され、Adorner に含まれる ListBox に文字列のリストを追加できます。これは、装飾された要素に含まれる文章に「タグ」(Flickr 風) を追加するために使用されます。

装飾図

まず: そんなことが可能なのか?

Adorner のほとんどの例では、図形の描画などの些細な処理を実行するために Adorner の OnRender メソッドをオーバーライドする方法が示されています。これを使用して、Adorner の灰色の境界線を作成する一連の四角形をレンダリングできました。また、Adorner が表示されている間に追加の行テキストが追加されて RichTextBox の高さが増加すると、この境界線のサイズも自動的に変更されます。

protected override void OnRender(DrawingContext drawingContext)
{
    SolidColorBrush grayBrush = new SolidColorBrush();
    grayBrush.Color = Color.FromRgb(153, 153, 153);

    // left
    drawingContext.DrawRectangle(grayBrush, null, new System.Windows.Rect(1, 1, 5, ActualHeight));
    // right
    drawingContext.DrawRectangle(grayBrush, null, new System.Windows.Rect(ActualWidth - 6, 1, 5, ActualHeight));
    //bottom
    drawingContext.DrawRectangle(grayBrush, null, new System.Windows.Rect(1, ActualHeight, ActualWidth - 2, 5));

    // for reasons unimportant to this example the top gray bar is rendered as part of the RichTextBox

}

しかし、コントロールの追加は少し問題があります。一般的に、WPFのアドナーでは、XAMLではなくコードで子コントロールを追加する必要があります。DrawingContext 装飾 - スタックパネルを描画できますか?、Adorner の初期化子内で問題なく子コントロール (TextBox など) を Adorner に追加する方法を学びました。

しかし、問題は、Adorner 内でのこれらのコントロールの配置です。

灰色の背景のグリッドを作成し、それを Adorner の下部に配置できれば、準備は完了です。タグが追加されたときにグリッドのサイズが変わることに基づいて Adorner のサイズが自動的に変更されるなどの処理が自動的に行われると想定 (期待) します。

つまり、これが可能であると仮定すると誰かこの下のタグ付けコントロールエリアを作成する方法をお勧めできますか?内でAdorner と、Adorner の下部を基準にして配置しますか (RichTextBox コンテンツのサイズが変更されると、サイズも変更する必要がある可能性があります)?

ベストアンサー1

やった!ゲナディ・タナシエフ、答えは出ました。

WPFのほとんどのコントロールとは異なり、アドーナには子要素を割り当てるためのすぐに使える方法がありません(私が追加したいコントロールなど)。アドーナに何も追加しないと、そのOnRenderメソッドをオーバーライドして、渡された要素内に描画することしかできませんDrawingContext。正直に言うと、これはおそらくアドーナのユースケースの99%に適合します(オブジェクトの周囲にドラッグハンドルを作成するなど)が、私はいくつかの追加が必要でした。ちゃんとした私の Adorner を制御します。

これを実現するコツは、VisualCollectionコレクションのコンストラクターに渡して、装飾品をその所有者として設定します。

これはすべて、かなり包括的に説明されていますこのブログ記事VisualCollection残念ながら、 Ghenadie の指導のおかげで、を検索すればよいことがわかるまで、Google で何度も検索してもこの記事は見つかりませんでした。

この記事には記載されていませんが、VisualCollection テクニックと、装飾要素の OnRender メソッドでの描画を組み合わせることも可能です。私は、上の図で説明したサイドとトップの境界線を実現するために OnRender を使用し、コントロールを配置して作成するために VisualCollection を使用しています。

編集:前述のブログ投稿のソースコードは利用できなくなっているので、ここに記載します。

public class AdornerContentPresenter : Adorner
{
  private VisualCollection _Visuals;
  private ContentPresenter _ContentPresenter;

  public AdornerContentPresenter(UIElement adornedElement)
    : base(adornedElement)
  {
    _Visuals = new VisualCollection(this);
    _ContentPresenter = new ContentPresenter();
    _Visuals.Add(_ContentPresenter);
  }

  public AdornerContentPresenter(UIElement adornedElement, Visual content)
    : this(adornedElement)
  { Content = content; }

  protected override Size MeasureOverride(Size constraint)
  {
    _ContentPresenter.Measure(constraint);
    return _ContentPresenter.DesiredSize;
  }

  protected override Size ArrangeOverride(Size finalSize)
  {
    _ContentPresenter.Arrange(new Rect(0, 0,
         finalSize.Width, finalSize.Height));
    return _ContentPresenter.RenderSize;
  }

  protected override Visual GetVisualChild(int index)
  { return _Visuals[index]; }

  protected override int VisualChildrenCount
  { get { return _Visuals.Count; } }

  public object Content
  {
    get { return _ContentPresenter.Content; }
    set { _ContentPresenter.Content = value; }
  }
}

おすすめ記事