Load/Save Layout customization

18 posts, 1 answers
  1. Robyn
    Robyn avatar
    17 posts
    Member since:
    Aug 2011

    Posted 22 Sep 2011 Link to this post

    Hey,

    I'm loving the load and save layout feature of the RadGrid View. Very powerful tool to allow end users great control of how they want to view their data ;)

    BUT I a mhaving one issue with it. I have implemented the Save Load layout as per the documentation and I save these XML to our database without issue  - Since this has been done my boss has requested I add columns and change the names of columns on some of the Grids. The problem is, the SaveLayout() XML is saving the entire column template of the  grid and when I have an additional data row and bind this to the DataSource of the Grid the new column is not appearing (I have a similar problem if I rename the column in the underlying data-source).

    I've been tinkering with the SerializationMetadata and have been able to set this:

    this.XmlSerializationInfo.DisregardOriginalSerializationVisibility = true;

    And continue to make changes to how the columns themselves are saved. For example I was able to not save the format string - because this is again something we want control over in development.

    To top this off, it's very FEW things that I want removed from the Original Meta Data and it is painstaking and very prone to error to add all these serialization values back after calling the clear() method as instructed by the documentation. 

    Would love if anyone out there knows of a way to control WHICH columns exist via the datasource but still save the layout details of each columns - and if there's an easier approach to perhaps remove specific layout options instead of having to re-build the entire Serialization info.

    Cheers, thanks for reading
    Dave - Connect Direct
  2. Alexander
    Admin
    Alexander avatar
    306 posts

    Posted 27 Sep 2011 Link to this post

    Hello Dave,

    Thank you for your questions.

    RadGridView does not contain API for customizations of its save / load layout mechanism which to allow you to exclude a column property from the serialization. All column properties, which are visible for serialization, will be included by default. To achieve your task, you should recreate the serialization metadata of the control or save the layout to the memory and edit it.

    To identify if a column is generated from the control's DataSource, you can check its IsAutoGenerated property.

    I hope it helps.

    Best regards,
    Alexander
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

  3. Robyn
    Robyn avatar
    17 posts
    Member since:
    Aug 2011

    Posted 27 Sep 2011 Link to this post

    Hello,

    Your suggestion to recreate the meta data is exactly what I am trying to do, but unfortunately it is this approach which also seems limited in achieving my goals. Consider the following scenario:

    Day 1. We release our product with a grid that has a datasource bound containing three columns X,Y,Z. The user can change the layout and size and all wonderful things with these three columns. All is good
    Day 2. We are requested to add a new column to this grid, called A. We add in development this column to the underlying datasource and test on a machine WITHOUT any grid layout saved. All is fine, these columns X,Y,Z,A all get generated and added to the Grid.
    Day 3. We give this new version to our client. Unfortunately, since their column layout is saved they never see this new column.

    It's almost like once the columns are loaded from XML, the grid will no longer Auto-Generate any further columns if a new datasource is bound. At least this appears to be the behavior. PErhaps I am missing some grid option I should be saving to my meta data. Here's my code I'm using to serialize the meta-data. If there is any serialization you know of that can achieve what I'm after it would be very helpful. Currently we have implemented a hotkey to clear all layout data for a grid and we'll be asking clients to do this if they want to use new/renamed columns ;(

    I feel like, because I'm serializing the Columns in the MasterGridViewTemplate (which I have to do to serialize the properties of the columns), then this becomes the 'final' column set for the grid.

    private void SetupSerialization()
    {
        this.XmlSerializationInfo.DisregardOriginalSerializationVisibility = true;
        this.XmlSerializationInfo.SerializationMetadata.Clear();
    this.XmlSerializationInfo.SerializationMetadata.Add(typeof(RadGridView),"MasterGridViewTemplate",DesignerSerializationVisibilityAttribute.Content);
     
    this.XmlSerializationInfo.SerializationMetadata.Add(typeof(GridViewTemplate), "Columns", DesignerSerializationVisibilityAttribute.Content);
     
    this.XmlSerializationInfo.SerializationMetadata.Add(typeof(GridViewDataColumn), "IsVisible", DesignerSerializationVisibilityAttribute.Visible);
    this.XmlSerializationInfo.SerializationMetadata.Add(typeof(GridViewDataColumn), "UniqueName",DesignerSerializationVisibilityAttribute.Visible);
    this.XmlSerializationInfo.SerializationMetadata.Add(typeof(GridViewDataColumn), "Name", DesignerSerializationVisibilityAttribute.Visible);
    this.XmlSerializationInfo.SerializationMetadata.Add(typeof(GridViewDataColumn), "HeaderText", DesignerSerializationVisibilityAttribute.Visible);
    this.XmlSerializationInfo.SerializationMetadata.Add(typeof(GridViewDataColumn), "IsAutoGenerated", DesignerSerializationVisibilityAttribute.Visible);
    this.XmlSerializationInfo.SerializationMetadata.Add(typeof(GridViewDataColumn), "SortOrder", DesignerSerializationVisibilityAttribute.Visible);
    this.XmlSerializationInfo.SerializationMetadata.Add(typeof(GridViewDataColumn), "ReadOnly", DesignerSerializationVisibilityAttribute.Visible);
    this.XmlSerializationInfo.SerializationMetadata.Add(typeof(GridViewDataColumn), "TextAlignment", DesignerSerializationVisibilityAttribute.Visible);
    this.XmlSerializationInfo.SerializationMetadata.Add(typeof(GridViewDataColumn), "FieldName", DesignerSerializationVisibilityAttribute.Visible);
    this.XmlSerializationInfo.SerializationMetadata.Add( typeof(GridViewDataColumn), "Width", DesignerSerializationVisibilityAttribute.Visible);
    this.XmlSerializationInfo.SerializationMetadata.Add(typeof(GridViewDataColumn), "IsPinned", DesignerSerializationVisibilityAttribute.Visible);
    this.XmlSerializationInfo.SerializationMetadata.Add(typeof(GridViewDataColumn), "PinnedPosition", DesignerSerializationVisibilityAttribute.Visible);
    }


  4. Alexander
    Admin
    Alexander avatar
    306 posts

    Posted 30 Sep 2011 Link to this post

    Hello Robyn,

    Thank you for the detailed description of your scenario. I have attached a sample project which follows this scenario.

    The project allows you to bind the RadGridView control to two different DataSources. The first one has columns X, Y, and Z and the second one - X, Y, Z, and A. If you bind to the first DataSource, save the layout and bind to the second DataSource (as in your scenario), RadGridView will not create the A column from the second DataSource. This is a desired behavior. It allows the user to save layout with the columns he wants to see and keep them after rebinding.

    One approach you can use to achieve your requirements is to delete the RadGridView columns before rebinding. It is demonstrated in the attached sample. If you wish to keep some columns, missing in the new DataSource, you should implement additional logic to add them again after rebinding.

    I hope it helps you to accomplish your requirements.

    Best regards,
    Alexander
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

  5. Robyn
    Robyn avatar
    17 posts
    Member since:
    Aug 2011

    Posted 30 Sep 2011 Link to this post

    Good morning,

    Thanks for your example - It has been a good simple tool to tinker with the underlying behavior of what's going on

    Just to be clear on the 2 requirements- It's not a requirement to keep columns that are no longer in the second datasource. What we need is:
    1. New columns, or re-named columns to be included.
    2. Existing/identical columns must have all their width/order/sort/header text/pinning information etc etc maintained when binding the new datasource.

    It's requirement 2 that doesn't quite gell with removing all the existing columns and then rebinding. This fufills 1 but then the common columns lose their layout information.

    We have currently implemented a layout reset button for users to hit if they choose to get any new columns we release in our grids. This button will reset everything however so is not an ideal solution. I'll post here if I get a solution.

    Regards,
    Connect Direct Team
  6. Answer
    Alexander
    Admin
    Alexander avatar
    306 posts

    Posted 04 Oct 2011 Link to this post

    Hello Robyn,

    Thank you for the additionally specifying your requirements.

    Let's consider the following scenario and the possible approach to handle it:
    1. The user saves a layout with an older version of your application. Its layout includes the X, Y, and Z columns with their properties.
    2. The user updates his application. The new DataSource has one more column - A.
    3. The user loads layout and rebinds RadGridView. The X, Y, and Z columns are loaded with their previously saved properties. The A column is not generated.
    4. You can update your code so after rebinding RadGridView, you can call the AutoGenerateBoundColumns method of GridViewTemplate. The method is not public, so you should use reflection to call it. The method will add the missing column (A) without recreating the rest of the columns so they will keep their loaded properties. Then refresh the template in order to see the newly created column:
    this.radGridView1.DataSource = dataSource;
     
    MethodInfo methodInfo = typeof(GridViewTemplate).GetMethod("AutoGenerateBoundColumns", BindingFlags.Instance | BindingFlags.NonPublic);
    methodInfo.Invoke(this.radGridView1.MasterTemplate, new object[] { this.radGridView1.MasterTemplate.ListSource.BoundProperties });
    this.radGridView1.MasterTemplate.Refresh();

    You can find attached the updated test project. Please let me know if it helps you achieve your scenario.

    Best regards,
    Alexander
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

  7. Robyn
    Robyn avatar
    17 posts
    Member since:
    Aug 2011

    Posted 04 Oct 2011 Link to this post

    Hi Alexander,

    Perfect - Exactly the behavior I'm after!
    Invaluable support

    For anyone else following this the only difference my solution has to the provided one is it is built into a custom control we use in our project. I also deal with saving and loading the configuration XML to our database per grid automatically inside this custom control (On Load/Dispose) if anyone is interested. Below is my now working, custom code

        public partial class DCRadGridView : RadGridView
        {
     
            public DCRadGridView()
            {
                InitializeComponent();
                customContextMenu = this.ContextMenuStrip;
                this.DataBindingComplete += new Telerik.WinControls.UI.GridViewBindingCompleteEventHandler(DCRadGridView_DataBindingComplete);
                SetupSerialization();
            }
     
            void DCRadGridView_DataBindingComplete(object sender, Telerik.WinControls.UI.GridViewBindingCompleteEventArgs e)
            {
     
                 
                MethodInfo methodInfo = typeof(GridViewTemplate).GetMethod("AutoGenerateBoundColumns", BindingFlags.Instance | BindingFlags.NonPublic);
                methodInfo.Invoke(this.MasterTemplate, new object[] { this.MasterTemplate.ListSource.BoundProperties });
                this.MasterTemplate.Refresh();
            }
     
    ....



    Cheers,
    Connect Direct Team
  8. Alexander
    Admin
    Alexander avatar
    306 posts

    Posted 05 Oct 2011 Link to this post

    Hello Robyn,

    I am glad to hear this approach works for your case. Thank you for sharing your solution. I hope it will be useful to other developers as well.

    Best regards,
    Alexander
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

  9. AMF
    AMF avatar
    36 posts
    Member since:
    Mar 2011

    Posted 22 May 2012 Link to this post

    Is this still the best way to generate the columns that aren't in the layout?
  10. Boryana
    Admin
    Boryana avatar
    330 posts

    Posted 25 May 2012 Link to this post

    Hello,

    Thank you for writing.

    I confirm this is the best way to achieve the described scenario.

    Feel free to write back if you encounter any issues.

    Regards,
    Boryana
    the Telerik team
    RadControls for WinForms Q1'12 release is now live! Check out what's new or download a free trial >>
  11. Jay
    Jay avatar
    11 posts
    Member since:
    Mar 2012

    Posted 03 Apr 2014 Link to this post

    What about the opposite scenario. 

    Day 1. We release our product with a grid that has a datasource bound containing three columns A,X,Y,Z. The user can change the layout and size and all wonderful things with these three columns. All is good
    Day 2. We are requested to delete column to this grid, called A. We delete in development this column to the underlying datasource and test on a machine WITHOUT any grid layout saved. All is fine, these columns X,Y,Z all get generated and added to the Grid.
    Day 3. We give this new version to our client. Unfortunately, since their column layout is saved they see the old column.

    Just to be clear on the requirements- What we need is:
    2. Existing/identical columns must have all their width/order/sort/header text/pinning information etc etc maintained when binding the new datasource.
  12. Dess | Tech Support Engineer, Sr.
    Admin
    Dess | Tech Support Engineer, Sr.  avatar
    4086 posts

    Posted 08 Apr 2014 Link to this post

    Hello Jay,

    Thank you for writing.

    When the RadGridView saves its layout, it stores the currently available columns into a xml. The load layout functionality restores all of the serialized columns into the grid. It is desired and correct behavior of the introduced functionality. 

    If the initial data source has columns A, B, C, D and you save these columns in the xml, then change the data source, which contains columns A, B, C, E. Loading the layout will restore columns A, B, C, D. This is by design. However, if you want to manipulate the restored columns, it is necessary to be handled manually: remove the redundant columns and add the missing columns. Here is a sample code snippet, demonstrating the described scenario above. If the initial DataTable contains columns A, B, C, D, save the layout, rebind to the second data source with columns A, B, C, E and load the layout again. Then remove the columns that are not available in the current data source of the grid and add those ones that are missing:
    DataTable dt1 = new DataTable();
     
    DataTable dt2 = new DataTable();
     
    public Form1()
    {
        InitializeComponent();
     
        dt1.Columns.Add("A", typeof(string));
        dt1.Columns.Add("B", typeof(string));
        dt1.Columns.Add("C", typeof(string));
        dt1.Columns.Add("D", typeof(string));
     
        dt2.Columns.Add("A", typeof(string));
        dt2.Columns.Add("B", typeof(string));
        dt2.Columns.Add("C", typeof(string));
        dt2.Columns.Add("E", typeof(string));
     
        for (int i = 0; i < 10; i++)
        {
            dt1.Rows.Add("A" + i, "B" + i, "C" + i, "D" + i);
            dt2.Rows.Add("A" + i, "B" + i, "C" + i, "E" + i);
        }
        this.radGridView1.DataSource = dt1;
        this.radGridView1.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill;
    }
     
    private void radButtonSave_Click(object sender, EventArgs e)
    {
        string s = "default.xml";
        SaveFileDialog dialog = new SaveFileDialog();
        dialog.Filter = "xml files (*.xml)|*.xml|All files (*.*)|*.*";
        dialog.Title = "Select a xml file";
        if (dialog.ShowDialog() == DialogResult.OK)
        {
            s = dialog.FileName;
        }
        this.radGridView1.SaveLayout(s);
    }
     
    private void radButtonLoad_Click(object sender, EventArgs e)
    {
        string s = "default.xml";
        OpenFileDialog dialog = new OpenFileDialog();
        dialog.Filter = "xml files (*.xml)|*.xml|All files (*.*)|*.*";
        dialog.Title = "Select a xml file";
        if (dialog.ShowDialog() == DialogResult.OK)
        {
            s = dialog.FileName;
        }
        this.radGridView1.LoadLayout(s);
      
        //remove reduntant columns
        DataTable dt = this.radGridView1.DataSource as DataTable;
        for (int i = 0; i < this.radGridView1.Columns.Count; i++)
        {
            GridViewDataColumn col = this.radGridView1.Columns[i];
            if (!dt.Columns.Contains(col.Name))
            {
                this.radGridView1.Columns.Remove(col);
            }
        }
     
        //add missing columns
        foreach (DataColumn col in dt.Columns)
        {
            if (!this.radGridView1.Columns.Contains(col.ColumnName))
            {
                    this.radGridView1.Columns.Add(col.ColumnName);
                this.radGridView1.Columns[col.ColumnName].FieldName = col.ColumnName;
            }
        }
    }
     
    private void radButtonRebind_Click(object sender, EventArgs e)
    {
        this.radGridView1.DataSource = dt2; 
    }

    Note that this sample code snippet is purposed to demonstrate the approach and it may not cover all possible cases. Feel free to modify it on a way, which suits your requirement best. 

    I hope this information helps. Should you have further questions, I would be glad to help.

    Regards,
    Desislava
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  13. Evangelista
    Evangelista avatar
    3 posts
    Member since:
    Mar 2011

    Posted 21 Nov 2017 Link to this post

    Hi,

    Is this still the best way to generate the columns that aren't in the layout?

    Thanks

  14. Dess | Tech Support Engineer, Sr.
    Admin
    Dess | Tech Support Engineer, Sr.  avatar
    4086 posts

    Posted 22 Nov 2017 Link to this post

    Hello, Evangelista,

    Thank you for writing.  

    RadGridView will display only the columns that are stored in the layout. This is desired behavior and it has not been changed. The suggested approach from my previous post is still valid. Feel free to use if you have a similar scenario.

    I hope this information helps. Should you have further questions I would be glad to help.
     
    Regards,
    Dess
    Progress Telerik
    Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
  15. parthiv
    parthiv avatar
    7 posts
    Member since:
    Sep 2017

    Posted 23 Nov 2017 in reply to Dess | Tech Support Engineer, Sr. Link to this post

    hi

    I am new to telerik ,i am using R2 2017 but i cant get method radgridview.savelayout and loadlayout method.plz help

  16. Dess | Tech Support Engineer, Sr.
    Admin
    Dess | Tech Support Engineer, Sr.  avatar
    4086 posts

    Posted 23 Nov 2017 Link to this post

    Hello, Parthiv,

    Thank you for writing.  

    Save/Load layout functionality gives your applications the opportunity to preserve user grid settings such as column order and restore them later. Additional information is available in the following section of the online documentation: https://docs.telerik.com/devtools/winforms/gridview/save-and-load-layout/save-and-load-layout

    You can refer to our Demo application >> GridView >> Export >> Save/Load layout example. The Demo application is located in the installation folder of the suite. It can be found at the following path: C:\Program Files (x86)\Progress\Telerik UI for WinForms R3 2017\Examples\QuickStart\Bin

    I hope this information helps. Should you have further questions I would be glad to help.
     
    Regards,
    Dess
    Progress Telerik
    Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
  17. parthiv
    parthiv avatar
    7 posts
    Member since:
    Sep 2017

    Posted 23 Nov 2017 in reply to Dess | Tech Support Engineer, Sr. Link to this post

    Hello Dess,

    Thx for quick rply, i forgot to tell you m using Wpf..plz help

  18. Dess | Tech Support Engineer, Sr.
    Admin
    Dess | Tech Support Engineer, Sr.  avatar
    4086 posts

    Posted 23 Nov 2017 Link to this post

    Hello, Parthiv,    

    Thank you for writing back. 

    I would like to note that this forum is related to the Telerik UI for WinForms suite. If you  have any questions related to other products feel free to use the relevant forum:
    https://www.telerik.com/forums

    I hope this information helps.  

     Regards,
    Dess
    Progress Telerik
    Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
Back to Top