Hello all,
currently I'm developing a feature to persist the UltraGrid filter configuration to a local file. Due to the fact that even more configurations (beside the grid configuration) already stored in a XML file the goal is to extend the XML with the UltraGrid filter configuration.
I tried different ways to achieve the goal but I run into multiple problems and currently there is no idea how to handle them.
The overall algorithem to store the data in the XML file (1-3) and load the saved data (4-6) looks like the folling steps:
I tried the following ways to include the filter settings into this algorithem (step 2):
Use DisplayLayout.SaveAsXML MethodThis is not working because the method isn't supported in .net5:
==> We using WinGrid Version 21.1.24 - is this method supported in newer versions? In case of yes, I think using the method would solve our problem.
Use DisplayLayout.Save Method - No base 64 encoding
Due to the restrictions mentiond, I tried to use the Save method to serialize the filter. The input stream of the Save method is casted to a StreamReader and later on to a string. This string is assigned to as property of the class which will serialized to the XML.
As a result I get a HTML encoded string in the XML file (the HTML encoding is automatically done by the XMLSerializer). When the XMLSerializer tries to deserialize the XML file (step 5) there is an exception that the XML is invalid (I think based on the HTML encoding).
The same exception is thrown when I HTMLDecode the XML before the deserialization.
This is the relevant part of the code:
/ /SERIALIZATION using (var memStream = new MemoryStream()) { this.DisplayLayout.Save(memStream, PropertyCategories.ColumnFilters); StreamWriter sw = new StreamWriter(memStream); sw.Flush(); memStream.Position = 0; StreamReader sr = new StreamReader(memStream); string temp = sr.ReadToEnd(); gridSettings.FilterSettings = temp; //gridSettings.FilterSettings = Convert.ToBase64String(Encoding.UTF8.GetBytes(temp)); sr.Dispose(); sw.Dispose(); } using (var stream = new MemoryStream()) { var serializer = new XmlSerializer(gridColumnSettings.GetType()); serializer.Serialize(stream, gridColumnSettings); var s = Encoding.UTF8.GetString(stream.GetBuffer(), 0, (int)stream.Length); return s; } // DESERIALIZATION using (var stream = new StringStream(serializedData)) { var serializer = new XmlSerializer(typeof(GridSettings)); var deserializedGridSettings = (GridSettings)serializer.Deserialize(stream); using (var ms = new MemoryStream()) { var sw = new StreamWriter(ms); var temp = WebUtility.HtmlDecode(deserializedGridSettings.FilterSettings); //var temp = Encoding.UTF8.GetString(Convert.FromBase64String(deserializedGridSettings.FilterSettings)); sw.Write(temp); sw.Flush(); ms.Position = 0; this.DisplayLayout.Load(ms, PropertyCategories.ColumnFilters); } }
=> Not working for our use case
Use DisplayLayout.Save Method - With base 64 encoding
To bypass the problem with the HTML encoding I tried to use a base64 encoding. The algorithm includes the following steps:
This is working fine and as a result the Base64 string is saved to the XML (without some HTML encoding).
Loading the XML and deserialize it is working now, but when the Base64 string is decoded and passed to the DisplayLayout.Load Method by wrapping it in a stream an exception with the message No map for object '201326592'. is thrown (see also Post here). By debugging the application I see that the string which is passed to the Load method is the same as the string that is created by the Save method.
--> Code see code snipet above with the base64 comments
=> Not working for my use case. Is there maybe a but at the Load method?
Serialize the FilterConditionsCollection or ColumnFilter class using the XMLSerializer
As a last way I tried to assign the ColumnFilter or FilterConditionsCollection object of the colum to the custom structure property which is serialized to the XML (step 2) but during the serialization process an exception is thrown because there is no parameterless constructure available for ColumnFilter or FilterConditionsCollection and subclasses of them.
=> Not working.
As a result my questions are:
by the way, saving the configuration by the Save method to a new txt file and load that file again is working without problems, but this is no solution for our problem.
Thank you and best regards
Sebastian
Hello ,
Thank you for your post. Yes you are right LoadFromXml and SaveAsXml methods are not present on the UltraGrid.DisplayLayout in .NET 5/.net 6. The reason for this is because Microsoft discontinued the SoapFormatter class in .NET Core, which the methods in question used extensively.
Luckily, we do expose other methods to save and load the layout of the UltraGridLayout via the Save and Load methods. These will save to binary, and so if you have an XML file that needs to be loaded, I would recommend that you first load it in a .NET Framework application and then re-save it using the Save method.
Hello,
Cust response from the email:
"
Bad news for the first part of your answer because I thought that would be the best and easiest way to solve my problem. But the Microsoft development is not up to you, so this is not an option.
Your suggestion how to handle the problem is not completely clear to me. With the Save method it’s only possible to save the UltraGridLayout data to a binary file/memory (vie stream) but even if I use the binary and save it to the XML file it’s not possible to re-open it (see the description at my post section Use DisplayLayout.Save Method - No base 64 encoding and Use DisplayLayout.Save Method – With base 64 encoding.
Maybe it helps to explain your current situation more detailed. We already have a common method which saves a XML file to the file system by using the System.Xml.Serialization.XMLSerializer. This algorithm creates a file like the following:
<applicationSettings>
<control1>
<visible>true</visible>
</control1>
<control2>
<fullscreen>true</fullscreen>
</control2>
</applicationSettings>
Now we want to add a tag with the filter settings of the grid. A example could look like the following example
<filter><<PLACEHOLDER_FOR_FILTER_SETTINGS>></filter>
By using the Save method to create a Memorystream and assign the result to the `filter` tag, I was not able to reload the binary data (as described at my initial post). So this solution is not working for us.
If you are able you can post my mail as a reply to the forum post so the information are documented at one place."