Расположение позиционера относительно размеров родителя в WPF
Я пытаюсь расположить 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 ответ
Положение Adorner относительно украшенного элемента. Если вы хотите, чтобы он был на вершине вашего объекта, значение yloc
должен быть отрицательным. Тем не менее, код, который вы имеете, также касается границ холста. Если места для прямоугольника недостаточно, он поместит его ниже. Попытка поместить TextBox немного ниже в Canvas.