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.