This is a migrated thread and some comments may be shown as answers.

Geometry to XAML

10 Answers 614 Views
Diagram
This is a migrated thread and some comments may be shown as answers.
Svyatoslav
Top achievements
Rank 1
Svyatoslav asked on 25 Oct 2016, 09:01 AM

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

Sort by
0
Svyatoslav
Top achievements
Rank 1
answered on 27 Oct 2016, 06:30 AM
somebody help me please
0
Martin Ivanov
Telerik team
answered on 28 Oct 2016, 08:39 AM
Hi Svyatoslav,

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
Do you need help with upgrading your WPF project? Try the Telerik API Analyzer and share your thoughts!
0
Svyatoslav
Top achievements
Rank 1
answered on 28 Oct 2016, 11:33 AM
a big thank you Martin!!! it really helped! And could you even tell how can I select all elements with RadDiagram and keep their geometry?=)
0
Martin Ivanov
Telerik team
answered on 01 Nov 2016, 08:26 AM
Hello Svyatoslav,

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.
So, if you want to get the geometries of all shapes you can iterate through the required collection and get the Geometry property of each diagram item. For example:
var shapes = diagram.Shapes.OfType<RadDiagramShape>();
foreach (RadDiagramShape s in shapes)
{
    Geometry geometry = s.Geometry;
}

Regards,
Martin
Telerik by Progress
Do you need help with upgrading your WPF project? Try the Telerik API Analyzer and share your thoughts!
0
Svyatoslav
Top achievements
Rank 1
answered on 10 Nov 2016, 12:15 PM

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

0
Martin Ivanov
Telerik team
answered on 14 Nov 2016, 09:25 AM
Hello Svyatoslav,

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
Do you need help with upgrading your WPF project? Try the Telerik API Analyzer and share your thoughts!
0
Svyatoslav
Top achievements
Rank 1
answered on 15 Nov 2016, 09:20 AM

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

0
Martin Ivanov
Telerik team
answered on 17 Nov 2016, 09:39 AM
Hi Svyatoslav,

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>
-----------------------------
This xml fragment is get from the MyLibrary.xml file. I just added the Position tag.

Regards,
Martin
Telerik by Progress
Telerik UI for WPF is ready for Visual Studio 2017 RC! Learn more.
0
Svyatoslav
Top achievements
Rank 1
answered on 21 Nov 2016, 10:03 AM
I figured it out. But do you have any idea as the most just fold Geometry and Position? Now I think I need to provide both values as strings, search there separating characters such as "," or ";" to make the indent on the number of characters in the value of the number of coordinates and then folding. But it will be very fragile and complicated algorithm. Maybe there is a simpler way?
0
Martin Ivanov
Telerik team
answered on 24 Nov 2016, 07:52 AM
Hello Svyatoslav,

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
Telerik UI for WPF is ready for Visual Studio 2017 RC! Learn more.
Tags
Diagram
Asked by
Svyatoslav
Top achievements
Rank 1
Answers by
Svyatoslav
Top achievements
Rank 1
Martin Ivanov
Telerik team
Share this question
or