VisualTreeHelper.GetDescendantBounds() reports incorrect value for Row with collapsed RowDetails that were previously expanded
- Dominant language
- C#
- Stars
- 7.7k
- Forks
- 1.3k
- Avg merge
- 1d 11h
- Merged PRs (30d)
- 61
Description
* .NET Core Version: 3.1 and .NET 5
* Windows version: Version 21H1 (OS Build 19043.1110)
* Does the bug reproduce also in WPF for .NET Framework 4.8?: Yes
**Problem description:**
`VisualTreeHelper.GetDescendantBounds()` reports the wrong boundaries for a `DataGridRow` when that row's details were previously expanded and then collapsed.
This is very easy to reproduce and extremely frustrating.
`InvalidateMeasure()`, `InvalidateArrange()` and `InvalidateVisual()` do not correct the problem.
So far the only way I've found to get the correct value is to call `DataGrid.Items.Refresh()`, however this is completely overkill when needing to refresh a single row, both in performance and in functional impact that will affect selected items, expansion state, etc.
I'm desperately looking for workarounds that don't involve refreshing every item in the `DataGrid`, even if those solutions involve extensive reflection, etc.
From Googling, it's possible that this is related: https://social.msdn.microsoft.com/Forums/vstudio/en-US/d5ce7ab8-cd40-4f81-8a34-08abe4e67c5a/looks-like-visualcalculatesubgraphboundsinnerspace-internal-method-has-a-serious-bug?forum=wpf
Unfortunately I have been unable to get the workaround mentioned in that thread to work using the `RowDetailsVisibilityChanged` event of the `DataGrid`.
**EDIT:** I believe there are also other examples of this issue [here](https://web.archive.org/web/20080527023236/http://kentb.blogspot.com/) (scroll down to the "Expander and VisualBrush" header - there's no archived link directly to the post, unfortunately, but the whole post is there) and [here](https://social.msdn.microsoft.com/Forums/vstudio/en-US/997fb616-4cd4-49f0-8b85-f05cde328104/visualbrush-of-an-expander-after-expandingcollapsing?forum=wpf).
**Actual behavior:**
Row with collapsed row details reports previous boundaries.
**Expected behavior:**
Row with collapsed row details reports correct boundaries.
**Minimal repro:**
https://github.com/Metritutus/VisualTreeCollapseIssue001/
**Repro instructions:**
1. Run the repro project and click the `CalculateRow1DescendantBounds` button. Observe the value (for example: "Bounds: 0,0,783.6,**29**)")
2. Expand the first row by clicking that row's expander button to its left.
3. Click the `CalculateRow1DescendantBounds` button again. Observe the value (eg "Bounds: 0,0,783.6,**37.92**)")
4. Collapse the first row by clicking that row's expander button to its left.
5. Click the `CalculateRow1DescendantBounds` button again. Observe the value (eg "Bounds: 0,0,783.6,**37.92**)"). Note that the height returned is unchanged, where I would have expected it to be 29 again.
6. Click the `RefreshItems` button.
7. Click the `CalculateRow1DescendantBounds` button again. Observe the value (eg "Bounds: 0,0,783.6,**29**)").
Contributor guide
Research direction
Start by running the minimal repro project linked in the issue and follow the VisualTreeHelper.GetDescendantBounds() calls around the DataGrid row and its RowDetailsVisibilityChanged behavior. Reproduce expansion, collapse, and refresh, then trace the relevant WPF layout state; done means a collapsed row reports its original bounds without refreshing all DataGrid items.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- desktop
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 32/100