C1FlexGrid: improved "AutoSizeRows" for merged ranges

Posted by: wknauf on 4 November 2020, 4:52 am EST

    • Post Options:
    • Link

    Posted 4 November 2020, 4:52 am EST - Updated 3 October 2022, 11:14 pm EST

    Hi,

    I noticed that “AutoSizeRows” might result in “not so nice looking” results if merged ranges with long texts are involved.

    Attached is a sample which has a cell merged over three rows with very long text.

    When calling “AutoSizeRows”, all rows of this range get the same height, which looks bad for rows 1 and 2 of the range, as the content of the other cols of those rows is smaller, and thus the rows could have a smaller height:

    So I tried to improve it: all rows get only the required height, and the last row of each merged range gets the remaining height and will be much larger. Result is this:

    But this is very clumsy and inperformant code, as I make a lot of calls to “AutoSizeRows” with “AutoSizeFlags.IgnoreMerged”. And this code will fail if there are overlapping merged ranges which start in different rows. I think I could fix this problem if there was any method in C1FlexGrid to calculate the height of a cell range (or a merged range). Could you add this? This code probably exists as part of “AutoSizeRows”, so hopefully you could extract part of this code and make it public API.

    Bonus problem: is it a feature or a bug that “AutoSizeRows” for a custom merged range will only work if all cells of the merged range contain the same text and the same “word wrap” style? I think the top left cell of a merged range defines rendered content, so it should also define the “AutoSizeRow” result.

    FlexAutoSizeRow.zip

    Best regards

    Wolfgang

  • Posted 5 November 2020, 7:54 am EST

    Hi Wolfgang,

    We are discussing this with the developers and will get back to the updates soon.

    [Internal Tracking ID: 23851]

    Regards,

    Prabhat Sharma.

  • Posted 5 November 2020, 8:49 am EST

    Hi Prabhat,

    I had an idea on how to fix the issue with overlapping ranges in my own sample: instead of calling “AutoSizeRows” for the whole grid to get the height of all merged ranges, I could call call “AutoSizeRows (toprow, leftcol, bottomrow, rightcol)” for each merged range and thus get the height for just this range. This should resolve the problem with ranges whoses rows overlap (though they are in different cols).

    But the main issue is still “how can I measure the ranges without having to use AutoSizeRows?”.

    Best regards

    Wolfgang

  • Posted 5 November 2020, 10:04 pm EST

    Hi Wolfgang,

    Thank you for the additional information.

    We will let you know once we get an update from the developer.

    Regards,

    Prabhat

  • Posted 11 February 2021, 7:01 am EST

    Hi,

    any update from the developers? Are there plans to implement this?

    Best regards

    Wolfgang

  • Posted 11 February 2021, 10:36 pm EST

    Hello,

    We are getting in touch with the developers for the updates and will let you know soon.

    Regards,

    Prabhat Sharma.

  • Posted 8 March 2021, 9:33 am EST

    Hi Prabhat,

    any feedback from the developers?

    Best regards

    Wolfgang

  • Posted 10 March 2021, 7:41 am EST

    Hello,

    Our developers are working on this issue and we will let you know the updates soon.

    Regards,

    Prabhat Sharma.

  • Posted 28 April 2021, 6:27 am EST

    Hi,

    The developers have shared the workaround sample “Workaround.zip”. They implemented another way to do what you want. Its clearer, has more performance, and also handled overlapping merged ranges correctly.

    For the Bonus problem: the developers need some screenshots with the explanation of the issue.

    Regards,

    Prabhat Sharma.

    Workaround.zip

  • Posted 30 April 2021, 2:25 am EST - Updated 3 October 2022, 11:14 pm EST

    Hi Pabhat,

    this sounds promising, but the “Workaround” sample has one bug: the cell in the screenshot is clipped:

    Also, I fear that using your workaround suggestion causes performance issues, because AutoSizeRows is called twice for merged ranges. And in our application, the grid where I would like to see this improved “AutoSize” logic, has merged ranges for most rows and it will contain a lot of rows. Here, performance is critical. So I hope that you can add it to C1FlexGrid, where you probably have a better control for performance and could measure cell texts only once.

    Also, the workaround currently only works for “AllowMergingEnum.Custom”, but in our real grid, we use “AllowMergingFixed = Free”. OK, it would be possible to change our grid.

    About the bonus problem: attached sample shows it: I removed most of the filling code, so that only one large merged range remains. Click the “AutoSizeRows” button => text will be clipped.

    It works if I set text and style with “WordWrap” to all cells of the range.

    BonusProblem.zip

    Screenshot:

    Best regards

    Wolfgang

  • Posted 3 May 2021, 5:54 am EST

    Hello Wolfgang,

    Thank you for the detailed explanation, we have forwarded your comments to the development team and will let you know as soon as we get the update from their end.

    Regards,

    Prabhat Sharma.

  • Posted 5 May 2021, 9:09 am EST

    Hi,

    Please find the developer’s comment on the issue:

    The “Workaround” sample has one bug: the cell in the screenshot is clipped. issue1.png

    Text and style for c1FlexGrid1[4, 1] was not set. I didn’t set it by accident.

    this.c1FlexGrid1[4, 1] = shortmerged;
    this.c1FlexGrid1.SetCellStyle(4,1, styleWrap);
    

    will fix the bug. And this is just an example of a bonus problem. And about it: the style and text are involved in the calculation of the height of the range, even for merged cells. So this is not a bug, this is how it works now.

    About performance: I think that this is a fairly productive solution. Since the second autosize call only applies to a small merged range. But since it applies to all ranges, in the worst case, the performance will be 2 times lower than calling the AutoSizeRows method (for all cells) 1 time. I don’t think that what you need, can be done in the one loop with the current behavior.

    You can always work on performance and gradually improve it, but you need to do this after the desired behavior is achieved.

    We can not embed a behavior that you need in the grid. But we can add some public API that can help you. You wrote that calculating the height of the range can help you. Is this still relevant?

    Regards,

    Prabhat Sharma.

  • Posted 6 May 2021, 2:03 am EST

    Yes, this would be very helpful. Probably, a methode “GetCellSize” or “MeasureCellSize” for a single cell would be sufficient, as I would have to call this only for the top left cell of each merged range.

    Thus, I could even avoid the duplicate size calculation if I do the “AutoSize” calculation for the whole grid myself.

    I am looking forward to the new method :wink:

    The “bonus problem” is OK for me, though I think it is confusing to require the full merged range to have the same content.

    Best regards

    Wolfgang

  • Posted 6 May 2021, 7:19 am EST

    Hello Wolfgang,

    Thank you for your comments, we have forwarded your comments to the development team and will let you know as soon as we get the update from their end.

    Regards,

    Prabhat Sharma.

  • Posted 16 January 2024, 11:04 am EST

    Any updates on this?

    Best regards

    Wolfgang

  • Posted 17 January 2024, 7:41 am EST

    Hello,

    We apologize for the delay in response.

    The MeasureCellSize method has been added into the FlexGrid API as per your request.

    https://developer.mescius.com/componentone/docs/win/online-flexgrid/C1.Win.C1FlexGrid.4.5.2~C1.Win.C1FlexGrid.C1FlexGrid~MeasureCellSize.html?highlight=measurecellsize%2C

    Regards,

    Prabhat Sharma.

  • Posted 18 January 2024, 3:49 pm EST

    Great, thanks!

    I tried to implement a “Height to last” autosizing algorithm, see attached sample.

    FlexAutoSizeRow6.zip

    Could you do me a favor and review it? Is it reasonable, did I miss something, or do you see any improvements (mainly performance is critical for me, as I want to autosize large grids).

    I made some effort to handle invisible rows (in case e.g. top row or bottom row of merged is invisible), and finally I noticed that C1FlexGrids own “AutoSizeRows” does not handle this case ;-). The sample has checkboxes to hide rows, and you will see that “AutoSizeRows” with an invisible merged range row truncates the range content.

    Best regards

    Wolfgang

  • Posted 19 January 2024, 8:52 am EST

    Hello Wolfgang,

    We tested your method and did not find any performance issues. It performs well even with extensive datasets, as we tested it with around 5000 rows by replicating the data in your sample.

    Also, it seems that all common scenarios are covered, and the logic and functionality are correct.

    We are sorry, but we could not observe the behavior where the cell data is truncated. Could you please provide a video or screenshots showcasing it?

    Regards,

    Uttkarsh.

  • Posted 19 January 2024, 9:00 am EST - Updated 19 January 2024, 9:05 am EST

    Hi Uttkarsh,

    thanks for the review and for the performance measurement! I think it might perform even better if I create a Graphics object only once and use it for all “MeasureCell” calls. I will add it to my C1FlexGridEnhancements github repository.

    Reality will probably reveal problems that we both don’t think about now ;-).

    About AutoSizeRows and wrong result with invisible rows:



    In the sample, uncheck “Second data row is visible” and click the “AutoSizeRows” button ==> the long text will be truncated.

    Best regards

    Wolfgang

  • Posted 19 January 2024, 6:49 pm EST

    I integrated the code in our real world app. The good news: performance of AutoSizeRows increased a lot. In a large grid, the default “AutoSizeRows” took about 0,5 sec, while my new method takes 0,2 sec. I made some changes, now it can not only handle custom merged ranged, but any merge mode from the grid.

    The bad news: while playing with different merged ranges, I noticed that C1FlexGrid.MeasureCells returns wrong values for my rather long text. This kind of texts does not occur in our real world app hopefully, so it is only a problem of my testing sample.

    To keep track of the problems, let’s give the problem “AutoSizeRows calculates wrong row height if rows of merged range are invisible” of my previous post the ID “2024-01-19A”

    Attached sample “FlexAutoSizeRow6_2024-01-19.zip” contains a slightly optimized code for autosizing, and it adds several more merged ranges.

    This causes two problems:

    First problem with ID “2024-01-19B”: suddenly, the long text in merged range “(4,3) to (6,3)” is clipped in default “AutoSizeRows” and also in my call to “MeasureCellSize”.

    Second problem with ID “2024-01-19C”: I added the same text to the cells “(7,1) to (8,5)”. Here, “AutoSizeRows” calculates the proper height, but “MeasureCellSize” returns an absurd cell height, which is caused by the fact that the measured range width is only “110” (width of first col of the range) instead of about “740”.

    FlexAutoSizeRow6_2024-01-19.zip

    Maybe I made some error in populating the grid, but I don’t see it.

    Best regards

    Wolfgang

  • Posted 22 January 2024, 9:12 am EST

    Hello Wolfgang,

    Thank you for the detailed explanation.

    We are looking into your sample and working on it. We’ll get back to you with updates soon.

    Regards,

    Uttkarsh.

  • Posted 23 January 2024, 8:59 am EST

    Hello Wolfgang,

    problem ID “2024-01-19A":

    We were able to replicate this on our end, so we have escalated it to the development team to get their insights on this behavior.

    problem with ID “2024-01-19B”:

    You can resize again using your HeightToLast() method after hiding rows. Please refer to the attached modified sample. (see FlexAutoSizeRow6_Mod.zip)

    problem with ID “2024-01-19C”:

    MeasureCellSize() method calculates the size of the cell.

    In your case, the merged cell range consists of 5 columns, but the height returned by the MeasureCellSize() method returns the size of the single cell based on the index you pass in the MeasureCellSize() method.

    We are discussing this behavior with the development team to get their insights on it.

    Regards,

    Uttkarsh

    FlexAutoSizeRow6_Mod.zip

  • Posted 23 January 2024, 12:12 pm EST

    Hi Uttkarsh,

    problem ID “2024-01-19A":

    Thanks. But I think it is not a realistic scenario to have merged ranged that are only partially visible. As we did not run into this in our real world application, it does not seem to be an issue ;-). So, you can forward it to the developers, but it is not urgent for me.

    problem with ID “2024-01-19B”:

    I think we have a misunderstanding here. The wrong cell height is not related to row visibility, it happens for me also if I start the sample and then click the “Height to last” button, without hiding any rows.

    Might be related to the form size: if I maximize the form (your sample gave me the inspiration, as you docked the grid ;-)) the merged text is completely rendered. It is clipped only if the form has it’s default size. But it seems to be a drawing issue: the merged range spans three rows: row 4 has a height of 57, row 5 is 25 high, and row 6 has the remaining height of 693, which results in the measured height of 775. Row 6 is clipped.

    So, I think it is a drawing issue: if the grid scrolls and a merged range does not fit completely on the screen, the range content is not scrolled, but it renders always the beginning.

    It also happens with default “AutoSizeRows”.

    So, this seems to be an issue that is not related to “MeasureCellSize” or my code.

    problem with ID “2024-01-19C”:

    This seems to be broken by design? “MeasureCellSize” does not handle merged ranges if they span multiple columns?

    A fix to this issue is critical for me, as I am not sure whether multi column/multi row merged ranges could occur in our app.

    Do you have any internal ticket IDs for me? This way I could check whether anything is fixed in the changelog of upcoming releases.

    Best regards

    Wolfgang

  • Posted 24 January 2024, 5:04 am EST

    Hello Wolfgang,

    Please find the internal tracking IDs for each of your concerns below:

    1. ID “2024-01-19A": C1WIN-31569

    2. ID “2024-01-19B": C1WIN-31570

      Thank you for the clarification.

      Previously, it seemed like you wanted to resize the rows after hiding some rows in a merged range. Now, we were also able to observe the behavior you pointed out, so we have escalated it to the developers to get their insights on this behavior.

    3. ID “2024-01-19C": C1WIN-31571

    We will update you when we get necessary updates on any of these.

    Regards,

    Uttkarsh.

  • Posted 25 January 2024, 4:23 am EST

    About 2 (ID “2024-01-19B": C1WIN-31570): first, I also thought it would be an issue with “MeasureCellSize”, but while writing my reply, I understood that it’s a rendering issue.

    Best regards

    Wolfgang

  • Posted 18 July 2024, 5:46 am EST

    Hello Wolfgang,

    For C1WIN-31571 -

    As per the developers, the MeasureCellSize method calculates the height of one row, taking into account that the row may be included in the merged range. If you want to get the height of all the rows in the merged range, then you can simply multiply the result of the MeasureCellSize calculation by the number of rows in the merged range as follows:

    int GetCalculatedHeight(CellRange cellRange)
    {
        var totalHeight = 0;
        for(int r = cellRange.TopRow; r <= cellRange.BottomRow; r++)
        {
            totalHeight += c1FlexGrid1.MeasureCellSize(r, 1).Height;
        }
        return totalHeight - (cellRange.BottomRow - cellRange.TopRow) * (c1FlexGrid1.Rows[0].HeightDisplay - 1);
    }


    Please refer to the attached sample for implementation. (see FlexGrid6_MeasureCellTest.zip)

    If this does not address the issue you are having, please clarify what exactly you are looking for and what you want to get as a result.

    Regards,

    Uttkarsh.

  • Posted 18 July 2024, 3:20 pm EST - Updated 18 July 2024, 3:25 pm EST

    Well, this seems to work in your sample, but after applying it to my own sample, I see still wrong heights, see sample. The results are different to my initial code, but still broken.

    FlexAutoSizeRow6_2024-07-18.zip

    I added debugging output for height calculation by “C1FlexGrid.MeasureCellSize” and by the suggested workaround, and it writes this:

    Measuring range CellRange: (3,4)-(4,5)
    	MeasureCellSize returned {Width=110, Height=20}
    	Workaround returned 57
    Measuring range CellRange: (4,2)-(5,2)
    	MeasureCellSize returned {Width=110, Height=36}
    	Workaround returned 57
    Measuring range CellRange: (4,3)-(6,3)
    	MeasureCellSize returned {Width=295, Height=258}
    	Workaround returned 57
    Measuring range CellRange: (7,1)-(8,5)
    	MeasureCellSize returned {Width=110, Height=124}
    	Workaround returned 98

    Maybe this happens because your workaround fetches “Row.HeightDisplay”, and this one might have been modified already it the row was already part of another merged range that started above and was also autosized.

    I actually don’t understand why the measured height is reduced by the height of the first row, multiplied by “range row count - 1” ;-).

    I am on vacation for the next two weeks, so replies might be delayed.

    Best regards

    Wolfgang

  • Posted 20 July 2024, 2:44 am EST

    Hello Wolfgang,

    I actually don’t understand why the measured height is reduced by the height of the first row, multiplied by “range row count - 1”

    This is to get the effective height to be applied to the last row. So, we subtracted the height of remaining rows from the totalHeight. After reviewing your sample, we observed that you were already handling the effective height by subtracting the height of other rows. Now we have removed our code of handling this.

    Maybe this happens because your workaround fetches “Row.HeightDisplay” . . .

    Well, we used this to get the height of a row if it has the default height of “-1”. In your sample, we observed that you are calling our

    GetCalculatedHeight(CellRange cellRange)
    method before altering the heights and even if our method fetch altered Row.HeightDisplay, it would handle them during the calculation of effective height.

    We also noticed that your code did not handled the condition where default height is “-1”. We have fixed it. Please refer to the line no. 162 in “C1FlexGridAutoSizeRowsHeightToLast.cs” in the attached modified sample.

    Another thing we noticed is that MeasureCellSize() method returned “-1” if a cell of the merged-range did not have data. We have modified our

    GetCalculatedHeight(CellRange cellRange)
    method accordingly. We’ll get in touch with developers for this behavior and will share their insights with you.

    Sample: FlexAutoSizeRow6_Mod.zip

    Regards,

    Uttkarsh.

  • Posted 25 July 2024, 6:13 am EST

    Hello Wolfgang,

    As per the developers, the behavior is a bug and the ETA for the fix is 2024v1 hotfix2.

    [Internal Bug ID: C1WIN-31580]

    Rest assured, we’ll update you once the issue is fixed.

    Regards,

    Uttkarsh.

  • Posted 5 August 2024, 2:27 am EST

    Hi Uttkarsh,

    sorry for the delay, I was on vacation.

    Thanks for the reworked sample. I can confirm that it seems to work for me now. Now awaiting the fix for the issue "MeasureCellSize() returns -1 for empty cells”.

    Best regards

    Wolfgang

  • Posted 19 September 2024, 6:58 am EST - Updated 19 September 2024, 7:03 am EST

    I found a fix for the issue from your latest response in the readme:

    [FlexGrid] It was impossible to get the size of a row from a merged range if there was no data in its other row. (Jira:C1WIN-31580)

    But I am lost on the current state of this discussion - your latest sample “FlexAutoSizeRow6_Mod.zip” still does not render the correct row height for the last merged range in mode “Height to last”:



    Could you check it? Also, I am not sure which version of the different samples finally applies and which workarounds are required. But it seems the result of “MeasureCellSize” must somehow be multiplied with the range row count?

    Also, if I uncheck “Fourth data row visible” and click “AutoSizeRows”, the range containing an invisible row has still a wrong height:



    According to the readme, this might have been fixed, but the issue number does not match mine from this thread (C1WIN-31569):

    [FlexGrid] AutoSizeRows was calculating the wrong row height if the rows in the merged range were invisible. (Jira:C1WIN-31578)

    I think that scrolling of a merged range that is higher than the form now works (issue C1WIN-31570 in this thread). I found this in the readme - does it match?

    [FlexGrid] Data in the merged range was displayed only from the beginning when scrolling. (Jira:C1WIN-31577)

    Best regards

    Wolfgang

  • Posted 20 September 2024, 1:25 am EST

    Hello Wolfgang,

    But it seems the result of “MeasureCellSize” must somehow be multiplied with the range row count?

    Yes, you are right. We have modified the sample accordingly.

    Also, if I uncheck “Fourth data row visible” and click “AutoSizeRows”, the range containing an invisible row has still a wrong height:

    We have fixed this in your sample by commenting out the line number 231 in C1FlexGridAutoSizeRowsHeightToLast.cs, which prevents the merged ranges whose last row is invisible and there are only two rows in the merged range. Please let us know if there are any issues with it.

    According to the readme, this might have been fixed, … when scrolling. (Jira:C1WIN-31577)

    Apologies, we did not provide the bug IDs for both the issue IDs (C1WIN-31569 and C1WIN-31570)

    Sample: FlexAutoSizeRow6_Mod2.zip

    Regards,

    Uttkarsh.

  • Posted 20 September 2024, 6:41 am EST - Updated 20 September 2024, 6:47 am EST

    Many thanks, your reworked sample seems to be fine.

    About this one:

    I think you misunderstood me here ;-): the issue does not happen in my own code, I just call “C1FlexGrid.AutoSizeRows”.

    Best regards

    Wolfgang

  • Posted 23 September 2024, 12:00 am EST

    Hello Wolfgang,

    This is because the AutoSizeRows method ignores hidden rows by default. You must call it without the ignore option as follows:

    this.c1FlexGrid1.AutoSizeRows(0, 0, c1FlexGrid1.Rows.Count -1, c1FlexGrid1.Cols.Count - 1, 0, AutoSizeFlags.None);

    Regards,

    Uttkarsh.

  • Posted 23 September 2024, 3:30 am EST

    Perfect, thanks! This works.

    Wolfgang

  • Posted 25 September 2024, 2:50 pm EST

    Added the “height to last” mode to my samples collection: https://github.com/WolfgangHG/C1FlexGridEnhancements/tree/main/C1FlexGrid6AutoSizeRowHeightToLast

    Hopefully someone finds it helpful.

Need extra support?

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

Learn More

Forum Channels