Good afternoon. How can I save the geometry of the selected objects to RadDiagram in xaml file? Now I take the RadDiagramShape geometry, convert it to a string and written in the xaml file. But when I try the reverse conversion, an error is thrown
1) the RadDiagramShape declare
<telerik:RadDiagramShape x:Name="ConditionShape"
IsEditable="False"
AllowCopy="False" AllowCut="False" AllowDelete="False" AllowDrop="False" AllowPaste="True" Background="Azure"
Geometry="{telerik:CommonShape ShapeType=RectangleShape }" StrokeThickness="1" Height="100" Width="100" RenderTransformOrigin="0.5,0.5" Position="180,50"/>
2) the entry in the xaml file
Init.overview.LibraryItems.FunctionItem[end].Data = Convert.ToString(ShapeFactory.GetShapeGeometry(FlowChartShapeType.DecisionShape));
FunctionLibrary Done = new FunctionLibrary();
Done = Init.overview;
XmlSerializer xml = new XmlSerializer(typeof(FunctionLibrary));
file.Close();
using (var fStream = new FileStream(path: "./****.xml", mode: FileMode.Create, access: FileAccess.Write, share: FileShare.ReadWrite))
{
xml.Serialize(fStream, Done);
fStream.Close();
}
3) the result in a file
<Data>M56;0,5L111,5;37,5 56;74,5 0,5;37,5z</Data>
4) and the inverse transform
var converter = new System.Windows.Media.GeometryConverter();
var data = (Geometry) converter.ConvertFromString(ListCode[i].Data);
ConditionShape.Geometry = data;
this line is not recognized as geometry. how to convert in the required format?
10 Answers, 1 is accepted
I tested your code and it seems that the issue comes from the culture of the application. When you call the ToString() method of most objects they will be converted differently depending on the current culture.
I used Russian culture with your code and the saved string contains the ";". However, when convert back to geometry the culture is not respected an error is thrown. Note that this behavior comes from the native Geometry class and not the diagram geometries. To resolve this you can call to convert methods with their IFormatProvider parameter set. For example, you can use the same culture when you convert to string and vise versa. Or you can use InvariantCulture so that you do not need to take care of the specific culture.
Here is an example:
// Convert to string
var geometryString = Convert.ToString(ShapeFactory.GetShapeGeometry(FlowChartShapeType.DecisionShape), CultureInfo.InvariantCulture);
// Convert back to Geometry
var converter =
new
System.Windows.Media.GeometryConverter();
var data = (Geometry)converter.ConvertFromInvariantString(geometryString);
I hope this helps.
Regards,
Martin
Telerik by Progress
The RadDiagram control exposes few collections which you can use to access its shapes and connections.
- Items collection: It contains all elements in the diagram. This means the shapes and connections visuals in a scenario with directly adding diagram items into the control. And the view models in an MVVM scenario.
- Shapes collection: It contains the RadDiagramShape and RadDiagramContainerShape objects.
- Connections collection: It contains the RadDiagramConnection objects.
var shapes = diagram.Shapes.OfType<RadDiagramShape>();
foreach
(RadDiagramShape s
in
shapes)
{
Geometry geometry = s.Geometry;
}
Regards,
Martin
Telerik by Progress
Thanks Martin, this helped me. You're a really cool man. But could you again tell me: as well as geometry of the elements to retain their relative positions? In the attachment there are some screenshots and two nested file with the geometries. For example, if you create geometry in the Microsoft Exprassion and export it to Xaml, then in my program the saved location, but if you extract the geometry of all elements from RadDiagramShape, that their location is lost. I'm sorry if my question was not too clear. Now I use this code: var shapes = diagram.Items.OfType<RadDiagramShape>();
foreach (RadDiagramShape s in shapes)
{
if (s.Geometry != null)
{ GeometryText.Text += Convert.ToString((s.Geometry), CultureInfo.InvariantCulture); }
}
and then put it in the library
Init.overview.LibraryItems.FunctionItem[...].Data = GeometryText.Text;
the reference to the xaml from Microsoft expression: https://www.dropbox.com/s/i6rl3xok9zg98t1/MicrosoftExpression.xaml?dl=0
and to the my library: https://www.dropbox.com/s/u8gy7x99l0jatqc/MyLibrary.xml?dl=0
In the common case, the shape Geometry is relative to the shape. In other words the geometry doesn't not know its position in the diagram surface. In order to resolve this you can manually recalculate the data of the geometry before saving it so that it respects the shape's position. Or you can save also the Position property of the shape in the custom XML you are creating.
Regards,
Martin
Telerik by Progress
I'm sorry that I was so obsessive. But could you give me an example how can I recalculate the data of the geometry? for example, geometric shape =M3.64884090231499E-06,65.9999983891397C210.000003648841,65.9999983891397,208.000003648841,66.9999983891397,208.000003648841,66.9999983891397C208.000003648841,66.9999983891397,217.000003648841,17.9999983891397,166.000003648841,-1.61086029493163 E-06
and position =105,304344177246;151,582290649414105,304344177246;151,582290649414
My idea was to offset the geometry bounds with the position of the shape. For example, if you have the rectangle geometry with points:
0,0 (top left)
5,0 (top right)
5,5 (bottom right)
5,0 (bottom left)
And if the shape is at position (120,300), you can offset the bounds with 120 and 300 respectively. So, the final rectangle could become something like this:
120,300 (top left)
125,300 (top right)
125,305 (bottom right)
125,300 (bottom left)
However, this approach might not be very convenient, because you will need to calculate the geometry each time you save and load it from the diagram.
The other approach includes saving also the Position property in the xml. For example:
---------------------------
<
FunctionType
>CANSend</
FunctionType
>
<
LeftEdge
>0</
LeftEdge
>
<
RightEdge
>1</
RightEdge
>
<
Data
>Some data here</
Data
>
<
Position
>120,300</
Position
>
<
Width
>100</
Width
>
<
Height
>100</
Height
>
<
Stroke
>#FF000000</
Stroke
>
-----------------------------
Regards,
Martin
Telerik by Progress
Yes, using an approach with saving both Geometry and Position in a single string is not the most convenient solution. This way you will need to write a good parsing mechanism and test it very well before use it in production.
Note that current the diagram supports only serialization which saves the entire diagram and the shapes in it using a custom XML schema. You can also use it to save a single shape. Your format of saving and loading is quite custom and the diagram doesn't work with it out of the box. In other words you will need to implement the saving/loading of the elements manually and choose the best approach to do so.
Regards,
Martin
Telerik by Progress