2012-04-03 24 views
19

Ich versuche, eine ungewöhnliche Verwendung eines Adorner zu erreichen. Wenn Sie mit der Maus über eine RichTextBox fahren, erscheint darüber ein Adorner (siehe Abbildung unten), mit dem Sie einer ListBox im Adorner eine Liste von Strings hinzufügen können. Dies wird verwendet, um "Tags" (à la Flickr) zu der Passage hinzuzufügen, die in dem geschmückten Element enthalten ist.WPF Adorner mit Kontrollen innerhalb

adorner diagram

Erstens: Ist das überhaupt möglich?

Die meisten Beispiele von Adorners zeigen, wie die OnRender-Methode von Adorner überschrieben wird, um triviale Dinge wie das Zeichnen von Formen auszuführen. Ich konnte damit eine Reihe von Rechtecken erzeugen, die den grauen Rand des Adorner erzeugt, der auch automatisch die Größe ändert, wenn die Höhe von RichTextBox aufgrund zusätzlicher Linien zunimmt, die Text hinzugefügt wird, während der Adorner angezeigt wird.

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 

} 

Das Hinzufügen von Steuerelementen ist jedoch etwas problematischer. Im Allgemeinen erfordert WPFs Adorner das Hinzufügen von untergeordneten Steuerelementen im Code anstelle von XAML. Mit der in beschriebenen Technik habe ich gelernt, wie man einem Adorner innerhalb des Adorner-Initialisierers untergeordnete Steuerelemente (wie eine TextBox) hinzufügt.

Das Problem ist jedoch die Platzierung dieser Steuerelemente innerhalb der Adorner.

Wenn ich ein Gitter mit einem grauen Hintergrund erstellen und es an der Unterseite des Adorner positionieren könnte, sollte ich gut gehen. Ich würde (hoffentlich) davon ausgehen, dass Dinge wie die automatische Größenanpassung der Adorner basierend auf der Größe des Gitters, wenn Tags hinzugefügt werden, automatisch auftreten würden.

Kurz, vorausgesetzt, dies möglich ist, kann jemand eine Möglichkeit zu schaffen, diesen unteren Tagging Steuerbereich innerhalb die Adorner und Positionierung relativ zu dem Boden des Adorner (empfehlen, die möglicherweise als RichTextBox, um die Größe können Inhalt ändert sich)?

Antwort

38

Huzah! Mit Hilfe von Ghenadie Tanasiev habe ich eine Antwort.

Im Gegensatz zu den meisten Steuerelementen in WPF verfügen Adorner nicht über eine Out-of-the-Box-Möglichkeit zum Zuweisen untergeordneter Elemente (z. B. die Steuerelemente, die ich hinzufügen wollte). Ohne etwas zu den Adornern hinzuzufügen, können Sie nur ihre OnRender Methode überschreiben und Sachen innerhalb der DrawingContext zeichnen, die hineingereicht wird. Um ehrlich zu sein, das passt wahrscheinlich zu 99% der Anwendungsfälle für Adorner (Dinge wie das Erstellen von Ziehpunkten um ein Objekt herum), aber ich musste meinem Adorner einige echte Steuerelemente hinzufügen.

Der Trick, dies zu tun, ist eine VisualCollection erstellen und setzen Sie Ihren Adorner als seinen Besitzer, indem Sie es in den Konstruktor für die Sammlung übergeben.

Dies ist alles ziemlich umfassend in this blog article beschrieben. Leider wiederholten meine wiederholten Google-Suchen diesen Artikel nicht, bis ich wusste, dass ich dank Ghenadies Anleitung nach VisualCollection suchen musste.

Dies ist nicht in dem Artikel erwähnt, aber beachten Sie, dass es möglich ist, die VisualCollection-Technik zusammen mit dem Zeichnen in der OnRender-Methode des Adorners zu kombinieren. Ich verwende OnRender, um die in meinem obigen Diagramm beschriebenen Seiten- und Obergrenzen zu erreichen und VisualCollection zum Platzieren und Erstellen der Steuerelemente zu verwenden.

Edit: hier ist der Quellcode aus dem Blog-Eintrag erwähnt, da es nicht mehr verfügbar ist:

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

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

+0

Nicht naheliegend, gut entdeckt – Basic

3

Sie müssen Ihre Hände nicht so schmutzig machen, werfen Sie einen Blick auf this CodeProject article, dass ich in der Vergangenheit verwendet habe.

Es Sie definieren Adornern in XAML können, tun Bindungen usw.

+0

ich eigentlich getüftelt hatte für ein paar Stunden mit diesem Ansatz um versuchen, einen Weg zu kommen um die oben beschriebene Positionierung zu implementieren, aber ich denke nicht, dass der Code im CodeProject-Beispiel ausreichend robust ist, um das zu berücksichtigen, was ich tun möchte. Zum Beispiel, es ist ein Clipping eines Adorners, den ich an den Grenzen des geschmückten Elements erzeuge (sehr merkwürdig, da der Z-Index von Adornern immer oben sein soll). Ich habe versucht, Dinge wie das Binden der Höhe eines Elements unter dem AdornedControl.AdornerContent an die ActualHeight des Adorned-Elements zu testen, und es ist (stillschweigend) fehlgeschlagen. –

+0

Ja, es tut den Ausschnitt, ich fand, dass es an das Layout nicht an das geschmückte Element klammert. Was Ihr Problem betrifft, werde ich noch einmal schauen –

+0

Je vous remercie, Baboon. :) Ich werde selbst heute Nachmittag weitermachen und alles berichten, was ich lerne. –