dotnet / dotnet/maui

Navigation.PopModalAsync accessing properties of pages BindingContext when it shouldn't.

Open
#27,344 4 comments 0 reactions 0 assignees View on GitHub
area-xaml migration-compatibility p/2 platform/android platform/windows s/triaged s/verified t/bug
Dominant language
C#
Stars
23.3k
Forks
2k
Avg merge
1d 14h
Merged PRs (30d)
296

Description

### Description

I have a page that has it's BindingContext set to my class, PersonViewModel.
On the page, I have a ToolBarItem "Delete", which calls "Delete" on the object, and then call Navigation.PopModalAsync.

Note that the "Delete" of the object simply marks that object as deleted, and any attempts to access any properties on it after it has been marked as deleted will result in an error being thrown.

On the page, I have Button that has it's IsEnabled property bound to a property on the PersonViewModel.

After Delete has been called, as mentioned above, Navigation.PopModalAsync gets called, but this results in an error. Note that this did not produce an error in Xamarin (3.5)

System.Reflection.TargetInvocationException Exception has been thrown by the target of an invocation.

at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters) at Microsoft.Maui.Controls.BindingExpression.BindingExpressionPart.TryGetValue(Object source, Object& value) at Microsoft.Maui.Controls.BindingExpression.ApplyCore(Object sourceObject, BindableObject target, BindableProperty property, Boolean fromTarget, SetterSpecificity specificity) at Microsoft.Maui.Controls.BindingExpression.Apply(Boolean fromTarget) at Microsoft.Maui.Controls.Binding.Apply(Boolean fromTarget) at Microsoft.Maui.Controls.BindableObjectExtensions.RefreshPropertyValue(BindableObject self, BindableProperty property, Object value) at Microsoft.Maui.Controls.VisualElement.Microsoft.Maui.Controls.IPropertyPropagationController.PropagatePropertyChanged(String propertyName) at Microsoft.Maui.Controls.Internals.PropertyPropagationExtensions.PropagatePropertyChanged(String propertyName, Element element, IEnumerable children) at Microsoft.Maui.Controls.VisualElement.Microsoft.Maui.Controls.IPropertyPropagationController.PropagatePropertyChanged(String propertyName) at Microsoft.Maui.Controls.Internals.PropertyPropagationExtensions.PropagatePropertyChanged(String propertyName, Element element, IEnumerable children) at Microsoft.Maui.Controls.VisualElement.Microsoft.Maui.Controls.IPropertyPropagationController.PropagatePropertyChanged(String propertyName) at Microsoft.Maui.Controls.Internals.PropertyPropagationExtensions.PropagatePropertyChanged(String propertyName, Element element, IEnumerable children) at Microsoft.Maui.Controls.VisualElement.Microsoft.Maui.Controls.IPropertyPropagationController.PropagatePropertyChanged(String propertyName) at Microsoft.Maui.Controls.Internals.PropertyPropagationExtensions.PropagatePropertyChanged(String propertyName, Element element, IEnumerable children) at Microsoft.Maui.Controls.VisualElement.Microsoft.Maui.Controls.IPropertyPropagationController.PropagatePropertyChanged(String propertyName) at Microsoft.Maui.Controls.Element.OnParentSet() at Microsoft.Maui.Controls.NavigableElement.OnParentSet() at Microsoft.Maui.Controls.Page.OnParentSet() at Microsoft.Maui.Controls.Element.SetParent(Element value) at Microsoft.Maui.Controls.Element.OnChildRemoved(Element child, Int32 oldLogicalIndex) at Microsoft.Maui.Controls.Element.RemoveLogicalChild(Element element, Int32 index) at Microsoft.Maui.Controls.Element.RemoveLogicalChild(Element element) at Microsoft.Maui.Controls.Platform.ModalNavigationManager.PopModalAsync(Boolean animated) at Microsoft.Maui.Controls.Shell.NavigationImpl.OnPopModal(Boolean animated) at Microsoft.Maui.Controls.ShellSection.PopModalStackToPage(Page page, Nullable`1 animated) at Microsoft.Maui.Controls.ShellNavigationManager.GoToAsync(ShellNavigationParameters shellNavigationParameters, ShellNavigationRequest navigationRequest) at Microsoft.Maui.Controls.Shell.NavigationImpl.OnPopModal(Boolean animated) at BindingToInvalidObject.PersonPage.<>c__DisplayClass1_0.<<-ctor>b__0>d.MoveNext() in C:\Temp\ThrowAwayCode\BindingToInvalidObject\BindingToInvalidObject\PersonPage.xaml.cs:line 25

### Steps to Reproduce

See the linked repository for code and the readme has instructions.

### Link to public reproduction project repository

https://github.com/Mark-NC001/BindingToInvalidObject

### Version with bug

9.0.30 SR3

### Is this a regression from previous behavior?

Yes, this used to work in Xamarin.Forms

### Last version that worked well

Unknown/Other

### Affected platforms

Windows, Android

### Affected platform versions

_No response_

### Did you find any workaround?

_No response_

### Relevant log output

```shell

```

Contributor guide

Open the contributing guide

Research direction

Start with the linked BindingToInvalidObject reproduction project and its README, then inspect PersonPage.xaml.cs at line 25 and follow the stack trace through PopModalAsync and binding propagation. Reproduce the failure on Windows or Android and confirm completion when popping the modal no longer accesses the deleted BindingContext or throws TargetInvocationException, with regression coverage for the behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
frontend, mobile-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.