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

Persistence exception

15 Answers 543 Views
PersistenceFramework
This is a migrated thread and some comments may be shown as answers.
Oliver
Top achievements
Rank 1
Oliver asked on 04 Oct 2012, 07:03 PM
Hi,

I'm using VS2008 and Telerik V2012.2.912.35 and I have a proble with the PersistenceFramework. I have a RadWindow with a root control (TabControl with 3 TabItem) and when I launch my application again, in the Loaded event of my RadWindow, I load the RadWindow persistence file previously saved and when I try to click on my second TabItem, I fall in the following exception:

System.ArgumentOutOfRangeException was unhandled by user code
  Message="DisplayIndex out of range! Département\r\nNom du paramètre : displayIndex"
  Source="Telerik.Windows.Controls.GridView"
  ParamName="displayIndex"
  StackTrace:
       à Telerik.Windows.Controls.GridViewColumnCollectionInternal.CheckDisplayIndex(GridViewColumn column, Int32 displayIndex, Boolean isAdding) dans c:\TB\135\WPF_Scrum\Release_WPF\Sources\Development\Controls\GridView\GridView\GridView\Columns\GridViewColumnCollectionInternal.cs:ligne 773
       à Telerik.Windows.Controls.GridViewColumnCollectionInternal.CheckDisplayIndex(GridViewColumn column, Int32 displayIndex) dans c:\TB\135\WPF_Scrum\Release_WPF\Sources\Development\Controls\GridView\GridView\GridView\Columns\GridViewColumnCollectionInternal.cs:ligne 766
       à Telerik.Windows.Controls.GridViewColumnCollectionInternal.InitializeDisplayIndexes() dans c:\TB\135\WPF_Scrum\Release_WPF\Sources\Development\Controls\GridView\GridView\GridView\Columns\GridViewColumnCollectionInternal.cs:ligne 612
       à Telerik.Windows.Controls.GridViewColumnCollectionInternal.get_DisplayIndexes() dans c:\TB\135\WPF_Scrum\Release_WPF\Sources\Development\Controls\GridView\GridView\GridView\Columns\GridViewColumnCollectionInternal.cs:ligne 442
       à Telerik.Windows.Controls.GridViewColumnCollectionInternal.ColumnFromDisplayIndex(Int32 displayIndex) dans c:\TB\135\WPF_Scrum\Release_WPF\Sources\Development\Controls\GridView\GridView\GridView\Columns\GridViewColumnCollectionInternal.cs:ligne 433
       à Telerik.Windows.Controls.GridView.GridViewCellsPanel.InitializeMeasureData() dans c:\TB\135\WPF_Scrum\Release_WPF\Sources\Development\Controls\GridView\GridView\GridView\Virtualization\GridViewCellsPanel.cs:ligne 355
       à Telerik.Windows.Controls.GridView.GridViewCellsPanel.MeasureOverride(Size availableSize) dans c:\TB\135\WPF_Scrum\Release_WPF\Sources\Development\Controls\GridView\GridView\GridView\Virtualization\GridViewCellsPanel.cs:ligne 301
       à System.Windows.FrameworkElement.MeasureCore(Size availableSize)
       à System.Windows.UIElement.Measure(Size availableSize)
       à MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint)
       à System.Windows.Controls.ItemsPresenter.MeasureOverride(Size constraint)
       à System.Windows.FrameworkElement.MeasureCore(Size availableSize)
       à System.Windows.UIElement.Measure(Size availableSize)
       à System.Windows.Controls.Grid.MeasureOverride(Size constraint)
       à System.Windows.FrameworkElement.MeasureCore(Size availableSize)
       à System.Windows.UIElement.Measure(Size availableSize)
       à System.Windows.Controls.Control.MeasureOverride(Size constraint)
       à System.Windows.FrameworkElement.MeasureCore(Size availableSize)
       à System.Windows.UIElement.Measure(Size availableSize)
       à System.Windows.Controls.Grid.MeasureCell(Int32 cell, Boolean forceInfinityV)
       à System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV)
       à System.Windows.Controls.Grid.MeasureOverride(Size constraint)
       à System.Windows.FrameworkElement.MeasureCore(Size availableSize)
       à System.Windows.UIElement.Measure(Size availableSize)
       à System.Windows.Controls.Control.MeasureOverride(Size constraint)
       à Telerik.Windows.Controls.GridView.GridViewRowItem.MeasureOverride(Size constraint) dans c:\TB\135\WPF_Scrum\Release_WPF\Sources\Development\Controls\GridView\GridView\GridView\Rows\GridViewRowItem.cs:ligne 215
       à Telerik.Windows.Controls.GridView.GridViewHeaderRow.MeasureOverride(Size availableSize) dans c:\TB\135\WPF_Scrum\Release_WPF\Sources\Development\Controls\GridView\GridView\GridView\Rows\GridViewHeaderRow.cs:ligne 234
       à System.Windows.FrameworkElement.MeasureCore(Size availableSize)
       à System.Windows.UIElement.Measure(Size availableSize)
       à System.Windows.Controls.Grid.MeasureCell(Int32 cell, Boolean forceInfinityV)
       à System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV)
       à System.Windows.Controls.Grid.MeasureOverride(Size constraint)
       à System.Windows.FrameworkElement.MeasureCore(Size availableSize)
       à System.Windows.UIElement.Measure(Size availableSize)
       à System.Windows.Controls.ScrollViewer.MeasureOverride(Size constraint)
       à Telerik.Windows.Controls.GridView.GridViewScrollViewer.MeasureOverride(Size constraint) dans c:\TB\135\WPF_Scrum\Release_WPF\Sources\Development\Controls\GridView\GridView\GridView\ScrollViewer\GridViewScrollViewer.cs:ligne 180
       à System.Windows.FrameworkElement.MeasureCore(Size availableSize)
       à System.Windows.UIElement.Measure(Size availableSize)
       à System.Windows.Controls.Grid.MeasureCell(Int32 cell, Boolean forceInfinityV)
       à System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV)
       à System.Windows.Controls.Grid.MeasureOverride(Size constraint)
       à System.Windows.FrameworkElement.MeasureCore(Size availableSize)
       à System.Windows.UIElement.Measure(Size availableSize)
       à System.Windows.Controls.Border.MeasureOverride(Size constraint)
       à System.Windows.FrameworkElement.MeasureCore(Size availableSize)
       à System.Windows.UIElement.Measure(Size availableSize)
       à System.Windows.Controls.Control.MeasureOverride(Size constraint)
       à Telerik.Windows.Controls.GridView.GridViewDataControl.MeasureOverride(Size constraint) dans c:\TB\135\WPF_Scrum\Release_WPF\Sources\Development\Controls\GridView\GridView\GridView\GridViewDataControl.cs:ligne 6636
       à System.Windows.FrameworkElement.MeasureCore(Size availableSize)
       à System.Windows.UIElement.Measure(Size availableSize)
       à Telerik.Windows.Controls.RadDockPanel.MeasureOverride(Size availableSize) dans c:\TB\135\WPF_Scrum\Release_WPF\Sources\Development\Core\Controls\Panels\RadDockPanel.cs:ligne 85
       à System.Windows.FrameworkElement.MeasureCore(Size availableSize)
       à System.Windows.UIElement.Measure(Size availableSize)
       à MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint)
       à System.Windows.Controls.ContentPresenter.MeasureOverride(Size constraint)
       à System.Windows.FrameworkElement.MeasureCore(Size availableSize)
       à System.Windows.UIElement.Measure(Size availableSize)
       à System.Windows.Controls.Grid.MeasureCell(Int32 cell, Boolean forceInfinityV)
       à System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV)
       à System.Windows.Controls.Grid.MeasureOverride(Size constraint)
       à System.Windows.FrameworkElement.MeasureCore(Size availableSize)
       à System.Windows.UIElement.Measure(Size availableSize)
       à System.Windows.Controls.Control.MeasureOverride(Size constraint)
       à System.Windows.FrameworkElement.MeasureCore(Size availableSize)
       à System.Windows.UIElement.Measure(Size availableSize)
       à Telerik.Windows.Controls.RadDockPanel.MeasureOverride(Size availableSize) dans c:\TB\135\WPF_Scrum\Release_WPF\Sources\Development\Core\Controls\Panels\RadDockPanel.cs:ligne 85
       à System.Windows.FrameworkElement.MeasureCore(Size availableSize)
       à System.Windows.UIElement.Measure(Size availableSize)
       à MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint)
       à System.Windows.Controls.ContentPresenter.MeasureOverride(Size constraint)
       à System.Windows.FrameworkElement.MeasureCore(Size availableSize)
       à System.Windows.UIElement.Measure(Size availableSize)
       à System.Windows.ContextLayoutManager.UpdateLayout()
       à System.Windows.ContextLayoutManager.UpdateLayoutCallback(Object arg)
       à System.Windows.Media.MediaContext.InvokeOnRenderCallback.DoWork()
       à System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks()
       à System.Windows.Media.MediaContext.RenderMessageHandlerCore(Object resizedCompositionTarget)
       à System.Windows.Media.MediaContext.RenderMessageHandler(Object resizedCompositionTarget)
       à System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Boolean isSingleParameter)
       à System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler)
       à System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler)
       à System.Windows.Threading.DispatcherOperation.InvokeImpl()
       à System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
       à System.Threading.ExecutionContext.runTryCode(Object userData)
       à System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
       à System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
       à System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       à System.Windows.Threading.DispatcherOperation.Invoke()
       à System.Windows.Threading.Dispatcher.ProcessQueue()
       à System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
       à MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
       à MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
       à System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Boolean isSingleParameter)
       à System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler)
       à System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler)
       à System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Boolean isSingleParameter)
       à System.Windows.Threading.Dispatcher.Invoke(DispatcherPriority priority, Delegate method, Object arg)
       à MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
       à MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
       à System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
       à System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
       à System.Windows.Window.ShowHelper(Object booleanBox)
       à System.Windows.Window.Show()
       à System.Windows.Window.ShowDialog()
  InnerException:

