csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
232 lines
6.1 KiB
232 lines
6.1 KiB
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();
|
|
}
|
|
}
|
|
}
|
|
|