Preserving FlexGrid groups expand/collapse state during refresh

Posted by: tse on 26 November 2019, 11:19 pm EST

    • Post Options:
    • Link

    Posted 26 November 2019, 11:19 pm EST

    When refreshing the content of a grouped Flexgrid we would like to preserve the current expand/collapse state of each group row. The grid component seems to reset all groups to being expanded regardless of their previous state.

    We’ve tried refreshing the grid data at various levels, either by updating the content of the underlying ObservableCollection or by replacing the ItemsSource entirely. No matter what we do, the grid always initializes each group row with IsCollapsed = false.

    We therefore now save the IsCollapsed state of each group row before refreshing the grid and then re-apply it again afterwards. This still doesn’t solve the problem, because the grid is now shortly being rendered with each group row expanded, before we get a chance to apply the correct state, resulting in annoying expand/collapse flickering.

    Is there any way to control the creation of the internal GroupRow instances used by the grid, so that we can apply the correct initial IsCollapsed state when the group row is being created?

  • Posted 28 November 2019, 7:24 pm EST

    Hi,

    By default the FlexGrid sets the GroupRow to expanded whenever rendered. You can store the current state of the GroupRow before refreshing the ItemSource.

    Create a GridCellFactory and override the BindCellContent method of the GridCellFactory. Check is the current cell is the GridGroupRowCell and check for the stored state for the cell. Assign the particular state to the GridGroupRowCell.

      public class CustomCellFactory : GridCellFactory
        {
            public override void BindCellContent(GridCellType cellType, GridCellRange range, View cellContent)
            {
                base.BindCellContent(cellType, range, cellContent);
                if (cellContent.GetType() == typeof(GridGroupRowCell))
                {
                    GridGroupRowCell rowCell = cellContent as GridGroupRowCell;
                  //  rowCell.IsCollapsed = true/False  Based on state stored before ItemSource refreshed
                    cellContent.BackgroundColor = Color.LightBlue;
    
                }
            }
        }
    

    Set the instance of this CustomCellFactory as the CellFactory of FlexGrid.

    grid.CellFactory = new CustomCellFactory();
    

    Please let me know if you feel any difficulty.

    Thanks

  • Posted 2 December 2019, 11:16 pm EST

    Hi,

    We’ve now tried the suggested solution, but the problem is still the same. Even when forcing each row to be collapsed, it seems as if the first group row is always initially being rendered as expanded.

    I have attached a sample solution as well as a video that demonstrates the issue.

    Best regards

    Torsten

    C1GridSample.zip

    C1GridSample_video.zip

  • Posted 4 December 2019, 11:02 pm EST

    Hi Torsten,

    Here is an slight change in the sample that you have provided, in the PopulateGrid method initially set the ItemSource of the Grid as null, then make all the changes in the Collection view and after that set the CollectionView as the ItemSource of the FlexGrid. This will only trigger a single change to the FlexGrid that it needs to render.

                grid.ItemsSource = null;
                var samplePeople = SampleData.GetSamplePeople(100).ToList();
                peopleCollection.Clear();
    
                foreach (var person in samplePeople)
                {
                    peopleCollection.Add(person);
                }
    
                peopleCollectionView = new C1CollectionView<Person>(peopleCollection);
    
                await peopleCollectionView.GroupAsync(p => p.Country);
                await peopleCollectionView.SortAsync(p => p.Country);
                grid.ItemsSource = peopleCollectionView;
    

    Also the part of setting the IsCollapsed property of GroupRow in the CellFactory, we can also do that on the event handler of the RefreshButton.Clicked.

    await PopulateGrid();
                foreach (GridRow row in grid.Rows)
                {
                    if (row is GridGroupRow groupRow)
                    {
                        groupRow.IsCollapsed = true;
                    }
                }
    

    For reference please see the attached ‘SampleGrid’ sample. Please let me know if you face any difficulty.

    Thanks

    SampleGrid.zip

  • Posted 8 December 2019, 7:33 pm EST

    Hi again

    That didn’t solve the problem. We still experience exactly the same behavior. When refreshing the grid, the first group row is first rendered as expanded and then visually collapsed, causing all other rows to animate in place - just like in the sample video that we provided to you.

    Are you experiencing other behavior when running the sample?

    Regards

    Torsten

  • Posted 8 December 2019, 9:48 pm EST

    Hi Torsten,

    The data is refreshed correctly at our end. First is not rendered expanded initially and then collapsed.

    For reference please refer the attached “DataRefresh” video.

    Can you please share your environment details with us? that will help us to assist you better.

    Thanks

  • Posted 9 December 2019, 2:47 am EST

    Hi again

    I don’t see any attached “DataRefresh” video.

    We are experiencing the problem in UWP when building the Sample solution with Visual Studio 2019 16.3.9 running on Windows 10 version 1903.

  • Posted 9 December 2019, 4:19 pm EST

    Hi Torsten,

    Please find the attached “DataRefresh” video.

    Thanks

    DataRefresh.zip

  • Posted 9 December 2019, 6:57 pm EST

    Hi again

    I see from the video that you are running the app on Android. The problem only exists on UWP, so this might explain the confusion.

    That was actually also the reason why the sample solution that I provided did only contain a UWP project :slight_smile:

    Could you please confirm that you can see the issue on UWP?

    Best regards

    Torsten

  • Posted 10 December 2019, 12:44 am EST

    Hi Torsten,

    Thanks for sharing the detail information with us, the issue can be replicated at our end on the UWP platform. We have escalated the case to the concerned team with internal tracking id : 412600. We will update you once we get any information from them.

    Thanks

  • Posted 8 January 2020, 10:22 pm EST

    Hi again

    Any news on this issue?

    Regards

    Torsten

  • Posted 13 January 2020, 10:32 pm EST

    Hi Torsten

    We need to modify the ObservableCollection, but instead of calling Clear and Add, there should be a “diff” logic, which removes the old items, adds the new ones and replaces the modified ones.

    The problem with the Clear and Add algorithm is when the items are cleared, the groups are also cleared, and so happens with the group rows in the grid, when new items are added to the ObservableCollection new groups are created and also new group rows in the grid, and this new groups are expanded by default.

    The natural way to dodge this problem is to avoid clearing all the items and updating the ObservableCollection accordingly. For example when an item needs to be removed, if there are more items in the same group, the group will remain intact, and so the group row in the grid, preserving its collapsing state and executing a “remove” animation. Similarly when adding items to the ObservableCollection, if the group already exist it will just add new row, with the corresponding animation, if the group doesn’t exist 2 new rows will be added. This way the group rows are kept in the grid and there is no need to be saving its collapse state outside of the grid.

    In case of needing new group rows (created by changes in the source) to be collapsed by default, listen to the CollectionChanged event of the Rows

    grid.Rows.CollectionChanged += OnRowsChanged;
    private void OnRowsChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        if(e.Action == NotifyCollectionChangedAction.Add)
        {
            for (int i = 0; i < e.NewItems.Count; i++)
            {
                var groupRow = (sender as GridRowCollection)[e.NewStartingIndex + i] as GridGroupRow;
                if (groupRow != null)
                    groupRow.IsCollapsed = true;
     
            }
        }
    }
    

    For reference please see the attached “SampleGrid” sample.

    Please let me know if it helps.

    ThanksSampleGrid.zip

  • Posted 30 January 2020, 3:12 am EST

    Hi,

    Your suggested solution solves the expand/collapse flickering issue, but introduces several other problems. It seems that the basic grouping of rows no longer works correctly. Try running the sample app that you provided and hit Refresh a few times. You will notice that many items are shown in wrong groups and that the group count displayed in the group row does not match the actual count of items in the group.

    If you reduce the number of random items from 100 to 20, the problems are very visible.

    Please note also, that the original problem of groups momentarily expanding upon refreshing the grid is only present on Windows. On Android there is no such issue. Maybe a solution to the problem should be applied in the UWP renderer?

    Regards

    Torsten

  • Posted 3 February 2020, 1:14 am EST

    Hi

    We are discussing the issue with the developer team, will get back to you as soon as we get any update from them.

    Thanks

  • Posted 8 February 2020, 9:56 pm EST

    Thank you. We are looking forward to hear from you.

  • Posted 13 February 2020, 8:46 am EST

    Could you please give us an estimate on when to expect a solution? Our UWP app is dependent on the functionality and therefore currently out of order.

  • Posted 16 February 2020, 11:38 pm EST

    Hi,

    I’ve requested an update on this issue from the concerned team. We’ll try and get this resolved ASAP.

    I understand the problem that this issue is causing and apologize for the same.

    Regards,

    Ankit

  • Posted 17 February 2020, 3:48 pm EST

    Hi Torsten,

    I’ve an update to share on this. The issue on UWP has been resolved by our dev team and would now undergo QA. The fix would be available in our next major release that’s scheduled for March 2020. Is that okay for you?

    In case, it’s urgent we can have some beta packages made available for you to verify things at your end.

    Regards,

    Ankit

  • Posted 17 February 2020, 10:59 pm EST

    Hi Ankit

    Thank you very much. The March release is soon enough for us to keep our customers happy, so that sounds great :slight_smile:

    If possible, we would very much like to verify the solution using your beta packages.

    Regards,

    Torsten

  • Posted 19 February 2020, 3:13 pm EST

    That’s good to know :slight_smile:

    As for the beta packages, I’ll get back to you on this. Discussing it with the concerned team.

    Regards,

    Ankit

  • Posted 27 February 2020, 4:20 am EST

    Any news on the beta packages?

  • Posted 27 February 2020, 3:34 pm EST

    Yes, the beta package is now available on nuget

    https://www.nuget.org/packages/C1.Xamarin.Forms.Grid/4.4.20201.438-beta

    Just a note for your reference. We’re making some changes w.r.t to the CollectionView branding. This beta FlexGrid makes use of C1DataCollection instead of the C1CollectionView package. Hence you might need to change the references to C1CollectionView in your codebase accordingly.

    More details on this change would be available once we have the official release in March.

    Please let us know in case you face any issues using the beta.

    Regards,

    Ankit

  • Posted 27 February 2020, 7:11 pm EST

    Thanks a lot. We’ll try out the beta version and get back to you.

  • Posted 8 March 2020, 11:33 pm EST

    Hi Ankit,

    Good News! The beta packages solves the flickering issue on UWP :slight_smile:

    But…

    It does require some additional work to make the grid remember and restore the expand/collapse state of group rows. This is mainly because the GridRowCollection.CollectionChanged event is now only fired when the collection changes after the first population of the grid. This means that we cannot initialize each group row as collapsed from the start simply by setting IsCollapsed to true when a new group row is added to the collection.

    Do you have any suggestion as to how we can achieve this?

    Regards

    Torsten

  • Posted 11 March 2020, 1:04 am EST

    Hi Torsten,

    The Grid remembers the previous state of the GroupRow(Collapsed or Expanded) when data is refreshed.

    For example.

    We collapsed the GroupRow with Country “Denmark”,“France” and “Spain” and rest the “Germany” and “Norway” is kept as expanded. When we click on the refresh button data updates on the individual group and the state of the GroupRow(expanded or collapsed) remains the same. Just Whenver any new GroupRow is added that will be collapsed(as specified in CollectionChanged event of Rows of FlexGrid) by default(as FlexGrid does not know the previous state of that Group Row), for reference please see the attached “SampleGridVideo” video also you can test with the attached “SampleGrid” sample.

    Please let me know if you are expecting some other behavior.

    Thanks

    SampleGrid.zipSampleGridVideo.zip

Need extra support?

Upgrade your support plan and get personal unlimited phone support with our customer engagement team

Learn More

Forum Channels