Skip to content

Commit

Permalink
Merge pull request #2385 from OronDF343/patch-1
Browse files Browse the repository at this point in the history
Add support for ConverterParameter and StringFormat to MultiBinding
  • Loading branch information
grokys committed Mar 23, 2019
2 parents 4da4fef + e03ff4d commit b3a497b
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 2 deletions.
24 changes: 22 additions & 2 deletions src/Markup/Avalonia.Markup/Data/MultiBinding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,15 @@ public class MultiBinding : IBinding
public IList<IBinding> Bindings { get; set; } = new List<IBinding>();

/// <summary>
/// Gets or sets the <see cref="IValueConverter"/> to use.
/// Gets or sets the <see cref="IMultiValueConverter"/> to use.
/// </summary>
public IMultiValueConverter Converter { get; set; }

/// <summary>
/// Gets or sets a parameter to pass to <see cref="Converter"/>.
/// </summary>
public object ConverterParameter { get; set; }

/// <summary>
/// Gets or sets the value to use when the binding is unable to produce a value.
/// </summary>
Expand All @@ -47,6 +52,11 @@ public class MultiBinding : IBinding
/// </summary>
public RelativeSource RelativeSource { get; set; }

/// <summary>
/// Gets or sets the string format.
/// </summary>
public string StringFormat { get; set; }

/// <inheritdoc/>
public InstancedBinding Initiate(
IAvaloniaObject target,
Expand Down Expand Up @@ -79,13 +89,23 @@ public InstancedBinding Initiate(

private object ConvertValue(IList<object> values, Type targetType)
{
var converted = Converter.Convert(values, targetType, null, CultureInfo.CurrentCulture);
var culture = CultureInfo.CurrentCulture;
var converted = Converter.Convert(values, targetType, ConverterParameter, culture);

if (converted == AvaloniaProperty.UnsetValue && FallbackValue != null)
{
converted = FallbackValue;
}

// We only respect `StringFormat` if the type of the property we're assigning to will
// accept a string. Note that this is slightly different to WPF in that WPF only applies
// `StringFormat` for target type `string` (not `object`).
if (!string.IsNullOrWhiteSpace(StringFormat) &&
(targetType == typeof(string) || targetType == typeof(object)))
{
converted = string.Format(culture, StringFormat, converted);
}

return converted;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See license.md file in the project root for full license information.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using Avalonia.Controls;
using Avalonia.Data;
using Avalonia.Data.Converters;
using Avalonia.Data.Core;
using Xunit;

namespace Avalonia.Markup.UnitTests.Data
{
public class MultiBindingTests_Converters
{
[Fact]
public void StringFormat_Should_Be_Applied()
{
var textBlock = new TextBlock
{
DataContext = new MultiBindingTests_Converters.Class1(),
};

var target = new MultiBinding
{
StringFormat = "Foo + Bar = {0}",
Converter = new SumOfDoublesConverter(),
Bindings =
{
new Binding(nameof(MultiBindingTests_Converters.Class1.Foo)),
new Binding(nameof(MultiBindingTests_Converters.Class1.Bar)),
}
};

textBlock.Bind(TextBlock.TextProperty, target);

Assert.Equal("Foo + Bar = 3", textBlock.Text);
}

[Fact]
public void StringFormat_Should_Not_Be_Applied_When_Binding_To_Non_String_Or_Object()
{
var textBlock = new TextBlock
{
DataContext = new MultiBindingTests_Converters.Class1(),
};

var target = new MultiBinding
{
StringFormat = "Hello {0}",
Converter = new SumOfDoublesConverter(),
Bindings =
{
new Binding(nameof(MultiBindingTests_Converters.Class1.Foo)),
new Binding(nameof(MultiBindingTests_Converters.Class1.Bar)),
}
};

textBlock.Bind(TextBlock.WidthProperty, target);

Assert.Equal(3.0, textBlock.Width);
}

private class SumOfDoublesConverter : IMultiValueConverter
{
public object Convert(IList<object> values, Type targetType, object parameter, CultureInfo culture)
{
return values.OfType<double>().Sum();
}
}

private class Class1
{
public double Foo { get; set; } = 1;
public double Bar { get; set; } = 2;
}
}
}

0 comments on commit b3a497b

Please sign in to comment.