From 09efc62908eba6e9526d4870ee045b0fb817644a Mon Sep 17 00:00:00 2001 From: Stephane Delcroix Date: Fri, 27 Oct 2023 11:07:31 +0200 Subject: [PATCH] [C] clear _targetObject Avoid NRE on reapplying. - fixes #18123 --- src/Controls/src/Core/MultiBinding.cs | 1 + .../Xaml.UnitTests/Issues/Maui18123.xaml | 57 +++++++++++ .../Xaml.UnitTests/Issues/Maui18123.xaml.cs | 96 +++++++++++++++++++ 3 files changed, 154 insertions(+) create mode 100644 src/Controls/tests/Xaml.UnitTests/Issues/Maui18123.xaml create mode 100644 src/Controls/tests/Xaml.UnitTests/Issues/Maui18123.xaml.cs diff --git a/src/Controls/src/Core/MultiBinding.cs b/src/Controls/src/Core/MultiBinding.cs index 24c05d06f52e..eaa9baef2d44 100644 --- a/src/Controls/src/Core/MultiBinding.cs +++ b/src/Controls/src/Core/MultiBinding.cs @@ -238,6 +238,7 @@ internal override void Unapply(bool fromBindingContextChanged = false) _bpProxies = null; _proxyObject = null; + _targetObject = null; } base.Unapply(fromBindingContextChanged: fromBindingContextChanged); diff --git a/src/Controls/tests/Xaml.UnitTests/Issues/Maui18123.xaml b/src/Controls/tests/Xaml.UnitTests/Issues/Maui18123.xaml new file mode 100644 index 000000000000..410e7c29f1a2 --- /dev/null +++ b/src/Controls/tests/Xaml.UnitTests/Issues/Maui18123.xaml @@ -0,0 +1,57 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/Controls/tests/Xaml.UnitTests/Issues/Maui18123.xaml.cs b/src/Controls/tests/Xaml.UnitTests/Issues/Maui18123.xaml.cs new file mode 100644 index 000000000000..2b574ec9b073 --- /dev/null +++ b/src/Controls/tests/Xaml.UnitTests/Issues/Maui18123.xaml.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Linq; +using Microsoft.Maui.ApplicationModel; +using Microsoft.Maui.Controls.Core.UnitTests; +using Microsoft.Maui.Controls.Shapes; +using Microsoft.Maui.Devices; +using Microsoft.Maui.Dispatching; + +using Microsoft.Maui.Graphics; +using Microsoft.Maui.UnitTests; +using NUnit.Framework; + +namespace Microsoft.Maui.Controls.Xaml.UnitTests; + +public class Maui18123MultiValueConverter : IMultiValueConverter +{ + public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + => values?.ToArray(); + + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) + => throw new NotImplementedException(); +} + +public partial class Maui18123 : ContentPage +{ + + public Maui18123() => InitializeComponent(); + + public Maui18123(bool useCompiledXaml) + { + //this stub will be replaced at compile time + } + + [TestFixture] + class Test + { + [SetUp] + public void Setup() + { + Application.SetCurrentApplication(new MockApplication()); + DispatcherProvider.SetCurrent(new DispatcherProviderStub()); + } + + + [TearDown] public void TearDown() => AppInfo.SetCurrent(null); + + [Test] + public void MultiBindingShouldNotThrow([Values(false, true)] bool useCompiledXaml) + { + if (useCompiledXaml) + Assert.DoesNotThrow(() => MockCompiler.Compile(typeof(Maui18123))); + + var page = new Maui18123(useCompiledXaml); + page.BindingContext = new Maui18123VM(); + page.editBtn.SendClicked(); + Assert.That(page.editBtn.Text, Is.EqualTo("SUBMIT")); + Assert.That(page.deleteBtn.Text, Is.EqualTo("CANCEL")); + page.deleteBtn.SendClicked(); + Assert.That(page.editBtn.Text, Is.EqualTo("Edit")); + Assert.That(page.deleteBtn.Text, Is.EqualTo("Delete")); + } + } + + public partial class Maui18123VM : BindableObject + { + string _mode = ""; + public string Mode + { + get { return _mode; } + set + { + _mode = value; + OnPropertyChanged(); + } + } + + Command testCommand; + public Command TestCommand => testCommand ??= new Command(Test); + + void Test(object parameter) + { + var value = string.Empty; + + if (parameter is object[] parameters) + value = parameters.LastOrDefault()?.ToString(); + else + value = parameter.ToString(); + + Mode = value; + } + + } +} \ No newline at end of file