2012-04-03 18 views
19

Estoy tratando de lograr un uso inusual de un Adorner. Cuando pase el mouse sobre un cuadro de texto enriquecido, aparecerá un adorno (ver el diagrama a continuación) encima de él, que le permitirá agregar una lista de cadenas a un cuadro de lista contenido en Adorner. Esto se usa para agregar "etiquetas" (à la Flickr) al pasaje contenido en el elemento adornado.Decodificador WPF con controles dentro

adorner diagram

En primer lugar: ¿es esto posible?

La mayoría de los ejemplos de Adorners muestran cómo anular el método OnRender de Adorner para hacer cosas triviales como dibujar formas. Pude usar esto para representar un conjunto de rectángulos que crea el borde gris del Adorner, que también cambia de tamaño automáticamente si la altura de RichTextBox aumenta debido a las líneas adicionales que se agregan texto mientras se muestra Adorner.

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 

} 

Sin embargo, agregar controles es un poco más problemático. En general, el adorno de WPF requiere agregar controles secundarios en código en lugar de XAML. Usando la técnica descrita en DrawingContext adorner - possible to draw stackpanel?, aprendí cómo agregar controles secundarios (como un TextBox) a Adorner sin ningún problema dentro del inicializador de Adorner.

El problema, sin embargo, es la ubicación de esos controles dentro de Adorner.

Si pudiera crear una cuadrícula con un fondo gris y colocarla en la parte inferior de Adorner, estaría bien. Asumiría (espero) que cosas como el cambio de tamaño automático del Adorner basado en el tamaño cambiante de ese Grid a medida que se agregan las etiquetas, pasarían automáticamente.

En resumen, suponiendo que esto es posible, cualquier persona puede recomendar una manera de crear esta zona de control de marcado inferior dentro la Adorner y posicionándola con respecto a la parte inferior de Adorner (que puede posiblemente tener que cambiar el tamaño como el RichTextBox el contenido cambia de tamaño)?

Respuesta

38

Huzah! Con la ayuda de Ghenadie Tanasiev, tengo una respuesta.

A diferencia de la mayoría de los controles en WPF, los adornos no tienen ninguna forma inmediata de asignar elementos secundarios (como los controles que quería agregar). Sin agregar nada a adornos, solo puede anular su método OnRender y dibujar cosas dentro del DrawingContext que se pasan a él. Para ser sincero, esto encaja probablemente en el 99% de los casos de uso de adornos (cosas como la creación de controles de arrastre alrededor de un objeto), pero necesitaba agregar algunos controles apropiados a mi Adorner.

El truco para hacer esto es crear un VisualCollection y configurar su adorner como su dueño pasándolo al constructor para la colección.

Todo esto se describe bastante exhaustivamente en this blog article. Desafortunadamente, mis repetidas búsquedas en Google no estaban cambiando este artículo hasta que supe buscar VisualCollection, gracias a la guía de Ghenadie.

Esto no se menciona en el artículo, pero tenga en cuenta que es posible combinar la técnica VisualCollection junto con el dibujo en el método OnRender del adornador. Estoy usando OnRender para lograr los bordes laterales y superiores descritos en mi diagrama anterior y el uso de VisualCollection para colocar y crear los controles.

Editar: aquí está el código fuente de la entrada en el blog mencionado, ya que ya no está disponible:

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

ver también http://social.msdn.microsoft.com/Forums/en-US/ wpf/thread/81eca7d5-88d7-477a-8cdb-cfb9e8b75379/ –

+0

No es obvio. Bien descubierto. – Basic

3

No tiene que ensuciarse las manos, eche un vistazo a this CodeProject article que he usado en el pasado.

Permite definir adorners en XAML, hacer encuadernaciones, etc.

+0

me había tocado el violín realmente alrededor con este enfoque durante unas horas tratando de llegar a un camino para implementar el posicionamiento descrito anteriormente, pero no creo que el código en el ejemplo de CodeProject sea lo suficientemente robusto para acomodar lo que quiero hacer. Por ejemplo, está recortando cualquier adorno que creo en los límites del elemento adornado (muy extraño dado que siempre se supone que el índice Z de los adornos está arriba). Intenté probar cosas como vincular la altura de un elemento bajo AdornedControl.AdornerContent con el elemento ActualHeight del Adornado y falló (silenciosamente) para hacerlo. –

+0

Sí, hace el recorte, encontré que se ajusta al diseño no al elemento adornado. En cuanto a su problema voy a tener otra mirada –

+0

Je vous remercie, Baboon. :) Voy a seguir haciéndolo esta tarde y reportaré todo lo que aprenda. –

Cuestiones relacionadas