| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- using System;
- using System.Globalization;
- using Avalonia.Controls;
- using Avalonia.Data;
- using Avalonia.Data.Converters;
- using Avalonia.UnitTests;
- using Xunit;
- #nullable enable
- namespace Avalonia.Base.UnitTests.Data.Core;
- public abstract partial class BindingExpressionTests
- {
- [Fact]
- public void Should_Write_Value_To_Source()
- {
- var data = new ViewModel { StringValue = "foo" };
- var target = CreateTargetWithSource(data, o => o.StringValue, mode: BindingMode.TwoWay);
- target.String = "bar";
- Assert.Equal("bar", data.StringValue);
- }
- [Fact]
- public void Should_Write_Value_To_Attached_Property_On_Source()
- {
- var data = new AvaloniaObject();
- var target = CreateTargetWithSource(
- data,
- o => o[DockPanel.DockProperty],
- mode: BindingMode.TwoWay,
- targetProperty: Control.TagProperty);
- target.Tag = Dock.Right;
- Assert.Equal(Dock.Right, data[DockPanel.DockProperty]);
- }
- [Fact]
- public void Should_Write_Indexed_Value_To_Source()
- {
- var data = new { Foo = new[] { "foo" } };
- var target = CreateTargetWithSource(data, o => o.Foo[0], mode: BindingMode.TwoWay);
- target.String = "bar";
- Assert.Equal("bar", data.Foo[0]);
- GC.KeepAlive(data);
- }
- [Fact]
- public void Should_Write_Value_To_Source_On_Simple_Property_Chain()
- {
- var data = new ViewModel { Next = new() { StringValue = "foo" } };
- var target = CreateTargetWithSource(data, o => o.Next!.StringValue, mode: BindingMode.TwoWay);
- target.String = "bar";
- Assert.Equal("bar", data.Next!.StringValue);
- }
- [Fact]
- public void Target_Value_Can_Be_Set_On_Broken_Chain()
- {
- var data = new ViewModel { Next = new() { StringValue = "foo" } };
- var target = CreateTargetWithSource(data, o => o.Next!.StringValue, mode: BindingMode.TwoWay);
- data.Next = null;
- target.String = "bar";
- Assert.Equal("bar", target.String);
- }
- [Fact]
- public void Should_Use_Converter_When_Writing_To_Source()
- {
- var data = new ViewModel { StringValue = "foo" };
- var target = CreateTargetWithSource(
- data,
- o => o.StringValue,
- mode: BindingMode.TwoWay,
- converter: new CaseConverter());
- target.String = "BaR";
- Assert.Equal("bar", data.StringValue);
- GC.KeepAlive(data);
- }
- [Fact]
- public void TwoWay_Binding_Should_Not_Write_Unchanged_Value_Back_To_Property_With_Converter()
- {
- var data = new Cat();
- var target = CreateTargetWithSource(
- data,
- o => o.WhiskerCount,
- converter: new CaseConverter(),
- mode: BindingMode.TwoWay);
- Assert.Equal(4, target.Int);
- Assert.Equal(9, data.Lives);
- data.WhiskerCount = 3;
- Assert.Equal(3, target.Int);
- Assert.Equal(8, data.Lives);
- GC.KeepAlive(data);
- }
- [Fact]
- public void Setter_Should_Convert_Double_To_String()
- {
- var data = new ViewModel { StringValue = $"{5.6}" };
- var target = CreateTargetWithSource(
- data,
- o => o.StringValue,
- mode: BindingMode.TwoWay,
- targetProperty: TargetClass.DoubleProperty);
- target.Double = 6.7;
- Assert.Equal($"{6.7}", data.StringValue);
- GC.KeepAlive(data);
- }
- [Fact]
- public void Setter_Should_Convert_String_To_Double()
- {
- var data = new ViewModel { DoubleValue = 5.6 };
- var target = CreateTargetWithSource(
- data,
- o => o.DoubleValue,
- mode: BindingMode.TwoWay,
- targetProperty: TargetClass.StringProperty);
- target.String = $"{6.7}";
- Assert.Equal(6.7, data.DoubleValue);
- GC.KeepAlive(data);
- }
- [Fact]
- public void Setting_Invalid_Double_String_Should_Not_Change_Target()
- {
- var data = new ViewModel { DoubleValue = 5.6 };
- var target = CreateTargetWithSource(
- data,
- o => o.DoubleValue,
- mode: BindingMode.TwoWay,
- targetProperty: TargetClass.StringProperty);
- target.String = "foo";
- Assert.Equal(5.6, data.DoubleValue);
- GC.KeepAlive(data);
- }
- [Fact]
- public void Setting_Invalid_Double_String_Should_Use_FallbackValue()
- {
- var data = new ViewModel { DoubleValue = 5.6 };
- var target = CreateTargetWithSource(
- data,
- o => o.DoubleValue,
- mode: BindingMode.TwoWay,
- fallbackValue: 9.8,
- targetProperty: TargetClass.StringProperty);
- target.String = "foo";
- Assert.Equal(9.8, data.DoubleValue);
- GC.KeepAlive(data);
- }
- [Fact]
- public void Should_Pass_ConverterParameter_To_Converter_ConvertBack()
- {
- var data = new ViewModel { StringValue = "Initial" };
- var converter = new PrefixConverter();
- var target = CreateTargetWithSource(
- data,
- o => o.StringValue,
- converter: converter,
- converterParameter: "foo",
- mode: BindingMode.TwoWay);
- target.String = "fooBar";
- Assert.Equal("Bar", data.StringValue);
- }
- private class Cat : NotifyingBase
- {
- private int _whiskerCount = 4;
- public int WhiskerCount
- {
- get => _whiskerCount;
- set
- {
- _whiskerCount = value;
- RaisePropertyChanged(nameof(WhiskerCount));
- --Lives;
- }
- }
- public int Lives { get; private set; } = 9;
- }
- private class CaseConverter : IValueConverter
- {
- public static readonly CaseConverter Instance = new();
- public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
- {
- return value?.ToString()?.ToUpper();
- }
- public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
- {
- return value?.ToString()?.ToLower();
- }
- }
- }
|