Thank's

15 Answers, 1 is accepted

Sort by
0
Tina Stancheva
Telerik team
answered on 09 Oct 2012, 02:07 PM
Hi Oliver,

This exception indicates that the RadGridView isn't fully initialized when you try to load its settings. And as at this point all Columns.DisplayIndex is -1, the persistence logic causes this exception to be thrown. This is why you can try to load the RadGridView settings in its Loaded event handler in a Dispatcher.

You can take a look at the solution attached at the end of this thread as it demonstrates how to load the RadGridView settings after it is loaded.

Regards,
Tina Stancheva
the Telerik team

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

0
Oliver
Top achievements
Rank 1
answered on 09 Oct 2012, 03:08 PM
Hi Tina,

nothing was attached with your response :

Actually in my application, I have to RadGridView in two separate TabItem. Of course when mu user load my application, it's not systematic that he have to go in both TabItem!!!

Thank's
0
Zarko
Telerik team
answered on 12 Oct 2012, 08:34 AM
Hello Oliver,
I'm sorry on behave of my colleague for the missing file attachment. Unfortunately I wasn't able to reproduce your issue so I'd like to ask you for some more code snippets or a sample project. You could also try to load your persisted settings a little bit later (as Tina have suggested) with something like this:
private void OnGridViewLoaded(object sender, RoutedEventArgs e)
{
    this.Dispatcher.BeginInvoke(new Action(() =>
    {
        IsolatedStorageProvider isoProvider = new IsolatedStorageProvider();
        isoProvider.LoadFromStorage();
    }));
}
I've attached a sample project with RadWindow, TabControl and GridViews so could you please examine it and see if it helps you?
We're looking forward to hearing from you.

