开发者

Adding Text inside a Shape

I have a custom WPF control MyLine that should represent or not some text in its middle.

public class MyLine : Shape
{   
    public double X1, Y1, X2, Y2;
    public bool IsTextDisplayed;
    public string Caption;

    protected override System.Windows.Media.Geometry DefiningGeometry
    {
        get
        {
            var geometryGroup = new GeometryGroup();

            if (IsTextDisplayed)
            {
                // calculate text point
                var midPoint = new Point((X1 + X2) / 2.0, (Y1 + Y2) / 2.0);
                // add a TextBlock with the Caption text in that point
                // ???
            }

            // Add line
            geometryGroup.Children.Add(new LineGeometry(
                new Point(X1, Y1), new Point(X2, Y2)));

            r开发者_如何转开发eturn geometryGroup;

        }
    }
}

How should I add the a TextBlock (or Label) here?

I tried to add a FormattedText inside, but this is NOK, because it draws the text with the line fat brush and is impossible to read something.

EDIT

Adding a visual Child

public MyLine() : base()
{
    textBlock = new System.Windows.Controls.TextBlock();
    textBlock.Visibility = System.Windows.Visibility.Hidden;
    this.AddVisualChild(textBlock);
}

protected override System.Windows.Media.Geometry DefiningGeometry
{
    get
    {
    ...

if (IsTextDisplayed)
{
    var midPoint = new Point((X1 + X2) / 2.0, (Y1 + Y2) / 2.0);
    string text = "some custom text";

    Canvas.SetLeft(textBlock, midPoint.X);
    Canvas.SetBottom(textBlock, midPoint.Y);

    textBlock.Text = text;
    this.textBlock.Visibility = System.Windows.Visibility.Visible;    
}
else 
{
    this.textBlock.Visibility = System.Windows.Visibility.Hidden;
}

I don't see any label... :"/

EDIT2

Adding Adorner

public MyLine() : base()
{
    this.Loaded += new RoutedEventHandler(MyLine_Loaded);
}

void MyLine_Loaded(object sender, RoutedEventArgs e)
{
    AdornerLayer aLayer = AdornerLayer.GetAdornerLayer(this);
    if (aLayer != null)
        aLayer.Add(new TextAdorner(this));        
}

class TextAdorner : Adorner
{
    public TextAdorner(UIElement adornedElement) : base(adornedElement) 
    { }

    protected override void OnRender(DrawingContext drawingContext)
    {
        MyLine segment = (this.AdornedElement as MyLine);            
        if (segment != null && segment.IsLabelUsed)
        {
            Rect segmentBounds = new Rect(segment.DesiredSize);

            FormattedText ft = new FormattedText(
                "654 m", Thread.CurrentThread.CurrentCulture,
                System.Windows.FlowDirection.LeftToRight,
                new Typeface("Arial"), 12, Brushes.White);

            drawingContext.DrawText(ft, segmentBounds.BottomRight);
        }
    }
}

Now, apparently the code never enters in the OnRender adorner method...


If you don't want the text displayed in the same brush as the line, you probably don't want to use a Shape as the base class, as the Geometry returned from DefiningGeometry is rendered in one brush. If you really want to use a Shape as the base class, you probably want to add the text as a visual child rather than add it to the existing Geometry.

If you aren't going to be using a lot of these, and can afford a slightly heavy-weight container, I'd suggest simply creating a UserControl based control that contains this Shape you created, and a text element like TextBox on a Canvas (for absolute positioning). Again, this is not going to be a great solution if you have hundreds or thousands of these, but if you only have tens of them, it is probably the easiest and quickest solution.


I'd use an adorner to draw the text on top of the line.

http://msdn.microsoft.com/en-us/library/ms746703.aspx

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