Browse Source

Fix "BindingExpression has not been started" (#15170)

* Added failing test for #14753.

* Don't try to publish on non-running binding.

This can happen in cases like #14653 where:

1. An event is raised with 2 binding expression subscribers
2. The first subscriber causes the 2nd subscriber to be stopped
3. The second subscriber is called from the event, even though it has been stopped (as the event list was cached at step 1)
4. It calls `PublishValue` causing an exception

Easiest to just do nothing in `PublishValue` when this scenario happens.
pull/15277/head
Steven Kirk 2 years ago
committed by GitHub
parent
commit
35fb2bc657
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 3
      src/Avalonia.Base/Data/Core/UntypedBindingExpressionBase.cs
  2. 36
      tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/DynamicResourceExtensionTests.cs

3
src/Avalonia.Base/Data/Core/UntypedBindingExpressionBase.cs

@ -403,6 +403,9 @@ public abstract class UntypedBindingExpressionBase : BindingExpressionBase,
/// <param name="error">The new binding or data validation error.</param>
private protected void PublishValue(object? value, BindingError? error = null)
{
if (!IsRunning)
return;
// When binding to DataContext and the expression results in a binding error, the binding
// expression should produce null rather than UnsetValue in order to not propagate
// incorrect DataContexts from parent controls while things are being set up.

36
tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/DynamicResourceExtensionTests.cs

@ -924,6 +924,42 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
window.Content = null;
}
[Fact]
public void Handles_Clearing_Resources_With_Dynamic_Theme_In_Dynamic_Template()
{
// Issue #14753
using var app = UnitTestApplication.Start(TestServices.StyledWindow);
var xaml = """
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Window.Resources>
<SolidColorBrush x:Key='Blue'>Blue</SolidColorBrush>
<ControlTheme x:Key="MyBorder" TargetType="Border">
<Setter Property="Background" Value="{DynamicResource Blue}"/>
</ControlTheme>
<ControlTheme x:Key="MyButton" TargetType="Button">
<Setter Property="Template">
<ControlTemplate>
<Border Theme="{DynamicResource MyBorder}"/>
</ControlTemplate>
</Setter>
</ControlTheme>
</Window.Resources>
<Button Theme="{DynamicResource MyButton}" Background="{DynamicResource Blue}"/>
</Window>
""";
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
window.Show();
var button = Assert.IsType<Button>(window.Content);
var border = Assert.IsType<Border>(button.GetVisualChildren().Single());
var background = Assert.IsAssignableFrom<ISolidColorBrush>(border.Background);
Assert.Equal(Colors.Blue, background.Color);
window.Resources.Clear();
}
private IDisposable StyledWindow(params (string, string)[] assets)
{
var services = TestServices.StyledWindow.With(

Loading…
Cancel
Save