2010-11-15 80 views
2

我有一个自定义的WPF控件MyLine,它应该代表中间没有文字。在形状中添加文本

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

      return geometryGroup; 

     } 
    } 
} 

我应该如何在这里添加一个TextBlock(或标签)?

我试着在里面添加一个FormattedText,但是这是NOK,因为它用线条画笔画了文字,并且不可能读取某些东西。

编辑

添加视觉儿童

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

我没有看到任何标签...“/

EDIT2

添加装饰器

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

现在,ap父母代码永远不会进入OnRender装饰器方法...

+0

我希望你的画布的backgroundColor是不是白... – VRage 2017-10-12 11:05:15

回答

2

如果您不希望文本显示在同一个画笔中作为行,那么您可能不希望使用Shape作为基类,如从DefiningGeometry返回的Geometry呈现在一个画笔中。如果您确实想使用Shape作为基类,则可能希望将文本添加为​​可视子元素,而不是将其添加到现有的Geometry

如果你不打算使用了很多这些,并且能买得起一个稍微重量级的容器,我建议干脆创建一个包含此Shape创建,一个文本UserControl基于控制像TextBox这样的元素在Canvas(用于绝对定位)。再次说明,如果您拥有数百或数千个解决方案,这不会是一个很好的解决方案,但如果您只有几十个,那么这可能是最简单和最快捷的解决方案。

+0

我已经有一个工作逻辑与这种形状,主要是,线移动等等。我会搜索一些有关儿童视觉...只是需要一些在所有行附近显示(或不显示)文本信息。 – serhio 2010-11-15 23:50:03

+0

你可以看看张贴的编辑? – serhio 2010-11-16 00:17:01

+0

如果您要使用可视化子方法,您需要的不仅仅是AddVisualChild - 奇怪的是,该方法实际上并没有添加子对象,它只是设置父/子关系。您还需要重写'VisualChildCount','GetVisualChild'以实际将该项目作为子项目,并使用'ArrangeOverride'来定位元素。 – 2010-11-16 13:26:55

0

我会使用一个装饰者来绘制文本的顶部。

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

+0

也添加了这个变体,但不能像我写的那样工作,请参阅我的编辑2 – serhio 2010-11-16 02:58:14

+0

你不能在构造函数中这样做。 OnLoaded/OnApply模板是你应该在哪里AdornerLayer.GetAdornerLayer(this) – NVM 2010-11-16 04:46:12

+0

修正了这一点,现在,显然代码从来没有进入OnRender装饰器方法...(参见编辑) – serhio 2010-11-16 10:03:05