Regards,
Zarko
the Telerik team

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

0
Oliver
Top achievements
Rank 1
answered on 12 Oct 2012, 01:31 PM
Hi Zarko,

I can't attached a demo from here so I include all the code of my unit.

It's verry easy to reproduce... In my RadWindow I have a RadTabConrol with 2 RadTabItem, each RadTabItem contain  a RadGridView. In the Loaded event of my RadWindow, I load the persistence of my RadWindow and in the PreviewClosed event I save the persistence of my RadWindow.

When the RadWindow is loaded, don't click on the RadTabItem #2, just close the RadWindow. Load the RadWindow again and noew click on the RadTabItem #2, bang, the application crash...

Thank's

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

using Telerik.Windows.Controls;
using Telerik.Windows.Controls.GridView;
using Telerik.Windows.Data;
using Telerik.Windows.Persistence;
using Telerik.Windows.Persistence.Services;
using Telerik.Windows.Persistence.Storage;

namespace RadControlsWpfApp_Persistence
{
    /// <summary>
    /// Interaction logic for Window2.xaml
    /// </summary>
    public partial class Window2 : RadWindow
    {
        public Window2()
        {
            InitializeComponent();
        }

        private void RadWindow_Loaded(object sender, RoutedEventArgs e)
        {
            WindowState = WindowState.Maximized;

            PersistenceManager.SetStorageId(this, "RadWindow2");
            Persist(PersistenceAction.Load);
            this.ClearValue(PersistenceManager.StorageIdProperty);
        }

