2012-04-03 13 views
19

Próbuję osiągnąć niezwykłe wykorzystanie Adornera. Po najechaniu kursorem myszy na RichTextBox, nad nim pojawi się Adorner (patrz diagram poniżej), umożliwiający dodanie listy ciągów do ListBoxu zawartego w Adornerze. Służy do dodawania "tagów" (à la Flickr) do fragmentu zawartego w ozdobnym elemencie.Adorator WPF z kontrolkami wewnątrz

adorner diagram

pierwsze: czy to w ogóle możliwe?

Większość przykładów Adornerów pokazuje, jak zastąpić metodę OnRender Adornera, aby robić trywialne rzeczy, takie jak kształty rysunków. Byłem w stanie użyć tego do renderowania zestawu prostokątów, które tworzą szare obramowanie Adornera, które również zmienia się automatycznie, gdy wysokość RichTextBox wzrasta z powodu dodania dodatkowego tekstu linii podczas wyświetlania Adornera.

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 

} 

Jednak dodanie kontroli jest nieco bardziej problematyczne. Ogólnie mówiąc, adorner WPF wymaga dodania kontroli podrzędnych w kodzie zamiast XAML. Korzystając z techniki opisanej w artykule DrawingContext adorner - possible to draw stackpanel?, nauczyłem się dodawać do Adornera formanty podrzędne (takie jak TextBox) bez żadnego problemu w inicjatorze Adornera.

Problem polega jednak na umieszczeniu tych elementów sterujących w Adornerze.

Gdybym mógł stworzyć siatkę z szarym tłem i ustawić ją na dole Adornera, powinienem być gotowy. Zakładam (mam nadzieję), że takie rzeczy jak automatyczna zmiana rozmiaru Adornera w oparciu o zmieniający się rozmiar tej siatki, gdy dodamy tagi, nastąpi automatycznie.

W skrócie, zakładając, że jest możliwe można każdy zalecane sposób tworzenia tego dolnego sterowania znakowania ciągu Adorner i ustawiania go względem dolnej części Adorner (która może mieć na rozmiar jak RichTextBox zawartość zmienia rozmiar)?

Odpowiedz

38

Huzah! Z pomocą Ghenadie Tanasiev, mam odpowiedź.

W przeciwieństwie do większości formantów w WPF, adoratorzy nie mają żadnego gotowego sposobu przypisywania elementów podrzędnych (takich jak kontrolki, które chciałem dodać). Bez dodawania nic do adorners, można tylko zastąpić ich metodę i narysować rzeczy w DrawingContext, które dostaje się do niego. Szczerze mówiąc, pasuje to prawdopodobnie do 99% przypadków użycia dla adorujących (rzeczy takie jak tworzenie uchwytów przeciągania wokół obiektu), ale musiałem dodać jakieś kontrole odpowiednie do mojego Adornera.

W tym celu należy utworzyć VisualCollection i ustawić swojego adoratora jako właściciela, przekazując go do konstruktora kolekcji.

Wszystko to opisano dość szczegółowo w artykule this blog article. Niestety, moje wielokrotne wyszukiwania w Google nie zmieniały tego artykułu, dopóki nie dowiedziałem się, że szukam VisualCollection, dzięki wskazówkom Ghenadie.

Nie wspomniano o tym w tym artykule, ale zauważ, że można połączyć technikę VisualCollection z rysunkiem w metodzie OnRendera adornera. Używam OnRender, aby osiągnąć boczne i górne granice opisane na powyższym diagramie i używając VisualCollection do umieszczenia i utworzenia kontrolek.

Edit: tutaj jest kod źródłowy ze wspomnianym blogu, ponieważ nie jest już dostępny:

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

zobaczyć również http://social.msdn.microsoft.com/Forums/en-US/ wpf/thread/81eca7d5-88d7-477a-8cdb-cfb9e8b75379/ –

+0

Nieoczywisty. – Basic

3

Nie musisz zabrudzić sobie rąk, spójrz na this CodeProject article, którego używałem w przeszłości.

Pozwala określić adorners w XAML, zrobić powiązań itd

+0

I rzeczywiście bawił się wokół tego podejścia na kilka godzin, próbując wymyślić sposób do implementacji opisanego powyżej pozycjonowania, ale nie sądzę, że kod w przykładzie CodeProject jest wystarczająco solidny, aby pomieścić to, co chcę zrobić. Na przykład przycina każdego adornera, który tworzę, do granic ozdobnego elementu (bardzo dziwne, biorąc pod uwagę, że indeks z adornerów zawsze powinien znajdować się na górze). Próbowałem testować takie rzeczy jak powiązanie wysokości elementu pod AdornedControl.AdornerContent z ActualHeight elementu Adorned i nie udało się tego (cicho). –

+0

Tak, to robi wycinek, stwierdziłem, że klipy do układu nie do ozdobnego elementu. Jeśli chodzi o twój problem, będę miał inny wygląd. –

+0

Je vous remercie, Baboon. :) Zamierzam zachować to samo dziś po południu i zgłosić wszystko, czego się nauczę. –

Powiązane problemy