2010-01-05 7 views
5

장식 된 요소의 부모 치수에 따라 Adorner를 배치하려고합니다. 예를 들어, 텍스트 상자가 있습니다. 나는 이런 식으로 뭔가 보이는 있도록이 텍스트 상자를 장식 할 : 텍스트 상자가 캔버스 객체에 배치됩니다WPF의 상위 차원에 상대적인 위치 지정 adorner

how the adorner needs to be placed http://img707.imageshack.us/img707/9840/fig1.png

을 충분한 공간을 사용할 수있는 경우 다음 줄의 adorner (반 투명 둥근 사각형)와 배치 텍스트 상자의 아래쪽 가장자리 사용자가 텍스트 상자를 클릭하면 adorner가 시작됩니다.

현재 캔버스와 그 내용 (텍스트 상자)은 WinForms 형식으로 호스팅되어 있으므로 WPF는 ElementHost 컨트롤로 처리됩니다.

그러나 코드를 실행할 때 텍스트 상자를 처음 클릭 할 때 텍스트 상자의 위쪽 가장자리에 정렬 된 adorner가 표시됩니다 (아래 그림 참조). 그 후 그것은 위의 그림과 같이 올바르게 위치를 잡습니다. 왜 이것이 그럴지 알 수 있습니까?

how adorner is positions http://img14.imageshack.us/img14/4766/fig2v.png

나는 아래이에 대한 코드를 붙여 넣은 :

TextBoxAdorner.cs - 이것을 adorner 로직

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; 
     } 
    } 
} 

답변

0

Adorner의 위치가 장식 요소를 기준으로합니다. 개체의 맨 위로 가려면 yloc 값이 음수 여야합니다. 그러나 코드는 Canvas의 경계도 고려합니다. 위 사각형에 대해 충분한 공간이 없다면 아래에 놓습니다. 캔버스에서 TextBox를 조금 아래쪽으로 배치하려고 시도합니다.