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
精彩评论