This is a migrated thread and some comments may be shown as answers.

Reordering columns issue once again

8 Answers 407 Views
PersistenceFramework
This is a migrated thread and some comments may be shown as answers.
Erik
Top achievements
Rank 1
Erik asked on 25 Apr 2016, 03:39 PM

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

8 Answers, 1 is accepted

Sort by
0
Erik
Top achievements
Rank 1
answered on 26 Apr 2016, 10:31 AM
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.
0
Kiril Vandov
Telerik team
answered on 28 Apr 2016, 07:59 AM
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.
0
John
Top achievements
Rank 1
answered on 31 May 2018, 01:37 PM

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.

0
Dinko | Tech Support Engineer
Telerik team
answered on 04 Jun 2018, 12:56 PM
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.
0
Hans
Top achievements
Rank 1
Veteran
answered on 15 Nov 2019, 10:40 AM

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

0
Hans
Top achievements
Rank 1
Veteran
answered on 15 Nov 2019, 11:12 AM

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

0
Dinko | Tech Support Engineer
Telerik team
answered on 20 Nov 2019, 09:31 AM

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.
0
Hans
Top achievements
Rank 1
Veteran
answered on 25 Nov 2019, 03:25 PM

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

Tags
PersistenceFramework
Asked by
Erik
Top achievements
Rank 1
Answers by
Erik
Top achievements
Rank 1
Kiril Vandov
Telerik team
John
Top achievements
Rank 1
Dinko | Tech Support Engineer
Telerik team
Hans
Top achievements
Rank 1
Veteran
Share this question
or