        private void RadWindow_PreviewClosed(object sender, Telerik.Windows.Controls.WindowPreviewClosedEventArgs e)
        {
            PersistenceManager.SetStorageId(this, "RadWindow2");
            Persist(PersistenceAction.Save);
            this.ClearValue(PersistenceManager.StorageIdProperty);
        }

        private void Persist(PersistenceAction pPersistenceAction)
        {
            ServiceProvider.RegisterPersistenceProvider<ICustomPropertyProvider>(typeof(RadGridView), new GridViewCustomPropertyProvider());

            PersistenceManager manager = new PersistenceManager();           
            IsolatedStorageProvider storage = new IsolatedStorageProvider(manager);

            try
            {
                try
                {
                    if (pPersistenceAction == PersistenceAction.Load)
                    {
                            storage.LoadFromStorage(); // TODO CHECK
                    }
                    else if (pPersistenceAction == PersistenceAction.Save)
                    {
                            storage.SaveToStorage(); // TODO CHECK
                    }
                }
                catch (Exception ex)
                {
                }
            }
            finally
            {               
                ServiceProvider.UnregisterPersistenceProvider<ICustomPropertyProvider>(typeof(RadGridView));
            }
        }

        public enum PersistenceAction { Load, Save }
    }

    public class GridViewCustomPropertyProvider : ICustomPropertyProvider
    {
        public CustomPropertyInfo[] GetCustomProperties()
        {
            // Create three custom properties to persist the Columns, Sorting and Group descriptors using proxy objects
            return new CustomPropertyInfo[]
            {
                new CustomPropertyInfo("Columns", typeof(List<ColumnProxy>)),
                new CustomPropertyInfo("SortDescriptors", typeof(List<SortDescriptorProxy>)),
                new CustomPropertyInfo("FilterDescriptors", typeof(List<FilterSetting>)),
                new CustomPropertyInfo("GroupDescriptors", typeof(List<GroupDescriptorProxy>)),
            };
        }

        public void InitializeObject(object context)
        {
            if (context is RadGridView)
            {
                RadGridView gridView = context as RadGridView;
                gridView.SortDescriptors.Clear();
                gridView.GroupDescriptors.Clear();
                gridView.FilterDescriptors.Clear();
            }
        }

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

        public object ProvideValue(CustomPropertyInfo customPropertyInfo, object context)
        {
            RadGridView gridView = context as RadGridView;
            if (customPropertyInfo.Name == "Columns")
            {
                // create proxies for all of the columns and save only specific properties
                List<ColumnProxy> proxies = new List<ColumnProxy>();
                foreach (Telerik.Windows.Controls.GridViewColumn column in gridView.Columns)
                {
                    proxies.Add(new ColumnProxy()
                    {
                        UniqueName = column.UniqueName,
                        Header = column.Header.ToString(),
                        DisplayOrder = column.DisplayIndex,
                        Width = column.Width,
                    });
                }
                return proxies;
            }
            else if (customPropertyInfo.Name == "SortDescriptors")
            {
                // create proxies for all of the sort descriptors and save only specific properties
                List<SortDescriptorProxy> proxies = new List<SortDescriptorProxy>();
                foreach (ColumnSortDescriptor descriptor in gridView.SortDescriptors)
                {
                    proxies.Add(new SortDescriptorProxy()
                    {
                        ColumnUniqueName = descriptor.Column.UniqueName,
                        SortDirection = descriptor.SortDirection,
                    });
                }
                return proxies;
            }
            else if (customPropertyInfo.Name == "GroupDescriptors")
            {
                // create proxies for all of the group descriptors and save only specific properties
                List<GroupDescriptorProxy> proxies = new List<GroupDescriptorProxy>();
                foreach (ColumnGroupDescriptor descriotor in gridView.GroupDescriptors)
                {
                    proxies.Add(new GroupDescriptorProxy()
                    {
                        ColumnUniqueName = descriotor.Column.UniqueName,
                        SortDirection = descriotor.SortDirection,
                    });
                }
                return proxies;
            }
            else if (customPropertyInfo.Name == "FilterDescriptors")
            {
                List<FilterSetting> settings = new List<FilterSetting>();

                foreach (GridViewDataColumn column in gridView.Columns
                    .OfType<GridViewDataColumn>()
                    .Where(column => column.ColumnFilterDescriptor.IsActive))
                {
                    FilterSetting setting = new FilterSetting();

                    setting.ColumnUniqueName = column.UniqueName;

                    if (column.ColumnFilterDescriptor.FieldFilter.Filter1.IsActive)
                    {
                        setting.Filter1 = new FilterDescriptorProxy();
                        setting.Filter1.Operator = column.ColumnFilterDescriptor.FieldFilter.Filter1.Operator;
                        setting.Filter1.Value = column.ColumnFilterDescriptor.FieldFilter.Filter1.Value;
                        setting.Filter1.IsCaseSensitive = column.ColumnFilterDescriptor.FieldFilter.Filter1.IsCaseSensitive;
                    }

                    if (column.ColumnFilterDescriptor.FieldFilter.Filter2.IsActive)
                    {
                        setting.Filter2 = new FilterDescriptorProxy();
                        setting.Filter2.Operator = column.ColumnFilterDescriptor.FieldFilter.Filter2.Operator;
                        setting.Filter2.Value = column.ColumnFilterDescriptor.FieldFilter.Filter2.Value;
                        setting.Filter2.IsCaseSensitive = column.ColumnFilterDescriptor.FieldFilter.Filter2.IsCaseSensitive;
                    }

                    foreach (object distinctValue in column.ColumnFilterDescriptor.DistinctFilter.DistinctValues)
                    {
                        setting.SelectedDistinctValues.Add(distinctValue);
                    }

                    settings.Add(setting);
                }

                return settings;
            }

