SaveLayout/LoadLayout Documentation

9 posts, 0 answers
  1. erwin
    erwin avatar
    358 posts
    Member since:
    Dec 2006

    Posted 23 Dec 2008 Link to this post

    Hello,

    I'm currently playing around with the SaveLayout LoadLayout Methods of RadGridView.
    The basic Idea of these functions is quite interesting.
     
    How are situations handled where the definition of the grid or datasource during LoadLayout is slightly different from the time the layout was saved?
    What's the expected behaviour if number, header, relative position and/or data types of columns change, or if the grid itself gets resized?

    I could not find comprehensive documentation about these functions.

    Regards
    Erwin

  2. Nick
    Admin
    Nick avatar
    767 posts

    Posted 23 Dec 2008 Link to this post

    Hi erwin,

    Thank you for your feedback. We will provide documentation soon. In the mean time, I am copying a ticket reply that contains some useful information:

    I'll try to explain explain how Save/LoadLayout works since Q2 SP1.

    SaveLayout persist all grid properties, similar to ComponentCodeDomSerializaer that VS designer uses, following the same rules - i.e. it uses properties serialization metadata (attributes) like DefaultValue, DesignerSerializationVisibility TypeConverter and others. There are few excluded properties though, like RadGridView.Name, ThemeName and DataSource, DataMember of all GridViewTemplates in the hierarchy. Those properties concern the runtime behavior of the grid and were causing various problems when serializing/deserializing.

    As it comes to deserialization, there are some new things to consider:
    • The GridColumns collection is merged upon deserialization. The columns that are present in the grid instance, which call LoadLayout, are mapped to those found in the xml file by the UniqueName property and then deserialized. Columns are reordered according to the xml-layout definition. The extra Columns found in the xml file that are not present in the original collection are added to the collection. No columns are deleted/recreated in the original collection. This is important, because column objects may contain references to other objects/components, e.g. the combo-column may have a DataSource and so on. Since Q2 SP2 loading layout will not break this column's behavior.
    • Similar to the column's updating logic, LoadLayout will not delete any existing GridViewTemplates when used in hierarchy mode. But RadGridView will load templates' properties in the same order they appear in the xml file. In other words, for best results LoadLayout expects the same grid hierarchy structure as the on that was used with SaveLayout. Nevertheless LoadLayout should not fail in other cases. Instead, extra GridViewTemplate definition found in the xml will be added to the corresponding ChildTemplates collection.
    Here is a sample unit-test code that I use to validate some parts of the logic of Save/LoadLayout methods. It may help you clarify how we think this feature should work:


    [TestMethod] 
            public void TestPeristGridColumns() 
            { 
                //Create grid test instance and set some properties, columns, etc 
                //later on we will test if all properties and structure are persisted to another grid instance 
                RadGridView gridView = new RadGridView(); 
     
                gridView.Size = new System.Drawing.Size(100, 100); 
                gridView.Behavior.ShowItemToolTips = true
                gridView.DataMember = "MasterDataMemeber"
                gridView.Location = new Point(10, 11); 
     
                GridViewTextBoxColumn textBoxColumn = new GridViewTextBoxColumn("field1"); 
                textBoxColumn.Width = 155; 
                textBoxColumn.SortOrder = RadSortOrder.Descending;             
                gridView.MasterGridViewTemplate.Columns.Add(textBoxColumn); 
     
                gridView.MasterGridViewTemplate.FilterExpressions.Add(new FilterExpression("field1", FilterExpression.BinaryOperation.AND, GridKnownFunction.StartsWith, new object[] { "a" })); 
     
                ConditionalFormattingObject formattingObject = new ConditionalFormattingObject("Green", ConditionTypes.Equal, "France"""false); 
                formattingObject.CellForeColor = Color.Red; 
                formattingObject.CellBackColor = Color.Blue; 
     
                textBoxColumn.ConditionalFormattingObjectList.Add(formattingObject); 
     
                GridViewDecimalColumn decimalColumn = new GridViewDecimalColumn("field2"); 
                decimalColumn.Width = 200; 
                gridView.MasterGridViewTemplate.Columns.Add(decimalColumn); 
     
                GridViewTemplate childTemplate = new GridViewTemplate(gridView); 
                childTemplate.DataMember = "TestMember"
                childTemplate.GroupBy = "field3 group by field3"
                childTemplate.HorizontalScrollState = ScrollState.AlwaysShow; 
                gridView.MasterGridViewTemplate.ChildGridViewTemplates.Add(childTemplate); 
     
                childTemplate.Columns.Add(new GridViewTextBoxColumn("field3")); 
     
                string output = null
     
                using (StringWriter stringWriter = new StringWriter()) 
                { 
                    using (XmlWriter writer = new XmlTextWriter(stringWriter)) 
                    { 
                        gridView.SaveLayout(writer); 
                    } 
                    output = stringWriter.ToString(); 
                    Console.WriteLine(output); 
                } 
     
                Assert.IsNotNull(output); 
     
                //now deserialize 
                gridView = new RadGridView(); 
     
                //create only 1 column this time, to test column merging 
                gridView.DataMember = "MasterDataMemeber"
                gridView.Columns.Add(new GridViewDecimalColumn("field2")); 
     
                //child templates should match 
                childTemplate = new GridViewTemplate(gridView); 
                childTemplate.DataMember = "TestMember"
                gridView.MasterGridViewTemplate.ChildGridViewTemplates.Add(childTemplate); 
     
                using (StringReader reader = new StringReader(output)) 
                { 
                    using (XmlTextReader textReader = new XmlTextReader(reader)) 
                    { 
                        gridView.LoadLayout(textReader); 
                    } 
                } 
     
                Assert.AreEqual(new Point(10, 11), gridView.Location); 
                Assert.AreEqual("MasterDataMemeber", gridView.DataMember); 
                Assert.AreEqual(true, gridView.Behavior.ShowItemToolTips); 
                Assert.AreEqual(new System.Drawing.Size(100, 100), gridView.Size); 
                 
                //test columns deserialization and correct ordering 
                Assert.AreEqual(2, gridView.Columns.Count);  
                Assert.AreEqual(typeof(GridViewTextBoxColumn), gridView.Columns[0].GetType()); 
                Assert.AreEqual(155, gridView.Columns[0].Width); 
                Assert.AreEqual(RadSortOrder.Descending, gridView.Columns[0].SortOrder); 
     
                Assert.AreEqual(1, gridView.Columns[0].ConditionalFormattingObjectList.Count); 
                Assert.AreEqual(Color.Red, gridView.Columns[0].ConditionalFormattingObjectList[0].CellForeColor); 
     
                Assert.AreEqual(typeof(GridViewDecimalColumn), gridView.Columns[1].GetType()); 
                Assert.AreEqual(200, gridView.Columns[1].Width); 
     
                //tests filtering 
                Assert.AreEqual("(([" + gridView.Columns[0].FieldAlias + "] LIKE 'a%'))", gridView.MasterGridViewTemplate.FilterExpressions[0].ToString()); 
     
                //test grouping and hierarchy deserialization 
                Assert.AreEqual(1, gridView.MasterGridViewTemplate.ChildGridViewTemplates.Count); 
                Assert.AreEqual("TestMember", gridView.MasterGridViewTemplate.ChildGridViewTemplates[0].DataMember); 
                Assert.AreEqual(1, gridView.MasterGridViewTemplate.ChildGridViewTemplates[0].Columns.Count); 
                Assert.AreEqual(ScrollState.AlwaysShow, childTemplate.HorizontalScrollState); 
                Assert.AreEqual("field3", gridView.MasterGridViewTemplate.ChildGridViewTemplates[0].Columns[0].UniqueName); 
            } 

    Let me know if you have any other questions.

    Kind regards,
    Nick
    the Telerik team

    Check out Telerik Trainer, the state of the art learning tool for Telerik products.
  3. UI for WinForms is Visual Studio 2017 Ready
  4. Dragoljub
    Dragoljub avatar
    26 posts
    Member since:
    Feb 2008

    Posted 07 Jan 2009 Link to this post

    Hi,

    One question about the layout saving and loading functionality.

    Why do you include Location and Size of the grid? I know that data is conventionally considered "layout", but in the case of the grid, it should not be.

    For me, the layout of the grid means: how the data is sorted, how it is filtered, which columns are visible, by which column the data is grouped, and maybe even the "design time" data such as: allow add, allow delete, read-only, selection mode and similar functional properties. But the position and size should be something that is determined at design time (or run-time if the grid is anchored or docked). If you made a poll, I bet 95% of people would vote like me, because the context where one would use this feature is similar to my case.
  5. erwin
    erwin avatar
    358 posts
    Member since:
    Dec 2006

    Posted 07 Jan 2009 Link to this post


    There is an undocumented way to specify exactly what gets serialized to xml.
    I got the workaround on the answer to a support ticket, therefore I don't publish it here.

    Either open a ticket with telerik, or maybe they publish the workaround here.

    I agree with your opinion about the size and location properties. In my examples, I think they are ignored on load.
    At least I have not experienced unexpected behaviour when loading layouts into re-sized grids. However, all my grids use fill docking to their container (usually table layout panel) which probably overrides size and location. If your grids are resized/moved on load layout, you might try to fill dock them into a container (panel etc.).

    Regards
    Erwin


  6. Dragoljub
    Dragoljub avatar
    26 posts
    Member since:
    Feb 2008

    Posted 07 Jan 2009 Link to this post

    It was docked! And then I discovered that the grouping panel was not showing columns by which the data was grouped WHEN the grid is docked and inside a WindowsFormsHost (in a WPF application). So the workaround that is currently in place is to use anchors on all sides.

    I know it's just XML and it's easy to remove unwanted data before persisting the XML, I just didn't get a chance to do it yet.
  7. erwin
    erwin avatar
    358 posts
    Member since:
    Dec 2006

    Posted 08 Jan 2009 Link to this post

    The Telerik approach does not involve direct manipulation of the .xml but rather using a customized Serializer object which is IMHO much more elegant. Trouble is that this is not documented yet.

    Erwin
  8. Nick
    Admin
    Nick avatar
    767 posts

    Posted 09 Jan 2009 Link to this post

    Hello Dragoljub,

    Thank you for your feedback. We are glad that you found a way to workaround this issue. We are going to remove serialization of Size, Location and Dock properties for 2008 Q3 SP2 which is to be released the week of 19th this month.

    If you are anxious to customize serialization, I can send you some sample code. We are, though, adding a few new serialization APIs in RadGridView in order to make it more convenient for you.

    Sincerely yours,
    Nick
    the Telerik team

    Check out Telerik Trainer, the state of the art learning tool for Telerik products.
  9. Dragoljub
    Dragoljub avatar
    26 posts
    Member since:
    Feb 2008

    Posted 09 Jan 2009 Link to this post

    Thanks for the tip. I can wait for the week after the 19th.

    I also must report another strange problem we had related to SaveLayout and LoadLayout and updating to a new version, although I don't see how you can fix it, because I don't have much details. The whole application got frozen soon after the LoadLayout was called. You only had to click on a column header, try filtering, or try grouping or open& try to close column chooser. It was solved finally by removing the grid from the form and adding it again (but first the toolbox items also had to be removed and added manually to point to the new version, the installer didn't do that!). I guess it was some properties stored in the .Designer.vb source file, but the stored layout xml was deleted as well, so maybe that was part of the solution too.

    The column chooser still made problems - when it's opened and you try to close it, the app gets frozen. The only clue we have to this problem is that it appears intermitently WHEN there are grouping columns. One theory I have is that your code for drawing (and managing drag& drop operations) within the area where grouped columns are shown (in the header of the grid) is causing this problem. We also encountered that bug where that area remains empty if you set grid's Dock property to Fill inside a WPF application. That is a reproducable issue and earlier I have submitted it as a support ticket using a different account. Maybe you can start from there. These other issues are harder to reproduce, I'm still not able to create a small and simple repro project.
  10. Nick
    Admin
    Nick avatar
    767 posts

    Posted 12 Jan 2009 Link to this post

    Hello Dragoljub,

    Thank you for writing us back and reporting the issues. We are going to check and fix them if we manage to reproduce the behavior. Please send us a sample project if you manage to do so because it will help us a lot. Do not hesitate to write me back if you have more questions.

    Regards,
    Nick
    the Telerik team

    Check out Telerik Trainer, the state of the art learning tool for Telerik products.
Back to Top
UI for WinForms is Visual Studio 2017 Ready