Расположение позиционера относительно размеров родителя в WPF - PullRequest
6 голосов
/ 05 января 2010

Я пытаюсь расположить Adorner в зависимости от размеров родителя украшенного элемента. Например, у меня есть текстовое поле. Я хочу украсить это текстовое поле, чтобы оно выглядело примерно так:

как нужно разместить украшения http://img707.imageshack.us/img707/9840/fig1.png

Текстовое поле помещается в объект Canvas и, если на нем достаточно свободного места, поместите рекламный элемент (полупрозрачный квадрат с закругленными углами) в линию с нижним краем текстового поля. Adorner инициируется, когда пользователь нажимает на текстовое поле.

В настоящее время холст и его содержимое (текстовое поле) размещаются в форме WinForms, поэтому WPF обрабатывается элементом управления ElementHost.

Но когда я запускаю свой код, при первом щелчке по текстовому полю на нем отображается выравниватель, выровненный по верхнему краю текстового поля (см. Рисунок ниже). После этого он правильно позиционирует себя (как на рисунке выше) Кто-нибудь знает, почему это может быть?

как украсил позиции http://img14.imageshack.us/img14/4766/fig2v.png

Я вставил код для этого ниже:

TextBoxAdorner.cs - это логика украшения

public class TextBoxAdorner : Adorner
{
    private TextBox _adornedElement;
    private VisualCollection _visualChildren;
    private Rectangle _shape;
    private Canvas _container;
    private Canvas _parentCanvas;

    public TextBoxAdorner(UIElement adornedElement, Canvas parentCanvas)
        : base(adornedElement)
    {
        _adornedElement = (TextBox)adornedElement;
        _parentCanvas = parentCanvas;
        _visualChildren = new VisualCollection(this);

        _container = new Canvas();

        _shape = new Rectangle();
        _shape.Width = 100;
        _shape.Height = 80;
        _shape.Fill = Brushes.Blue;
        _shape.Opacity = 0.5;

        _container.Children.Add(_shape);

        _visualChildren.Add(_container);
    }

    protected override Size ArrangeOverride(Size finalSize)
    {
        Point location = GetLocation();
        _container.Arrange(new Rect(location, finalSize));

        return finalSize;
    }

    private Point GetLocation()
    {
        if (_parentCanvas == null)
            return new Point(0, 0);

        Point translate;
        double xloc = 0, yloc = _shape.Height - _adornedElement.ActualHeight;

        if (yloc < 0) // textbox is bigger than the shape
            yloc = 0;
        else
        {
            translate = this.TranslatePoint(new Point(0, -yloc), _parentCanvas);

            // coordinate is beyond the position of the parent canvas
            if (translate.Y < 0)  // this is true the first time it's run
                yloc = 0;
            else
                yloc = -yloc;
        }

        translate = this.TranslatePoint(new Point(_shape.Width, 0), _parentCanvas);

        // textbox is in right edge of the canvas
        if (translate.X > _parentCanvas.ActualWidth) 
        {
            double pos = translate.X - _parentCanvas.ActualWidth;

            translate = this.TranslatePoint(new Point(-pos,0), _parentCanvas);

            if (translate.X < 0)
                xloc = 0;
            else
                xloc = translate.X;
        }

        return new Point(xloc, yloc);
    }

    protected override Size MeasureOverride(Size constraint)
    {
        Size myConstraint = new Size(_shape.Width, _shape.Height);
        _container.Measure(myConstraint);

        return _container.DesiredSize;
    }

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

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

1 Ответ

1 голос
/ 17 августа 2010

Положение Adorner относительно украшенного элемента. Если вы хотите, чтобы он был на вершине вашего объекта, значение yloc должно быть отрицательным. Тем не менее, код у вас также касается границ холста. Если места для прямоугольника недостаточно, он поместит его ниже. Попытка поместить TextBox немного ниже в Canvas.

...