Browse Source

Merge pull request #2641 from jp2masa/bindingoperations-donothing

Added BindingOperations.DoNothing
pull/2727/head
Steven Kirk 7 years ago
committed by GitHub
parent
commit
f5ccc5667e
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      src/Avalonia.Base/Data/BindingOperations.cs
  2. 31
      src/Avalonia.Base/Data/Core/BindingExpression.cs
  3. 7
      src/Markup/Avalonia.Markup/Data/MultiBinding.cs
  4. 71
      tests/Avalonia.Markup.Xaml.UnitTests/Converters/ValueConverterTests.cs
  5. 39
      tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests.cs

2
src/Avalonia.Base/Data/BindingOperations.cs

@ -10,6 +10,8 @@ namespace Avalonia.Data
{
public static class BindingOperations
{
public static readonly object DoNothing = new object();
/// <summary>
/// Applies an <see cref="InstancedBinding"/> a property on an <see cref="IAvaloniaObject"/>.
/// </summary>

31
src/Avalonia.Base/Data/Core/BindingExpression.cs

@ -114,6 +114,11 @@ namespace Avalonia.Data.Core
/// <inheritdoc/>
public void OnNext(object value)
{
if (value == BindingOperations.DoNothing)
{
return;
}
using (_inner.Subscribe(_ => { }))
{
var type = _inner.ResultType;
@ -126,6 +131,11 @@ namespace Avalonia.Data.Core
ConverterParameter,
CultureInfo.CurrentCulture);
if (converted == BindingOperations.DoNothing)
{
return;
}
if (converted == AvaloniaProperty.UnsetValue)
{
converted = TypeUtilities.Default(type);
@ -186,6 +196,11 @@ namespace Avalonia.Data.Core
/// <inheritdoc/>
private object ConvertValue(object value)
{
if (value == BindingOperations.DoNothing)
{
return value;
}
var notification = value as BindingNotification;
if (notification == null)
@ -196,6 +211,11 @@ namespace Avalonia.Data.Core
ConverterParameter,
CultureInfo.CurrentCulture);
if (converted == BindingOperations.DoNothing)
{
return converted;
}
notification = converted as BindingNotification;
if (notification?.ErrorType == BindingErrorType.None)
@ -327,7 +347,18 @@ namespace Avalonia.Data.Core
public void OnNext(object value)
{
if (value == BindingOperations.DoNothing)
{
return;
}
var converted = _owner.ConvertValue(value);
if (converted == BindingOperations.DoNothing)
{
return;
}
_owner._value = new WeakReference<object>(converted);
_owner.PublishNext(converted);
}

7
src/Markup/Avalonia.Markup/Data/MultiBinding.cs

@ -97,7 +97,12 @@ namespace Avalonia.Data
var culture = CultureInfo.CurrentCulture;
var converted = converter.Convert(values, targetType, ConverterParameter, culture);
if (converted == AvaloniaProperty.UnsetValue && FallbackValue != null)
if (converted == BindingOperations.DoNothing)
{
return converted;
}
if (converted == AvaloniaProperty.UnsetValue)
{
converted = FallbackValue;
}

71
tests/Avalonia.Markup.Xaml.UnitTests/Converters/ValueConverterTests.cs

@ -0,0 +1,71 @@
using System;
using System.Globalization;
using Avalonia.Controls;
using Avalonia.Data;
using Avalonia.Data.Converters;
using Avalonia.UnitTests;
using Xunit;
namespace Avalonia.Markup.Xaml.UnitTests.Converters
{
public class ValueConverterTests
{
[Fact]
public void ValueConverter_Special_Values_Work()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var xaml = @"
<Window xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
xmlns:c='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Converters;assembly=Avalonia.Markup.Xaml.UnitTests'>
<TextBlock Name='textBlock' Text='{Binding Converter={x:Static c:TestConverter.Instance}, FallbackValue=bar}'/>
</Window>";
var loader = new AvaloniaXamlLoader();
var window = (Window)loader.Load(xaml);
var textBlock = window.FindControl<TextBlock>("textBlock");
window.ApplyTemplate();
window.DataContext = 2;
Assert.Equal("foo", textBlock.Text);
window.DataContext = -3;
Assert.Equal("foo", textBlock.Text);
window.DataContext = 0;
Assert.Equal("bar", textBlock.Text);
}
}
}
public class TestConverter : IValueConverter
{
public static readonly TestConverter Instance = new TestConverter();
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is int i)
{
if (i > 0)
{
return "foo";
}
if (i == 0)
{
return AvaloniaProperty.UnsetValue;
}
return BindingOperations.DoNothing;
}
return "(default)";
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

39
tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests.cs

@ -1,20 +1,10 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq;
using Avalonia.Controls;
using Avalonia.Data;
using Avalonia.Markup.Data;
using Moq;
using Xunit;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using Avalonia.UnitTests;
using Avalonia.Data.Converters;
using Avalonia.Data.Core;
using Xunit;
namespace Avalonia.Markup.Xaml.UnitTests.Data
{
@ -40,5 +30,32 @@ namespace Avalonia.Markup.Xaml.UnitTests.Data
Assert.Equal("foo", textBlock.Text);
}
}
[Fact]
public void Binding_To_DoNothing_Works()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var xaml = @"
<Window xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
<TextBlock Name='textBlock' Text='{Binding}'/>
</Window>";
var loader = new AvaloniaXamlLoader();
var window = (Window)loader.Load(xaml);
var textBlock = window.FindControl<TextBlock>("textBlock");
window.ApplyTemplate();
window.DataContext = "foo";
Assert.Equal("foo", textBlock.Text);
window.DataContext = BindingOperations.DoNothing;
Assert.Equal("foo", textBlock.Text);
window.DataContext = "bar";
Assert.Equal("bar", textBlock.Text);
}
}
}
}

Loading…
Cancel
Save