            return null;
        }

        public void RestoreValue(CustomPropertyInfo customPropertyInfo, object context, object value)
        {
            RadGridView gridView = context as RadGridView;
            if (customPropertyInfo.Name == "Columns")
            {
                List<ColumnProxy> savedProxies = value as List<ColumnProxy>;

                // restore properties on the saved columns:
                foreach (ColumnProxy proxy in savedProxies)
                {
                    Telerik.Windows.Controls.GridViewColumn column = this.GetColumnInstance(gridView, proxy.UniqueName);
                    if (column != null)
                    {
                        column.DisplayIndex = proxy.DisplayOrder;
                        column.Header = proxy.Header;
                        column.Width = proxy.Width;
                    }
                }
            }
            else if (customPropertyInfo.Name == "SortDescriptors")
            {
                gridView.SortDescriptors.Clear();
                List<SortDescriptorProxy> savedProxies = value as List<SortDescriptorProxy>;

                // restore properties on the saved sort descriptors:
                foreach (SortDescriptorProxy proxy in savedProxies)
                {
                    Telerik.Windows.Controls.GridViewColumn column = this.GetColumnInstance(gridView, proxy.ColumnUniqueName);
                    gridView.SortDescriptors.Add(new ColumnSortDescriptor() { Column = column, SortDirection = proxy.SortDirection });
                }
            }
            else if (customPropertyInfo.Name == "GroupDescriptors")
            {
                gridView.GroupDescriptors.Clear();
                List<GroupDescriptorProxy> savedProxies = value as List<GroupDescriptorProxy>;

                // restore properties on the saved group descriptors:
                foreach (GroupDescriptorProxy proxy in savedProxies)
                {
                    Telerik.Windows.Controls.GridViewColumn column = this.GetColumnInstance(gridView, proxy.ColumnUniqueName);
                    gridView.GroupDescriptors.Add(new ColumnGroupDescriptor() { Column = column, SortDirection = proxy.SortDirection });
                }
            }
            else if (customPropertyInfo.Name == "FilterDescriptors")
            {
                gridView.FilterDescriptors.SuspendNotifications();

                foreach (var c in gridView.Columns)
                {
                    if (c.ColumnFilterDescriptor.IsActive)
                    {
                        c.ClearFilters();
                    }
                }

                List<FilterSetting> settings = value as List<FilterSetting>;

                foreach (FilterSetting setting in settings)
                {
                    Telerik.Windows.Controls.GridViewDataColumn column = gridView.Columns
                        .OfType<Telerik.Windows.Controls.GridViewDataColumn>()
                        .Single(c => c.UniqueName == setting.ColumnUniqueName);

                    if (column != null)
                    {
                        IColumnFilterDescriptor cfd = column.ColumnFilterDescriptor;

                        if (setting.Filter1 != null)
                        {
                            cfd.FieldFilter.Filter1.Operator = setting.Filter1.Operator;
                            cfd.FieldFilter.Filter1.Value = setting.Filter1.Value;
                            cfd.FieldFilter.Filter1.IsCaseSensitive = setting.Filter1.IsCaseSensitive;
                        }

                        if (setting.Filter2 != null)
                        {
                            cfd.FieldFilter.Filter2.Operator = setting.Filter2.Operator;
                            cfd.FieldFilter.Filter2.Value = setting.Filter2.Value;
                            cfd.FieldFilter.Filter2.IsCaseSensitive = setting.Filter2.IsCaseSensitive;
                        }

                        foreach (object distinctValue in setting.SelectedDistinctValues)
                        {
                            cfd.DistinctFilter.AddDistinctValue(distinctValue);
                        }
                    }
                }

                gridView.FilterDescriptors.ResumeNotifications();
            }
        }

