diff --git a/src/Markup/Avalonia.Markup/Data/MultiBinding.cs b/src/Markup/Avalonia.Markup/Data/MultiBinding.cs index 7aa1eed890..cbc5f414f2 100644 --- a/src/Markup/Avalonia.Markup/Data/MultiBinding.cs +++ b/src/Markup/Avalonia.Markup/Data/MultiBinding.cs @@ -48,7 +48,7 @@ namespace Avalonia.Data /// Gets or sets the binding priority. /// public BindingPriority Priority { get; set; } - + /// /// Gets or sets the relative source for the binding. /// @@ -77,12 +77,12 @@ namespace Avalonia.Data // 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) && + if (!string.IsNullOrWhiteSpace(StringFormat) && (targetType == typeof(string) || targetType == typeof(object))) { converter = new StringFormatMultiValueConverter(StringFormat, converter); } - + var children = Bindings.Select(x => x.Initiate(target, null)); var input = children.Select(x => x.Observable) @@ -116,7 +116,16 @@ namespace Avalonia.Data } var culture = CultureInfo.CurrentCulture; - var converted = converter.Convert(values, targetType, ConverterParameter, culture); + values = new System.Collections.ObjectModel.ReadOnlyCollection(values); + object converted; + if (converter != null) + { + converted = converter.Convert(values, targetType, ConverterParameter, culture); + } + else + { + converted = values; + } if (converted == null) { diff --git a/tests/Avalonia.Markup.UnitTests/Data/MultiBindingTests.cs b/tests/Avalonia.Markup.UnitTests/Data/MultiBindingTests.cs index 64f5eb2a0e..b87922aa1e 100644 --- a/tests/Avalonia.Markup.UnitTests/Data/MultiBindingTests.cs +++ b/tests/Avalonia.Markup.UnitTests/Data/MultiBindingTests.cs @@ -157,6 +157,29 @@ namespace Avalonia.Markup.UnitTests.Data Assert.Equal("1,2,Fallback", target.Text); } + [Fact] + public void MultiBinding_Without_StringFormat_And_Converter() + { + var source = new { A = 1, B = 2, C = 3 }; + var target = new ItemsControl { }; + + var binding = new MultiBinding + { + Bindings = new[] + { + new Binding { Path = "A", Source = source }, + new Binding { Path = "B", Source = source }, + new Binding { Path = "C", Source = source }, + }, + }; + + target.Bind(ItemsControl.ItemsProperty, binding); + Assert.Equal(target.ItemCount, 3); + Assert.Equal(target.Items.ElementAt(0), source.A); + Assert.Equal(target.Items.ElementAt(1), source.B); + Assert.Equal(target.Items.ElementAt(2), source.C); + } + private class ConcatConverter : IMultiValueConverter { public object Convert(IList values, Type targetType, object parameter, CultureInfo culture) diff --git a/tests/Avalonia.Markup.UnitTests/Extensions/IEnummerableExtension.cs b/tests/Avalonia.Markup.UnitTests/Extensions/IEnummerableExtension.cs new file mode 100644 index 0000000000..0d9e2969e1 --- /dev/null +++ b/tests/Avalonia.Markup.UnitTests/Extensions/IEnummerableExtension.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections; + +namespace Avalonia.Markup.UnitTests +{ + internal static class IEnumerableExtensions + { + public static object ElementAt(this IEnumerable source, int index) + { + var i = -1; + var enumerator = source.GetEnumerator(); + + while (enumerator.MoveNext() && ++i < index); + if (i == index) + { + return enumerator.Current; + } + throw new ArgumentOutOfRangeException(nameof(index)); + } + } +}