Reputation: 28586
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)));
return 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
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
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...
Upvotes: 2
Views: 4651
Reputation: 5552
I'd use an adorner to draw the text on top of the line.
http://msdn.microsoft.com/en-us/library/ms746703.aspx
Upvotes: 0
Reputation: 32578
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.
Upvotes: 2