maui
maui copied to clipboard
Adding/Removing layout children does not invalidate measures
Description
I'm using a simple BindableLayout
to add and remove children dynamically from VerticalStackLayout
and I realized MeasureInvalidated
event is not being fired when children changes.
So I went inside MAUI repo and added a couple of unit test which in fact are failing:
static IViewHandler ListenForInvalidation(IView view)
{
var handler = Substitute.For<IViewHandler>();
view.Handler = handler;
handler.ClearReceivedCalls();
return handler;
}
[Fact]
public void AddingChildInvalidatesLayoutHandler()
{
var layout = new VerticalStackLayout();
var handler = ListenForInvalidation(layout);
layout.Add(new Label());
AssertInvalidated(handler);
}
[Fact]
public void AddingChildInvalidatesLayout()
{
var layout = new VerticalStackLayout();
var invalidated = false;
layout.MeasureInvalidated += (_, _) => invalidated = true;
layout.Add(new Label());
Assert.True(invalidated);
}
Note: the Grid
from Compatibility package does behave correctly, in fact you have a working unit test there:
[Fact]
public void TestAddCell()
{
var layout = new Grid();
bool preferredSizeChanged = false;
layout.MeasureInvalidated += (sender, args) => preferredSizeChanged = true;
Assert.False(preferredSizeChanged);
layout.Children.Add(new Label(), 0, 0);
Assert.True(preferredSizeChanged);
}
I would propose a PR but I'm not sure which approach you would like to take here as the fix should probably go in Layout
base class or maybe in VisualElement
idk.
Steps to Reproduce
- Create a
VerticalStackLayout
- Subscribe to
MeasureInvalidated
- Add a child
- Observe nothing was triggered
Link to public reproduction project repository
No response
Version with bug
8.0.6
Is this a regression from previous behavior?
Yes, this used to work in Xamarin.Forms
Last version that worked well
Unknown/Other
Affected platforms
iOS, I was not able test on other platforms
Affected platform versions
No response
Did you find any workaround?
Manually trigger the event ((IVisualElementController)layout).InvalidateMeasure(InvalidationTrigger.MeasureChanged);
which is something that makes BindableLayout
basically unusable in combination with Binding
on ItemSource
because we have to subscribe twice using the view code behind.
Relevant log output
No response