Skip to content

Commit 35f6d73

Browse files
danwalmsleyMrJulmaxkatz6
committed
Raise the EffectiveViewPortChanged when a control is added to the tree that has already has a valid layout (#17570)
* add unit tests to show that the EffectiveViewPortChanged event is not being raised when it should. note: this tests are verified against UWP behavior. * fix raising of EffectiveViewPortChanged event. --------- Co-authored-by: Julien Lebosquain <[email protected]> Co-authored-by: Max Katz <[email protected]>
1 parent 901efda commit 35f6d73

File tree

2 files changed

+62
-8
lines changed

2 files changed

+62
-8
lines changed

src/Avalonia.Base/Layout/LayoutManager.cs

+3-6
Original file line numberDiff line numberDiff line change
@@ -213,9 +213,7 @@ public void Dispose()
213213
void ILayoutManager.RegisterEffectiveViewportListener(Layoutable control)
214214
{
215215
_effectiveViewportChangedListeners ??= new List<EffectiveViewportChangedListener>();
216-
_effectiveViewportChangedListeners.Add(new EffectiveViewportChangedListener(
217-
control,
218-
CalculateEffectiveViewport(control)));
216+
_effectiveViewportChangedListeners.Add(new EffectiveViewportChangedListener(control));
219217
}
220218

221219
void ILayoutManager.UnregisterEffectiveViewportListener(Layoutable control)
@@ -438,14 +436,13 @@ private void CalculateEffectiveViewport(Visual target, Visual control, ref Rect
438436

439437
private class EffectiveViewportChangedListener
440438
{
441-
public EffectiveViewportChangedListener(Layoutable listener, Rect viewport)
439+
public EffectiveViewportChangedListener(Layoutable listener)
442440
{
443441
Listener = listener;
444-
Viewport = viewport;
445442
}
446443

447444
public Layoutable Listener { get; }
448-
public Rect Viewport { get; set; }
445+
public Rect? Viewport { get; set; }
449446
}
450447

451448
private enum ArrangeResult

tests/Avalonia.Base.UnitTests/Layout/LayoutableTests_EffectiveViewportChanged.cs

+59-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ namespace Avalonia.Base.UnitTests.Layout
1414
public class LayoutableTests_EffectiveViewportChanged
1515
{
1616
[Fact]
17-
public async Task EffectiveViewportChanged_Not_Raised_When_Control_Added_To_Tree()
17+
public async Task EffectiveViewportChanged_Not_Raised_When_Control_Added_To_Tree_And_Layout_Pass_Has_Not_Run()
1818
{
1919
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
2020
await RunOnUIThread.Execute(async () =>
@@ -34,6 +34,60 @@ await RunOnUIThread.Execute(async () =>
3434
Assert.Equal(0, raised);
3535
});
3636
}
37+
38+
[Fact]
39+
public async Task EffectiveViewportChanged_Raised_When_Control_Added_To_Tree_And_Layout_Pass_Has_Run()
40+
{
41+
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
42+
await RunOnUIThread.Execute(async () =>
43+
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
44+
{
45+
var root = CreateRoot();
46+
var target = new Canvas();
47+
var raised = 0;
48+
49+
target.EffectiveViewportChanged += (s, e) =>
50+
{
51+
++raised;
52+
};
53+
54+
root.Child = target;
55+
56+
Assert.Equal(0, raised);
57+
58+
await ExecuteInitialLayoutPass(root);
59+
60+
Assert.Equal(1, raised);
61+
});
62+
}
63+
64+
[Fact]
65+
public async Task EffectiveViewportChanged_Raised_When_Root_LayedOut_And_Then_Control_Added_To_Tree_And_Layout_Pass_Runs()
66+
{
67+
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
68+
await RunOnUIThread.Execute(async () =>
69+
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
70+
{
71+
var root = CreateRoot();
72+
var target = new Canvas();
73+
var raised = 0;
74+
75+
target.EffectiveViewportChanged += (s, e) =>
76+
{
77+
++raised;
78+
};
79+
80+
await ExecuteInitialLayoutPass(root);
81+
82+
root.Child = target;
83+
84+
Assert.Equal(0, raised);
85+
86+
await ExecuteInitialLayoutPass(root);
87+
88+
Assert.Equal(1, raised);
89+
});
90+
}
3791

3892
[Fact]
3993
public async Task EffectiveViewportChanged_Raised_Before_LayoutUpdated()
@@ -268,8 +322,11 @@ await RunOnUIThread.Execute(async () =>
268322

269323
root.Child = parent;
270324

271-
await ExecuteInitialLayoutPass(root);
272325
target.EffectiveViewportChanged += (s, e) => ++raised;
326+
await ExecuteInitialLayoutPass(root);
327+
328+
raised = 0; // The initial layout pass is expected to raise.
329+
273330
target.RenderTransform = new TranslateTransform { X = 8 };
274331
target.InvalidateMeasure();
275332
await ExecuteLayoutPass(root);

0 commit comments

Comments
 (0)