Reordering columns issue once again

9 posts, 0 answers
  1. Erik
    Erik avatar
    2 posts
    Member since:
    Apr 2016

    Posted 25 Apr 2016 Link to this post

    Hi,

    I'm facing one issue and I really do not know where could the problem.

     

    It's once again (as I read few other posts in the forum, nothing new) related to persisting order of columns in GridView. My problem happens only when the columns get reordered by drag-n-drop. When I add and or remove columns (this is done programatically in my view's code-behind) and try to persists Grid's state, everything works well. Unless I reorder their sequence.

     

     

    It's worth mentioning that I'm persisting the state in my filesystem so that I could restore it later. Solution with IsolatedStorageProvider is not well suited for me. But I do not think that this should be any issue.Storage happens everytime the button 'Save layout' is being clicked.

     

    I have created sample video that shows what I'm trying to say maybe even more expressively. Look here.I have created sample video that shows what I'm trying to say maybe even more expressively. Look here - https://drive.google.com/file/d/0B0cxhvgqPibkNHhyUzM1TVVHOVU/view

     

    I have implemented my version of ICustomPropertyProvider, but it's almost identical to the one provided in WPF Control Examples. See here:

     

    public class GridViewCustomPropertyProvider : ICustomPropertyProvider
        {

            private const string _columnsProperty = "Columns";
            private const string _sortDescriptorsProperty = "SortDescriptors";

            public CustomPropertyInfo[] GetCustomProperties()
            {
                return new CustomPropertyInfo[]
                {
                    new CustomPropertyInfo(_columnsProperty, typeof(List<ColumnProxy>)), 
                    new CustomPropertyInfo(_sortDescriptorsProperty, typeof(List<SortDescriptorProxy>)), 
                };
            }

            public void InitializeObject(object context)
            {
                if (context is RadGridView)
                {
                    RadGridView gridView = context as RadGridView;
                    //gridView.Columns.Clear();
                    gridView.SortDescriptors.Clear();
                    foreach (GridViewColumn gridViewColumn in gridView.Columns)
                    {
                        gridViewColumn.ClearFilters();
                    }
                }
            }

            public object InitializeValue(CustomPropertyInfo customPropertyInfo, object context)
            {
                return null;
            }

            public void RestoreValue(CustomPropertyInfo customPropertyInfo, object context, object value)
            {
                RadGridView gridView = context as RadGridView;

                switch (customPropertyInfo.Name)
                {
                    case _sortDescriptorsProperty:

                        gridView.SortDescriptors.SuspendNotifications();
                        gridView.SortDescriptors.Clear();

                        List<SortDescriptorProxy> proxies = value as List<SortDescriptorProxy>;

                        foreach (SortDescriptorProxy proxy in proxies)
                        {
                            GridViewColumn column = gridView.Columns[proxy.ColumnName];
                            gridView.SortDescriptors.Add(new ColumnSortDescriptor(){Column = column, SortDirection = proxy.SortDirection});
                        }

                        gridView.SortDescriptors.ResumeNotifications();

                        break;

                    default:

                        var columnProxies = value as List<ColumnProxy>;
                        //var orderedColumns = columnProxies.OrderBy(x => x.DisplayIndex);

                        foreach (ColumnProxy columnProxy in columnProxies)
                        {
                            GridViewColumn gridColumn = gridView.Columns[columnProxy.UniqueName];
                            gridColumn.DisplayIndex = columnProxy.DisplayIndex;
                            gridColumn.Header = "blabhalbl" + columnProxy.Header;
                            gridColumn.Width = columnProxy.Width;
                            //gridView.Columns.Add(gridColumn);
                        }

                        break;
                }
            }

            public object ProvideValue(CustomPropertyInfo customPropertyInfo, object context)
            {
                RadGridView gridView = context as RadGridView;

                var orderedColuns = OrderedColumns(gridView);

                switch (customPropertyInfo.Name)
                {

                    case _sortDescriptorsProperty:
                        {
                            List<SortDescriptorProxy> sortDescriptorProxies = new List<SortDescriptorProxy>();

                            foreach (ColumnSortDescriptor descriptor in gridView.SortDescriptors)
                            {
                                sortDescriptorProxies.Add(new SortDescriptorProxy()
                                {
                                    ColumnName = descriptor.Column.UniqueName,
                                    SortDirection = descriptor.SortDirection,
                                });
                            }

                            return sortDescriptorProxies;
                        }


                    default:

                        var columns = new List<ColumnProxy>();
                        foreach (GridViewColumn column in orderedColuns.OrderBy(x => x.DisplayIndex))
                        {
                            columns.Add(new ColumnProxy()
                            {
                                UniqueName = column.UniqueName,
                                Header = column.Header.ToString() + "someother",
                                DisplayIndex = column.DisplayIndex,
                                Width = column.Width
                            });
                        }

                        return columns;
                }
            }

            private static List<GridViewColumn> OrderedColumns(RadGridView gridView)
            {
                var orderedList = new List<GridViewColumn>();

                for (int i = 0; i < gridView.Columns.Count; i++)
                {
                    orderedList.Add(gridView.Columns[i]);
                }
                return orderedList;
            }
        }

     

    Thanks in advance for any piece of advice,

    Erik

  2. Erik
    Erik avatar
    2 posts
    Member since:
    Apr 2016

    Posted 26 Apr 2016 in reply to Erik Link to this post

    I also gave a chance to IsolatedStorageProvider, but the issue is the same though. Adding and removing columns works well. But rearranging them and then retrieving their state does not work properly.
  3. Kiril Vandov
    Admin
    Kiril Vandov avatar
    324 posts

    Posted 28 Apr 2016 Link to this post

    Hello Erik,

    The attached providers looks ok and there is no reason on why the ordering state with drag drop is not saved. I have tested this scenario with our latest official binaries and its working.

    I have attached a sample project with CustomPropertyProvider for the GridView in which I am saving the FilterDescriptors/GroupDescriptors/SortDescriptors and Columns properties for your convenience.

    Kind regards,
    Kiril Vandov
    Telerik
    Do you need help with upgrading your AJAX, WPF or WinForms project? Check the Telerik API Analyzer and share your thoughts.
  4. John
    John avatar
    1 posts
    Member since:
    Mar 2017

    Posted 31 May 2018 Link to this post

    I was having a strange issue with column ordering when applying saved settings. I am using a custom property provider to limit the amount of data stored for my grid. As the display order was being applied to each, column the original order of the columns matters. If a column is moved closer to the front of the grid and another column is moved in front of that one, the first column is moved one place to the right. The fix for this is to sort the list of column proxies by display order in the restore value method of the custom property provider. That way the display orders are applied from lowest to highest.

     

    public void RestoreValue(CustomPropertyInfo customPropertyInfo, object context, object value)
            {
                myGridView gridView = context as myGridView;

                switch (customPropertyInfo.Name)
                {
                    case "Columns":
                        {                                                                                 //Here
                            List<GridViewColumnProxy> columnProxies = (value as List<GridViewColumnProxy>).OrderBy(x => x.DisplayOrder).ToList();

                            foreach (GridViewColumnProxy proxy in columnProxies)
                            {                           
                                GridViewColumn column = gridView.Columns[proxy.UniqueName];
                                if (column is GridViewDataColumn)
                                {
                                    column.Dispatcher.Invoke(() => 
                                    {
                                        column.DisplayIndex = proxy.DisplayOrder;
                                        column.Header = proxy.Header;
                                        column.Width = proxy.Width;
                                        column.IsVisible = proxy.IsVisible;
                                    });
                                }                            
                            }
                        }
                        break;

    I hope this helps someone else.

  5. Dinko
    Admin
    Dinko avatar
    1165 posts

    Posted 04 Jun 2018 Link to this post

    Hi John,

    I am happy to hear that you manage to found a solution for your scenario. And thank you for sharing your solution with the community.

    Regards,
    Dinko
    Progress Telerik
    Want to extend the target reach of your WPF applications, leveraging iOS, Android, and UWP? Try UI for Xamarin, a suite of polished and feature-rich components for the Xamarin framework, which allow you to write beautiful native mobile apps using a single shared C# codebase.
  6. Hans
    Hans avatar
    67 posts
    Member since:
    Nov 2017

    Posted 15 Nov 2019 Link to this post

    Hi Dinko,

    I did some testing with your sample project and encountered some very strange behavior (same behavior as I'm having in my project).

    I ran the project a few times, saving and loading the grid layout.  At some point, and I really don't have a clue why because I wasn't doing anything special, the 'Load UI' stopped working.  The code in the RadButton_Click_1 method was still executed but the RestoreValue method (in GridViewCustomPropertyProvider) was no longer called.  Strangely enough, when saving the grid layout the ProvideValue method (in GridViewCustomPropertyProvider) was still called.

    The only way I got the loading of the layout working again was by deleting the project and unzip it again.  

    I did the same test a few times, always with the same result.

    Regards,
    Hans

  7. Hans
    Hans avatar
    67 posts
    Member since:
    Nov 2017

    Posted 15 Nov 2019 in reply to Hans Link to this post

    Hi Dinko,

    correction on my previous post: after changing the column order and saving the layout a few times, the loading worked again but to stop working again after changing/saving the layout a few times.

    Regards,
    Hans

  8. Dinko
    Admin
    Dinko avatar
    1165 posts

    Posted 20 Nov 2019 Link to this post

    Hello Hans,

    Thank you for the provided steps. 

    I have double-checked this behavior and after some time of saving and loading, I was able to reproduce it. It turns out that after saving numerous times, the XML in the file got broken. When you save the stream to a file, it overrides the text inside. But in some cases, the newly saved XML will be shorter than the XML inside the file, and there will be leftovers. What you can try is to truncate the XML file on every save. You can set the FileMode enumeration property to Truncate.

    using (FileStream fileStream = new FileStream(File_Name, FileMode.Truncate, FileAccess.ReadWrite))
    {
    	StreamWriter streamWriter = new StreamWriter(fileStream);
    	streamWriter.Write(rawXml);
    	streamWriter.Close();
    	fileStream.Close();
    }

    Using the above code, I wasn't able to reproduce this behavior. Can you give this approach a try and let me know how it goes on your side.

    Regards,
    Dinko
    Progress Telerik

    Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
  9. Hans
    Hans avatar
    67 posts
    Member since:
    Nov 2017

    Posted 25 Nov 2019 in reply to Dinko Link to this post

    Hi Dinko,

    thank's for the tip.  I'm using a somewhat different approach, that also seems to work

    if (File.Exists(fullFileName))
        File.Delete(fullFileName);
     
    PersistenceManager manager = new PersistenceManager();
    Stream stream = manager.Save(this);
     
    using (Stream outputFile = File.OpenWrite(fullFileName))
        stream.CopyTo(outputFile);

     

    As you can see I simply deleting the file before saving.  I haven't test this thoroughly, but first tests are ok.

    Regards,
    Hans

Back to Top