6

装飾された要素の親の寸法に応じて Adorner を配置しようとしています。たとえば、テキストボックスがあります。このテキストボックスを飾りたいので、次のようになります。

装飾者をどのように配置する必要があるか http://img707.imageshack.us/img707/9840/fig1.png

テキストボックスはキャンバスオブジェクトに配置され、十分なスペースが利用できる場合は、テキストボックスの下端に沿って装飾 (半透明の丸みを帯びた正方形) を配置します。ユーザーがテキストボックスをクリックすると、装飾が開始されます。

現在、キャンバスとそのコンテンツ (テキスト ボックス) は 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;
        }
    }
}
4

1 に答える 1

1

Adorner の位置は、装飾された要素に対して相対的です。オブジェクトの上部に配置したい場合は、 の値をyloc負にする必要があります。ただし、コードは Canvas の境界も考慮しています。上の四角形を配置するのに十分な場所がない場合は、下に配置します。テキストボックスをキャンバスの少し下に配置しようとしています。

于 2010-08-17T09:07:19.143 に答える