        private Telerik.Windows.Controls.GridViewColumn GetColumnInstance(RadGridView gridView, string uniqueName)
        {
            foreach (Telerik.Windows.Controls.GridViewColumn column in gridView.Columns)
            {
                if (column.UniqueName == uniqueName)
                    return column;
            }
            return null;
        }

    }

    public class ColumnProxy
    {
        public string UniqueName { get; set; }
        public int DisplayOrder { get; set; }
        public string Header { get; set; }
        public GridViewLength Width { get; set; }
    }

    public class SortDescriptorProxy
    {
        public string ColumnUniqueName { get; set; }
        public ListSortDirection SortDirection { get; set; }
    }

    public class GroupDescriptorProxy
    {
        public string ColumnUniqueName { get; set; }
        public ListSortDirection? SortDirection { get; set; }
    }

    public class FilterDescriptorProxy
    {
        public FilterOperator Operator { get; set; }
        public object Value { get; set; }
        public bool IsCaseSensitive { get; set; }
    }

    public class FilterSetting
    {
        public string ColumnUniqueName { get; set; }

        List<object> _SelectedDistinctValues;

        public List<object> SelectedDistinctValues
        {
            get
            {
                if (_SelectedDistinctValues == null)
                {
                    _SelectedDistinctValues = new List<object>();
                }
                return _SelectedDistinctValues;
            }
        }

        FilterDescriptorProxy _Filter1;
        public FilterDescriptorProxy Filter1
        {
            get
            {
                return _Filter1;
            }
            set
            {
                _Filter1 = value;
            }
        }

        FilterDescriptorProxy _Filter2;
        public FilterDescriptorProxy Filter2
        {
            get
            {
                return _Filter2;
            }
            set
            {
                _Filter2 = value;
            }
        }
    }

}

0
Tina Stancheva
Telerik team
answered on 17 Oct 2012, 08:01 AM
Hi Oliver,

I used your code to create a sample solution to reproduce the issue but to no avail.

In any case, you need to keep in mind that the RadGridView has to be fully initialized before the PersistenceManager can load its saved settings. And as the controls is complex and it takes time to fully generate its columns and data, we usually recommend loading its persisted data in the RadGridView.Loaded event handler in a Dispatcher.

And in your scenario, you've also placed the RadGridView controls in different RadTabItems. However, the RadTabControl only initializes the content of the TabItems once they are selected and if the IsContentPreserved property isn't set to True, the control will remove the RadGridView in an unselected tab from the visual tree of the application each time the selection is changed. These add/remove operations that the RadTabControl implements in the visual tree lead to new initialization operations for the RadGridView controls - and again you need to be sure that the RadGridView columns and data has fully loaded before using the PersistenceManager to load the persisted settings.

Due to the above complications, in scenarios where the RadGridView is persisted, we usually recommend persisting it on its own, apart from the RadWindow persisting logic. This means that you'll have to exclude the content of the RadTabItems from being persisted (you can use the PersistenceManager.SerializationOptions) and then create custom logic to save and specifically load the RadGridView settings once the control is ready to be restored.

If you can modify my solution to better demonstrate your case and approach, we will be able to take a closer look at it and suggest another approach for implementing your requirements.

Regards,
Tina Stancheva
the Telerik team

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

0
Greg
Top achievements
Rank 2
answered on 11 Dec 2012, 11:25 PM
I've looked at the example projects and do not see the code to save/load RadGridViews only when the RadGridView is loaded. I too have RadGridViews on multiple RadTabItems and have occasional crashes with "DisplayIndex out of range" exceptions.
0
Zarko
Telerik team
answered on 14 Dec 2012, 02:24 PM
Hi Greg,
You can find the code for saving the GridView on the MainWindow_PreviewClosed and MainWindow_Loaded event handlers:
void MainWindow_PreviewClosed(object sender, WindowPreviewClosedEventArgs e)
{
    PersistenceManager.SetStorageId(this, "RadWindow2");
    Persist(PersistenceAction.Save);
    this.ClearValue(PersistenceManager.StorageIdProperty);
}
 
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
    WindowState = WindowState.Maximized;
    PersistenceManager.SetStorageId(this, "RadWindow2");
    Persist(PersistenceAction.Load);
    this.ClearValue(PersistenceManager.StorageIdProperty);
}
in Tina's project or in MyRadWindowLoaded and OnSave:
private void MyRadWindowLoaded(object sender, RoutedEventArgs e)
{
    IsolatedStorageProvider isoProvider = new IsolatedStorageProvider();
    isoProvider.LoadFromStorage();
}
 
