AvaloniaObjectTests_MultiBinding.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. // Copyright (c) The Avalonia Project. All rights reserved.
  2. // Licensed under the MIT license. See licence.md file in the project root for full license information.
  3. using System.Collections.Generic;
  4. using System.Globalization;
  5. using System.Linq;
  6. using System.Reactive.Linq;
  7. using System.Reactive.Subjects;
  8. using Avalonia.Data;
  9. using Avalonia.Data.Converters;
  10. using Xunit;
  11. namespace Avalonia.Base.UnitTests
  12. {
  13. public class AvaloniaObjectTests_MultiBinding
  14. {
  15. [Fact]
  16. public void Should_Update()
  17. {
  18. var target = new Class1();
  19. var b = new Subject<object>();
  20. var mb = new MultiBinding()
  21. {
  22. Converter = StringJoinConverter,
  23. Bindings = new[]
  24. {
  25. b.ToBinding()
  26. }
  27. };
  28. target.Bind(Class1.FooProperty, mb);
  29. Assert.Equal(null, target.Foo);
  30. b.OnNext("Foo");
  31. Assert.Equal("Foo", target.Foo);
  32. b.OnNext("Bar");
  33. Assert.Equal("Bar", target.Foo);
  34. }
  35. [Fact]
  36. public void Should_Update_With_Multiple_Bindings()
  37. {
  38. var target = new Class1();
  39. var bindings = Enumerable.Range(0, 3).Select(i => new BehaviorSubject<object>("Empty")).ToArray();
  40. var mb = new MultiBinding()
  41. {
  42. Converter = StringJoinConverter,
  43. Bindings = bindings.Select(b => b.ToBinding()).ToArray()
  44. };
  45. target.Bind(Class1.FooProperty, mb);
  46. Assert.Equal("Empty,Empty,Empty", target.Foo);
  47. bindings[0].OnNext("Foo");
  48. Assert.Equal("Foo,Empty,Empty", target.Foo);
  49. bindings[1].OnNext("Bar");
  50. Assert.Equal("Foo,Bar,Empty", target.Foo);
  51. bindings[2].OnNext("Baz");
  52. Assert.Equal("Foo,Bar,Baz", target.Foo);
  53. }
  54. [Fact]
  55. public void Should_Update_When_Null_Value_In_Bindings()
  56. {
  57. var target = new Class1();
  58. var b = new Subject<object>();
  59. var mb = new MultiBinding()
  60. {
  61. Converter = StringJoinConverter,
  62. Bindings = new[]
  63. {
  64. b.ToBinding()
  65. }
  66. };
  67. target.Bind(Class1.FooProperty, mb);
  68. Assert.Equal(null, target.Foo);
  69. b.OnNext("Foo");
  70. Assert.Equal("Foo", target.Foo);
  71. b.OnNext(null);
  72. Assert.Equal("", target.Foo);
  73. }
  74. [Fact]
  75. public void Should_Update_When_Null_Value_In_Bindings_With_StringFormat()
  76. {
  77. var target = new Class1();
  78. var b = new Subject<object>();
  79. var mb = new MultiBinding()
  80. {
  81. StringFormat = "Converted: {0}",
  82. Bindings = new[]
  83. {
  84. b.ToBinding()
  85. }
  86. };
  87. target.Bind(Class1.FooProperty, mb);
  88. Assert.Equal(null, target.Foo);
  89. b.OnNext("Foo");
  90. Assert.Equal("Converted: Foo", target.Foo);
  91. b.OnNext(null);
  92. Assert.Equal("Converted: ", target.Foo);
  93. }
  94. [Fact]
  95. public void MultiValueConverter_Should_Not_Skip_Valid_Null_ReferenceType_Value()
  96. {
  97. var target = new FuncMultiValueConverter<string, string>(v => string.Join(",", v.ToArray()));
  98. object value = target.Convert(new[] { "Foo", "Bar", "Baz" }, typeof(string), null, CultureInfo.InvariantCulture);
  99. Assert.Equal("Foo,Bar,Baz", value);
  100. value = target.Convert(new[] { null, "Bar", "Baz" }, typeof(string), null, CultureInfo.InvariantCulture);
  101. Assert.Equal(",Bar,Baz", value);
  102. }
  103. [Fact]
  104. public void MultiValueConverter_Should_Not_Skip_Valid_Default_ValueType_Value()
  105. {
  106. var target = new FuncMultiValueConverter<StringValueTypeWrapper, string>(v => string.Join(",", v.ToArray()));
  107. IList<object> create(string[] values) =>
  108. values.Select(v => (object)(v != null ? new StringValueTypeWrapper() { Value = v } : default)).ToList();
  109. object value = target.Convert(create(new[] { "Foo", "Bar", "Baz" }), typeof(string), null, CultureInfo.InvariantCulture);
  110. Assert.Equal("Foo,Bar,Baz", value);
  111. value = target.Convert(create(new[] { null, "Bar", "Baz" }), typeof(string), null, CultureInfo.InvariantCulture);
  112. Assert.Equal(",Bar,Baz", value);
  113. }
  114. private struct StringValueTypeWrapper
  115. {
  116. public string Value;
  117. public override string ToString() => Value;
  118. }
  119. private static IMultiValueConverter StringJoinConverter = new FuncMultiValueConverter<object, string>(v => string.Join(",", v.ToArray()));
  120. private class Class1 : AvaloniaObject
  121. {
  122. public static readonly StyledProperty<string> FooProperty =
  123. AvaloniaProperty.Register<Class1, string>("Foo");
  124. public string Foo
  125. {
  126. get => GetValue(FooProperty);
  127. set => SetValue(FooProperty, value);
  128. }
  129. }
  130. }
  131. }