Skip to content

Commit

Permalink
[C] clear _targetObject (#18398)
Browse files Browse the repository at this point in the history
Avoid NRE on reapplying.

- fixes #18123
  • Loading branch information
StephaneDelcroix authored Oct 27, 2023
1 parent 783f8c9 commit 9910699
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/Controls/src/Core/MultiBinding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ internal override void Unapply(bool fromBindingContextChanged = false)

_bpProxies = null;
_proxyObject = null;
_targetObject = null;
}

base.Unapply(fromBindingContextChanged: fromBindingContextChanged);
Expand Down
57 changes: 57 additions & 0 deletions src/Controls/tests/Xaml.UnitTests/Issues/Maui18123.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Microsoft.Maui.Controls.Xaml.UnitTests"
x:Class="Microsoft.Maui.Controls.Xaml.UnitTests.Maui18123">
<ContentPage.Resources>
<local:Maui18123MultiValueConverter x:Key="MultiValueConverter"/>
</ContentPage.Resources>
<StackLayout>
<Button
Text="Delete" WidthRequest="100"
HorizontalOptions="Center"
Command="{Binding TestCommand}"
x:Name="deleteBtn">
<Button.CommandParameter>
<MultiBinding Converter="{StaticResource MultiValueConverter}">
<Binding Source="Dummy"/>
<Binding Source="Edit"/>
</MultiBinding>
</Button.CommandParameter>
<Button.Triggers>
<DataTrigger TargetType="Button" Binding="{Binding Mode}" Value="Edit">
<Setter Property="Text" Value="CANCEL" />
<Setter Property="CommandParameter">
<Setter.Value>
<MultiBinding Converter="{StaticResource MultiValueConverter}">
<Binding Source="Cancel"/>
</MultiBinding>
</Setter.Value>
</Setter>
</DataTrigger>
</Button.Triggers>
</Button>

<Button
Text="Edit" WidthRequest="100"
HorizontalOptions="Center"
Command="{Binding TestCommand}"
x:Name="editBtn">
<Button.CommandParameter>
<MultiBinding Converter="{StaticResource MultiValueConverter}">
<Binding Source="Dummy"/>
<Binding Source="Edit"/>
</MultiBinding>
</Button.CommandParameter>
<Button.Triggers>
<DataTrigger TargetType="Button" Binding="{Binding Mode}" Value="Edit">
<Setter Property="Text" Value="SUBMIT" />
</DataTrigger>
<DataTrigger TargetType="Button" Binding="{Binding Mode}" Value="Create">
<Setter Property="Text" Value="SUBMIT" />
<Setter Property="CommandParameter" Value="Edit"/>
</DataTrigger>
</Button.Triggers>
</Button>
</StackLayout>
</ContentPage>
96 changes: 96 additions & 0 deletions src/Controls/tests/Xaml.UnitTests/Issues/Maui18123.xaml.cs
Original file line number Diff line number Diff line change
@@ -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;
}

}
}

0 comments on commit 9910699

Please # to comment.