Skip to content

Commit 2a1d9bf

Browse files
committed
VirtualizingStackPanel - Warmup for IVirtualizedDataTemplates
VirtualizingStackPanel can handle items with (very) different heights (no scroll jumping, no layout cycles) IVirtualizingDataTemplate implementation for ItemsControls (not only ItemContainers are re-used but also the Content)
1 parent bd041f2 commit 2a1d9bf

23 files changed

Lines changed: 7126 additions & 120 deletions

VARIABLE_HEIGHT_TEST.md

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
# Variable Height Testing Setup
2+
3+
## Changes Made to ComplexVirtualizationPage
4+
5+
### Modified Files:
6+
1. `samples/ControlCatalog/ViewModels/ComplexVirtualizationPageViewModel.cs`
7+
8+
### What Was Changed:
9+
10+
#### 1. Enhanced SampleText Array (Line 162-179)
11+
Added 15 text samples with **extreme length variance**:
12+
- **Very short**: "A", "Brief.", "Short text." (1-10 characters)
13+
- **Short**: Single sentences (~50-60 characters)
14+
- **Medium**: Standard Lorem Ipsum sentences (~100-120 characters)
15+
- **Long**: Extended Lorem Ipsum paragraphs (~200-250 characters)
16+
- **Very long**: Excessive verbose sentence (~300+ characters)
17+
18+
This creates text that will wrap from 0 lines to 5+ lines depending on container width.
19+
20+
#### 2. Person Bio Length (Lines 33-43)
21+
**Old**: 0-4 sentences
22+
**New**: Weighted distribution 0-11 sentences:
23+
- 9% - No bio (0 sentences)
24+
- 18% - Very short (1 sentence, ~1 line)
25+
- 27% - Short (2-3 sentences, ~2-3 lines)
26+
- 18% - Medium (4-5 sentences, ~3-4 lines)
27+
- 18% - Long (6-8 sentences, ~5-7 lines)
28+
- 9% - Very long (9-11 sentences, ~8-10 lines)
29+
30+
**Skills**: Increased from 2-7 to 2-10 skills
31+
32+
#### 3. Task Description Length (Lines 69-78)
33+
**Old**: 1-5 sentences
34+
**New**: Weighted distribution 1-12 sentences:
35+
- 18% - Very short (1 sentence)
36+
- 27% - Short (2-3 sentences)
37+
- 27% - Medium (4-6 sentences)
38+
- 18% - Long (7-9 sentences)
39+
- 9% - Very long (10-12 sentences)
40+
41+
**Subtasks**: Increased from 2-6 to 2-8 subtasks
42+
43+
#### 4. Product Description Length (Lines 110-119)
44+
**Old**: 0-3 sentences (50% chance)
45+
**New**: Weighted distribution 0-8 sentences:
46+
- 11% - No description
47+
- 22% - Very short (1 sentence)
48+
- 22% - Short (2-3 sentences)
49+
- 22% - Medium (4-5 sentences)
50+
- 22% - Long (6-8 sentences)
51+
52+
**Tags**: Increased from 1-10 to 1-12 tags
53+
54+
#### 5. Photo Caption Length (Lines 135-144)
55+
**Old**: 0-4 sentences
56+
**New**: Weighted distribution 0-8 sentences:
57+
- 11% - No caption
58+
- 22% - Very short (1 sentence)
59+
- 22% - Short (2-3 sentences)
60+
- 22% - Medium (4-5 sentences)
61+
- 22% - Long (6-8 sentences)
62+
63+
**Comments**: Increased from 1-5 to 1-7 comments
64+
65+
---
66+
67+
## Expected Item Height Variance
68+
69+
With these changes, item heights will vary **dramatically**:
70+
71+
### Minimum Heights (No text content):
72+
- **PersonItem**: ~150px (header + name/email + phone only)
73+
- **TaskItem**: ~120px (header + title + progress bar only)
74+
- **ProductItem**: ~100px (header + name + price only)
75+
- **PhotoItem**: ~120px (image + header + title + location only)
76+
77+
### Maximum Heights (Full text content):
78+
- **PersonItem**: ~800px+ (long bio + 10 skills)
79+
- **TaskItem**: ~900px+ (very long description + 8 subtasks)
80+
- **ProductItem**: ~600px+ (long description + 12 tags)
81+
- **PhotoItem**: ~700px+ (long caption + 7 comments)
82+
83+
### Height Ratio:
84+
- **Minimum to Maximum**: ~5:1 to 8:1 ratio
85+
- **Average height variance**: Items will randomly range from 100px to 900px
86+
87+
---
88+
89+
## How to Test
90+
91+
### 1. Enable Tracing (Optional)
92+
In your XAML or code, enable tracing on the VirtualizingStackPanel:
93+
```csharp
94+
var stackPanel = listBox.ItemsPanelRoot as VirtualizingStackPanel;
95+
if (stackPanel != null)
96+
{
97+
stackPanel.IsTracingEnabled = true;
98+
}
99+
```
100+
101+
### 2. Run the ControlCatalog Sample
102+
```bash
103+
cd samples/ControlCatalog
104+
dotnet run
105+
```
106+
107+
### 3. Navigate to ComplexVirtualizationPage
108+
In the ControlCatalog, find and click on "Content Virtualization Demo"
109+
110+
### 4. Observe Scrolling Behavior
111+
112+
**What to look for:**
113+
114+
#### ✅ Good Behavior (Distance-based gap tolerance working):
115+
- Smooth scrolling up and down
116+
- No "RECYCLING ALL" messages during normal scrolling
117+
- Debug output shows gaps like:
118+
```
119+
GapBefore=5 items (650px/605px), Disjunct=False
120+
GapBefore=8 items (1040px/605px), Disjunct=True → RECYCLING (expected for large gap)
121+
```
122+
- Items vary wildly in height, but scrolling remains smooth
123+
124+
#### ❌ Bad Behavior (If distance-based tolerance wasn't working):
125+
- Frequent "RECYCLING ALL" messages
126+
- Stuttering/janky scrolling
127+
- Gap calculations ignoring actual pixel distances:
128+
```
129+
GapBefore=5 items (5000px/605px), Disjunct=False → BAD! Should recycle
130+
```
131+
132+
### 5. Test Scenarios
133+
134+
#### Scenario A: Slow Smooth Scrolling
135+
- Scroll slowly from top to bottom
136+
- Expected: No recycling, all gaps handled incrementally
137+
- Debug shows: `GapBefore/After` values staying below thresholds
138+
139+
#### Scenario B: Fast Scrolling
140+
- Rapidly scroll down/up
141+
- Expected: Occasional recycling when gaps exceed viewport size
142+
- Debug shows: `Disjunct=True` only when gap distance > 605px
143+
144+
#### Scenario C: Jump to End
145+
- Scroll all the way to bottom quickly
146+
- Expected: One "RECYCLING ALL" as viewport jumps far
147+
- Debug shows: Large gap distance triggering disjunct
148+
149+
#### Scenario D: Scroll Up from End
150+
- At bottom, scroll slowly upward
151+
- Expected: No recycling until gap exceeds 605px (100% of viewport)
152+
- This was the original issue - now fixed!
153+
154+
---
155+
156+
## Debug Output Example
157+
158+
With tracing enabled, you should see output like:
159+
160+
```
161+
[VSP] CalculateMeasureViewport: Anchor=15 (u=2340.50), Realized=[10-30] (Count=21),
162+
GapBefore=5 items (650px/605px), GapAfter=-15 items (-1950px/302px),
163+
Disjunct=True, ViewportSize=605px
164+
[VSP] RECYCLING ALL - HasReachedEnd=False, HasReachedStart=False, ItemCount=5000
165+
166+
[VSP] CalculateMeasureViewport: Anchor=42 (u=6500.00), Realized=[40-58] (Count=19),
167+
GapBefore=2 items (260px/605px), GapAfter=-16 items (-2080px/302px),
168+
Disjunct=False, ViewportSize=605px
169+
```
170+
171+
**Key metrics to watch:**
172+
- **Gap pixel distance**: Should accurately reflect estimated height × item count
173+
- **Disjunct decision**: Should be `True` only when pixel distance exceeds thresholds
174+
- **ViewportSize**: Should match your window's visible area
175+
176+
---
177+
178+
## Verification Checklist
179+
180+
- [ ] Items have wildly varying heights (100px to 900px range)
181+
- [ ] Text wraps across multiple lines in many items
182+
- [ ] Scrolling is smooth without excessive recycling
183+
- [ ] "RECYCLING ALL" only appears on large jumps
184+
- [ ] Debug output shows pixel-based gap calculations
185+
- [ ] Backward scrolling (up) tolerates larger gaps than forward scrolling
186+
- [ ] No layout cycle warnings during normal scrolling
187+
188+
---
189+
190+
## Performance Comparison
191+
192+
### Before Distance-Based Tolerance:
193+
- Fixed 2-item gap tolerance
194+
- Small items: Frequent unnecessary recycling (e.g., 5 tiny items = 100px, incorrectly recycled)
195+
- Large items: Inadequate recycling (e.g., 3 huge items = 2700px, incorrectly kept)
196+
197+
### After Distance-Based Tolerance:
198+
- Dynamic tolerance based on viewport size
199+
- Small items: Many items can be realized without recycling (gap < 605px)
200+
- Large items: Fewer items trigger recycling (gap > 605px)
201+
- Adaptive: Works perfectly regardless of item size distribution

0 commit comments

Comments
 (0)