WPF装饰器里面的控制 [英] WPF adorner with controls inside

查看:421
本文介绍了WPF装饰器里面的控制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想实现一个不同寻常的使用装饰器的。当您将鼠标悬停一个RichTextBox,装饰器(见下图),就会出现上面,让您的字符串列表添加到包含在装饰器列表框。这是用于添加标签(点菜的Flickr)包含在佐餐元素的流逝

I am trying to achieve an unusual use of an Adorner. When you mouse-over a RichTextBox, an Adorner (see diagram below) will appear above it, allowing you to add a list of strings to a ListBox contained in the Adorner. This is used for adding "tags" (à la Flickr) to the passage contained in the adorned element.




首先:这是甚至可能吗?

装饰器的大多数例子说明如何覆盖装饰器的方法的OnRender做像绘制形状琐碎的事情。我可以用它来呈现一组矩形创建装饰器,这也将自动调整,如果在显示装饰器被添加的,由于其他行文本的RichTextBox的高度增加的灰色边框。

Most examples of Adorners show how to override the Adorner's OnRender method to do trivial things like draw shapes. I was able to use this to render a set of rectangles that creates the gray border of the Adorner, which also resizes automatically if the height of RichTextBox increases due to additional lines text being added while the Adorner is displayed.

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装饰器 - 可能得出的StackPanel ,我有吗?学会了如何子控件(如文本框)添加到一个装饰器没有装饰器的初始化中的任何问题。

However, adding controls is slightly more problematic. Generally speaking, WPF's adorner requires adding child controls in code rather than XAML. Using the technique described in DrawingContext adorner - possible to draw stackpanel?, I have learned how to add child controls (like a TextBox) to an Adorner without any problem within the Adorner's initializer.

这个问题,但是,距离这些控件的位置装饰器。

The issue, however, is the placement of those controls within the Adorner.

如果我可以创建一个灰色的背景,并将其位置装饰器底部的网格,我应该是好去。我假设(希望)之类的东西的基础上的标签被添加会然后自动发生的网格大小变化的装饰器的自动调整大小。

If I could create a grid with a gray background and position it at the bottom of the Adorner, I should be good to go. I would assume (hope) that things like automatic resizing of the Adorner based on the changing size of that Grid as tags are added would then happen automatically.

在总之,假设这是可能的,任何人都可以建议创建这个较低的标记控制区的一种方式的的装饰器和定位它相对于装饰器的底部(这有可能要调整为RichTextBox的内容调整大小)?

In short, assuming this is possible, can anyone recommend a way of creating this lower tagging control area within the Adorner and positioning it relative to the bottom of Adorner (which may possibly have to resize as the RichTextBox content resizes)?

推荐答案

Huzah!随着 Ghenadie Tanasiev 的帮助下,我有一个答案。

Huzah! With the help of Ghenadie Tanasiev, I've got an answer.

不像大多数WPF控件,装饰器没有分配子元素(比如我想添加控件)的任何超出现成的方式。无需添加任何装饰器,你只能覆盖其的OnRender 法和内画的东西是被传递到它的DrawingContext 。说实话,这可能是适合的使用案例99%的装饰器(比如创建拖东西,处理围绕对象),但我需要一些的正确的控件添加到我的装饰器。

Unlike most controls in WPF, adorners don't have any out-of-the-box way of assigning child elements (such as the controls I wanted to add). Without adding anything to adorners, you can only override their OnRender method and draw stuff within the DrawingContext that gets passed into it. To be honest, this fits probably 99% of use cases for adorners (stuff like creating drag handles around an object), but I needed to add some proper controls to my Adorner.

诀窍这样做是创建一个 VisualCollection ,并通过将其插入构造函数集合设置你的装饰器作为其所有者。

The trick to doing this is to create a VisualCollection and set your adorner as its owner by passing it into the constructor for the collection.

这在所有描述非常全面的这篇博客文章。不幸的是,我多次谷歌搜索并没有把这个文章,直到我知道搜索 VisualCollection ,感谢Ghenadie的指导。

This is all described pretty comprehensively in this blog article. Unfortunately, my repeated Google searches weren't turning this article up until I knew to search for VisualCollection, thanks to Ghenadie's guidance.

这是不是在文章中提到,但要注意,它可以将VisualCollection技术与装饰器的方法的OnRender绘制融会贯通。我使用的OnRender实现我上图中使用VisualCollection放置和创建控件中​​所描述的侧面和顶部边框

This isn't mentioned in the article, but note that it is possible to combine the VisualCollection technique along with drawing in the OnRender method of the adorner. I'm using OnRender to achieve the side and top borders described in my diagram above and using VisualCollection to place and create the controls.

编辑:这里是自提博客文章的源代码,因为它不再可用:

here is the source code from the mentioned blog post since it is no longer available:

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

这篇关于WPF装饰器里面的控制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