Geometry to XAML

11 posts, 0 answers
  1. Svyatoslav
    Svyatoslav avatar
    10 posts
    Member since:
    Oct 2016

    Posted 25 Oct Link to this post

    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?

  2. Svyatoslav
    Svyatoslav avatar
    10 posts
    Member since:
    Oct 2016

    Posted 27 Oct Link to this post

    somebody help me please
  3. UI for WPF is Visual Studio 2017 Ready
  4. Martin
    Admin
    Martin avatar
    1101 posts

    Posted 28 Oct Link to this post

    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!
  5. Svyatoslav
    Svyatoslav avatar
    10 posts
    Member since:
    Oct 2016

    Posted 28 Oct in reply to Martin Link to this post

    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?=)
  6. Martin
    Admin
    Martin avatar
    1101 posts

    Posted 01 Nov Link to this post

    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!
  7. Svyatoslav
    Svyatoslav avatar
    10 posts
    Member since:
    Oct 2016

    Posted 10 Nov in reply to Martin Link to this post

    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

  8. Martin
    Admin
    Martin avatar
    1101 posts

    Posted 14 Nov Link to this post

    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!
  9. Svyatoslav
    Svyatoslav avatar
    10 posts
    Member since:
    Oct 2016

    Posted 15 Nov in reply to Martin Link to this post

    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

  10. Martin
    Admin
    Martin avatar
    1101 posts

    Posted 17 Nov Link to this post

    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.
  11. Svyatoslav
    Svyatoslav avatar
    10 posts
    Member since:
    Oct 2016

    Posted 21 Nov in reply to Martin Link to this post

    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?
  12. Martin
    Admin
    Martin avatar
    1101 posts

    Posted 24 Nov Link to this post

    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.
Back to Top
UI for WPF is Visual Studio 2017 Ready