private void OnSave(object sender, System.Windows.RoutedEventArgs e)
{
    IsolatedStorageProvider isoProvider = new IsolatedStorageProvider();
    isoProvider.SaveToStorage();
}
in my previous project. As for your exception - it seems that you're trying to set a DisplayIndex that is bigger than the columns count so you may want to add some validation for this.
If you still have problems with your GridView and the persistence framework I'd like to ask you to open a support thread and send us a sample project or at lease some code snippets.
We're looking forward to hearing from you.

All the best,
Zarko
the Telerik team

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

0
Matt
Top achievements
Rank 2
answered on 04 Jan 2013, 04:04 PM
This may be late to the table, but we experienced saved column indexes that were -1. I'm not completely sure how becuase this is not reproducable at will but did to more than one person in development at various discreet times. I belive it has to do with hidden windows, typically with tabbed pages which is what the person decribes and what we use, and how initialization is handled within the hidden tab windows and those not fully resolved settings are then saved.

I've removed the code block, since this was not the issue and it had major issues. Our issue was that we were recreating the columns at runtime based on another column source, whenever that column source was editied; but never setting the display index during the creation. When the grid is on a tab that is not visible and this is done, the columns are never displayed and never achieve their index and stayed -1. If the grid tab was shown, the column indexes were updated and everything worked fine. If not, we saved out -1 for the DisplayIndex as part of the persistance call for that data. The code that I originally posted was actually really bad in that could further corrupt the display index range and push it beyond the maximum column index generating a different exception. My apologies!

0
Tina Stancheva
Telerik team
answered on 09 Jan 2013, 01:04 PM
Hi Matt,

The DisplayIndex of a column is -1 when the column is not fully generated. With the PersistenceFramework this may cause exceptions when the RadGridView persisted settings are loaded too early before the control has fully initialized its components.

This is why we usually recommend our customers to call the Load() method of the PersistenceFramework only after they make sure that the RadGridView control has fully loaded. For example, you can load the saved settings in the RadGridView.Loaded event handler in a Dispatcher. This will make sure that all columns are initialized and loaded on the screen and their DisplayIndexes are properly updated.

Regards,
Tina Stancheva
the Telerik team

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

0
Matt
Top achievements
Rank 2
answered on 30 Jan 2013, 08:57 PM
You keep mentioning when we load the settings, and that's not the issue. The problem is that the docked window that contains the control is created but never initialized (brought into view) since its tab is never shown. Your grid control leaves the column's display index as -1 until viewied despite saying that it's loaded. It's the save operation that is saving the -1 which is being pulled from the created but never viewed control. The window is created and the controls are never initilaiized since they are never brought into view. In this case, all created columns have a -1 as their default value unless I manually provide one for them, and that's what's being saved out. I have a test project that I just created that shows a simple example of this behavior. For some reason it won't let me attach it to this reply. I have attached pictures of the screens as it loads.

The first is page 2 grid control firing the loaded event; for what you keep saying we need to wait.
The second is showing that Page 1 is visible but page 2 is never selected (tab content is never made visible, only page 1 content is seen) or shown despite the grid saying that it was loaded.
The third image is clicking the button that goes through the columns of the grid on page 2. All columns have a display index of -1. If I view the page 2 grid first and then click the button, there is not report of bad display indexes.

SO, if someone tries to save the application with the persistance framework you provide, they will save the -1 unless the programmer prevents this or the user clicks on the page 2 tab prior to initiating the save. It's just something the developed needs to understand; a loaded control is not always initialized. I don't think this is a bug, but maybe you can clarify.

If there is a place to attach or send the sample project, let me know and I'll send it up.

We got around this by forcing the display index to a valid value.
0
Matt
Top achievements
Rank 2
answered on 31 Jan 2013, 12:24 PM
When I mention that load is not the issue, you have to consider the first time case for my sample window. There are no persisted settings to load. A save from that state saves the -1 DisplayIndexes unless the user happened to click on the page 2 tab to show and initialize the page 2 grid. This is not a consistent thing, so it appears to be a happenstance control bug. It's really a combination of order of user action and developer initialization/state bug and something developers need to code against.

