I'd like to position a Shape's text outside of the shape itself. Can this be accomplished?
Initially I thought I might have to have a separate Label shape associated with every shape, to achieve this. I also need to apply alignment, e.g. left, center, right, so perhaps a separate Label shape would be better, then group it with its shape (as they are inseparable).
21 Answers, 1 is accepted
To achieve this you can create a custom shape, add a second text element and set its position offset:
class MyDiagramShape : RadDiagramShape{ LightVisualElement label = new LightVisualElement(); protected override void CreateChildElements() { base.CreateChildElements(); label.Text = "Test Label"; label.PositionOffset = new SizeF(-100, 0); this.DiagramShapeElement.Children.Add(label); }}I hope this will be useful. Let me know if you have additional questions.
Regards,
Dimitar
Progress Telerik
Sounds like a great idea. I will experiment with this and see if it's a good solution for me.
Would the shape bounds then encompass the label as well?
The text will be outside of the shape bounds but will be moved with the shape. I have attached a small video that shows the result.
Should you have any other questions do not hesitate to ask.
Regards,
Dimitar
Progress Telerik
What I meant is whether the shape's bounding box are considered to encompass both shape and label.
Anyway I have tried this and it looks like a possibility. It seems there is text alignment, which I need.
Further, will I able to do the following:
1. Allow in-place editing of this additional text
2. Set the bounds for the text (currently I'm seeing long text cut off). Do I use the TextBlock property?
3. Display an outline to show where the bounds of the text are
Thanks
You can use the following approach to achieve the desired layout:
class MyDiagramShape : RadDiagramShape{ RadTextBox label = new RadTextBox(); RadHostItem hostItem; protected override void CreateChildElements() { base.CreateChildElements(); hostItem = new RadHostItem(label); hostItem.StretchVertically = false; hostItem.ShouldHandleMouseInput = true; hostItem.NotifyParentOnMouseInput = false; hostItem.Text = "Test Label"; this.Children.Add(hostItem); } protected override SizeF ArrangeOverride(SizeF finalSize) { var result = base.ArrangeOverride(finalSize); var recatangle = new RectangleF(finalSize.Width / 2, 0, (finalSize.Width / 2), finalSize.Height); var rectangle2 = new RectangleF(0, 0, finalSize.Width / 2, 25); this.hostItem.Arrange(rectangle2); this.DiagramShapeElement.Arrange(recatangle); return result; }}Should you have any other questions do not hesitate to ask.
Regards,
Dimitar
Progress Telerik
Thanks for the extra option. I've tried it, but at the moment I'm going with the other method. Having the TextBox always active and with a border (although I'm sure I could customize that) wasn't quite what I wanted. I need behaviour similar to the standard shape's text editing.
You've also answered another question I was going to ask, which is how to have compound shapes. Now I know the technique for doing that. For instance I need to display radio buttons, as a single group (they don't have to be functional, just visual). Unless there's another way, I'll just add circle objects and offset them from each other.
The approach from my previous post shows how you can add the text box within the bounds of the shape as well. And this will work with a label element as well.
This approach is suitable for adding and arranging any controls or elements. If you want you can add another LightVisualElement that has its own shape. For example:
class MyDiagramShape : RadDiagramShape{ LightVisualButtonElement secondShape = new LightVisualButtonElement(); protected override void CreateChildElements() { base.CreateChildElements(); secondShape.ShouldHandleMouseInput = true; secondShape.NotifyParentOnMouseInput = false; secondShape.Text = "Test Label"; secondShape.DrawFill = true; secondShape.BackColor = System.Drawing.Color.Red; StarShape starShape = new StarShape(); starShape.Arms = 12; starShape.InnerRadiusRatio = .5f; secondShape.Shape = starShape; this.Children.Add(secondShape); } protected override SizeF ArrangeOverride(SizeF finalSize) { var result = base.ArrangeOverride(finalSize); var recatangle = new RectangleF(finalSize.Width / 2, 0, (finalSize.Width / 2), finalSize.Height); var rectangle2 = new RectangleF(0, 0, finalSize.Width / 2, finalSize.Height); this.secondShape.Arrange(rectangle2); this.DiagramShapeElement.Arrange(recatangle); return result; } }Please let me know if there is something else I can help you with.
Regards,
Dimitar
Progress Telerik
It seems there's more than one way to do this
What I'm trying to achieve overall, is a kind of UI form designer.
I will have checkbox, radio button, combobox, text field, table, etc.
I thought the way was to have one ElementShape-derived class for each of my element types, and override CreatePath. This is working reasonably well. Is this a reasonable approach? It seems to be recommended in the Custom Shapes docs.
If you want to add controls and the user should be able to interact with them, use my approach and add elements. If you want to have only shapes that can be drawn by using a path, use the element shape. However please note that each element can have one shape only. Both approaches are valid and you should choose the one more suitable for your case.
Should you have any other questions do not hesitate to ask.
Regards,
Dimitar
Progress Telerik
So I've put together the following based on various suggestions. This is pretty much the same result as I had with the CreatePath technique, but now I actually have a filled triangle in my sample 'dropdown' shape. I also have an offset Label.
A few things though:
1. I can't drag the shape by the text
2. I'm not sure how to get a border around my rectangle; I set 'DrawBorder' to true and got a rounded rectangle border
Otherwise, this seems ok. Please comment on the code below.
using System.Drawing;using System.Drawing.Drawing2D;using Telerik.WinControls;using Telerik.WinControls.UI;namespace TestDiagram{ class DropdownShape : RadDiagramShape { LightVisualElement rectangle = new LightVisualElement(); LightVisualElement triangle = new LightVisualElement(); LightVisualElement label = new LightVisualElement(); protected override void CreateChildElements() { base.CreateChildElements(); this.Size = new Size(150, 15);// this.DrawBorder = true; label.Text = "Test Label"; label.PositionOffset = new Size(-120, 0); rectangle.ShouldHandleMouseInput = true; rectangle.NotifyParentOnMouseInput = false; rectangle.DrawFill = true; rectangle.BackColor = Color.LightGray; triangle.DrawFill = true; triangle.BackColor = Color.Black; var rectangleShape = new CustomShape(); rectangleShape.CreateRectangleShape(0, 0, 150, 15); var triangleShape = new TriangleShape(); rectangle.Shape = rectangleShape; triangle.Shape = triangleShape; this.Children.Add(rectangle); this.Children.Add(triangle); this.Children.Add(label); } protected override SizeF ArrangeOverride(SizeF finalSize) { var result = base.ArrangeOverride(finalSize); var rectTriangle = new RectangleF(finalSize.Width - 10, finalSize.Height / 2 -3 , 15, 15); var rectRectangle = new RectangleF(0, 0, finalSize.Width, finalSize.Height); var rectMain = new RectangleF(0, 0, finalSize.Width, finalSize.Height); this.rectangle.Arrange(rectRectangle); this.triangle.Arrange(rectTriangle); this.DiagramShapeElement.Arrange(rectMain); return result; } } class TriangleShape : ElementShape { public override GraphicsPath CreatePath(Rectangle bounds) { var path = new GraphicsPath(); Point[] points = { new Point( bounds.X, bounds.Y ), new Point( bounds.X + 6, bounds.Y), new Point( bounds.X + 3, bounds.Y + 6) }; path.AddPolygon(points); return path; } }}
And also..
using Telerik.Windows.Diagrams.Core;namespace TestDiagram{ public partial class RadForm1 : Telerik.WinControls.UI.RadForm { public RadForm1() { InitializeComponent(); var dropdownShape = new DropdownShape() { Position = new Point(100, 100) }; radDiagram1.AddShape(dropdownShape); } }}We can continue to discuss this in the other thread and I will close this one for now.
Regards,
Dimitar
Progress Telerik
Hi Renier,
It would be better to ask your questions in the WPF forum where you can receive an answer from the WPF community: Diagram in UI for WPF - Telerik Forums.
Thank you for your understanding.
Regards,
Dimitar
Progress Telerik
Hello Greg,
LightVisualElement is in Telerik.WinControls.UI namespace. In general, you should always have Telerik.WinControls.UI, Telerik.WinControls and TelerikCommon assemblies in your project.
I hope this helps. Please, let me know if you need further assistance.
Regards,
Nadya
Progress Telerik
Our thoughts here at Progress are with those affected by the outbreak.