I can only assume that the control is purposefully not initilizing the columns until the window is activated for the first time to conserve in the performance arena; which makes sense. Developers just need to understand that better and code appropriately. 
0
Tina Stancheva
Telerik team
answered on 04 Feb 2013, 01:15 PM
Hello Matt,

Thank you for getting back to us. Now I can better understand your scenario and you're right that the RadGridView control hosted in an unselected tab won't be properly loaded after a persisting operation. The issue is caused by the RadTabControl default behavior.

I can see that in your case, you've placed your RadGridView controls inside a RadDocking control. But the RadPaneGroup derives from the RadTabControl, which is designed to use lazy loading when loading the content of its items. This means that the content of a RadTabItem/RadPane is only added in the visual tree of the application after the tab is selected (by default the RadTabControl/RadPaneGroup will add all items and their content in the logical tree as soon as the control loads, but will wait for a selection change to add the items in the visual tree).

This is why the RadGridView control that is hosted in a never selected tab/pane, isn't added in the visual tree and therefore it cannot apply any DisplayIndex settings to its columns so their values are -1 by default.

This is truly something the developers need to consider when persisting such a layout. And in order to workaround it, you can either follow your approach and define default values or you can make sure that the RadPerisistenceFramework can't load a RadGridView that isn't loaded in the visual tree of the application. You can implement such a logic in the CustomPropertyProvider that you setup for the RadGridView persistence - you can modify the ProvideValue method as follows:
        public object ProvideValue(CustomPropertyInfo customPropertyInfo, object context)
        {
            RadGridView gridView = context as RadGridView;
            if (gridView.ItemContainerGenerator.Status != System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated)
            {
                if (customPropertyInfo.Name == "Columns")
                    return new List<ColumnProxy>();
                else if (customPropertyInfo.Name == "SortDescriptors")
                    return new List<SortDescriptorProxy>();
                else if (customPropertyInfo.Name == "GroupDescriptors")
                    return new List<GroupDescriptorProxy>();
                else if (customPropertyInfo.Name == "FilterDescriptors")
                    return new List<FilterSetting>();
            }
 ...
}

I hope this information helps in better understanding the reasons behind the issue. However, if I'm still missing something from your scenario, you can open a new support ticket and attach your sample solution in it. Then we will be able to take a closer look at your case.

Regards,
Tina Stancheva
the Telerik team

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

0
Matt
Top achievements
Rank 2
answered on 04 Feb 2013, 01:20 PM
Getting the specifics for checking control state is very helpful. Thanks for responding. It's probably better to just not save anything if the control was never initialized.

Thanks again. Have a great day.
0
Greg
Top achievements
Rank 2
answered on 04 Feb 2013, 07:54 PM
I am not able to implement the fix as indicated. I am using version 2012.3.1129.40 and in it radGridView.ItemContainerGenerator is of type IContainerGenerator (not GridviewItemContainerGenerator) and does not expose the Status property. Doesn't help to cast as the GridviewItemContainerGenerator, Status property in now private. It It's frustrating to finally see an apparent fix to this long standing problem only to not be able to implement it.
0
Tina Stancheva
Telerik team
answered on 07 Feb 2013, 03:12 PM
Hello Greg,

Yes, you're right. With the latest version of the RadGridView, it is better to use another approach. Instead of getting the status of the containers generations, you can simply restore only those columns that have a proper DisplayIndex value:
public object ProvideValue(CustomPropertyInfo customPropertyInfo, object context)
{
    RadGridView gridView = context as RadGridView;
        switch (customPropertyInfo.Name)
        {
            case "Columns":
                {
                    List<ColumnProxy> columnProxies = new List<ColumnProxy>();
 
                    foreach (GridViewColumn column in gridView.Columns.OfType<GridViewColumn>().Where(c => c.DisplayIndex > 0))
                    {
                        columnProxies.Add(new ColumnProxy()
                        {
                            ...
                        });
                    }
 
                    return columnProxies;
                }
               ...
        }
     ...
}

Please give this approach a try and let me know if it works for you.

Kind regards,
Tina Stancheva
the Telerik team

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

Tags
PersistenceFramework
Asked by
Oliver
Top achievements
Rank 1
Answers by
Tina Stancheva
Telerik team
Oliver
Top achievements
Rank 1
Zarko
Telerik team
Greg
Top achievements
Rank 2
Matt
Top achievements
Rank 2
Share this question
or