Browse Source

Merge pull request #2190 from AvaloniaUI/nullable-converters

Added nullable type converter proxy
pull/2124/head
Steven Kirk 7 years ago
committed by GitHub
parent
commit
4f4f826936
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
  2. 8
      src/Markup/Avalonia.Markup.Xaml/AvaloniaTypeConverters.cs
  3. 89
      src/Markup/Avalonia.Markup.Xaml/Converters/NullableTypeConverter.cs
  4. 31
      tests/Avalonia.Markup.Xaml.UnitTests/Converters/NullableConverterTests.cs

1
src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj

@ -11,6 +11,7 @@
<Compile Include="Converters\AvaloniaUriTypeConverter.cs" />
<Compile Include="Converters\FontFamilyTypeConverter.cs" />
<Compile Include="Converters\MemberSelectorTypeConverter.cs" />
<Compile Include="Converters\NullableTypeConverter.cs" />
<Compile Include="Converters\ParseTypeConverter.cs" />
<Compile Include="Converters\SetterValueTypeConverter.cs" />
<Compile Include="Converters\TimeSpanTypeConverter.cs" />

8
src/Markup/Avalonia.Markup.Xaml/AvaloniaTypeConverters.cs

@ -51,6 +51,14 @@ namespace Avalonia.Markup.Xaml
/// <returns>The type converter.</returns>
public static Type GetTypeConverter(Type type)
{
if (type.IsConstructedGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
var inner = GetTypeConverter(type.GetGenericArguments()[0]);
if (inner == null)
return null;
return typeof(NullableTypeConverter<>).MakeGenericType(inner);
}
if (_converters.TryGetValue(type, out var result))
{
return result;

89
src/Markup/Avalonia.Markup.Xaml/Converters/NullableTypeConverter.cs

@ -0,0 +1,89 @@
using System;
using System.Collections;
using System.ComponentModel;
using System.Globalization;
namespace Avalonia.Markup.Xaml.Converters
{
public class NullableTypeConverter<T> : TypeConverter where T : TypeConverter, new()
{
private TypeConverter _inner;
public NullableTypeConverter()
{
_inner = new T();
}
public NullableTypeConverter(TypeConverter inner)
{
_inner = inner;
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (value == null)
return null;
return _inner.ConvertTo(context, culture, value, destinationType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value == null)
return null;
if (value as string == "")
return null;
return _inner.ConvertFrom(context, culture, value);
}
public override object CreateInstance(ITypeDescriptorContext context, IDictionary propertyValues)
{
return _inner.CreateInstance(context, propertyValues);
}
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
{
return _inner.GetStandardValuesSupported(context);
}
public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
{
return _inner.GetStandardValuesExclusive(context);
}
public override bool GetCreateInstanceSupported(ITypeDescriptorContext context)
{
return _inner.GetCreateInstanceSupported(context);
}
public override bool GetPropertiesSupported(ITypeDescriptorContext context)
{
return _inner.GetPropertiesSupported(context);
}
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
return _inner.GetStandardValues(context);
}
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
{
return _inner.GetProperties(context, value, attributes);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return _inner.CanConvertTo(context, destinationType);
}
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return _inner.CanConvertFrom(context, sourceType);
}
public override bool IsValid(ITypeDescriptorContext context, object value)
{
return _inner.IsValid(context, value);
}
}
}

31
tests/Avalonia.Markup.Xaml.UnitTests/Converters/NullableConverterTests.cs

@ -0,0 +1,31 @@
using Avalonia.Controls;
using Avalonia.UnitTests;
using Xunit;
namespace Avalonia.Markup.Xaml.UnitTests.Converters
{
public class ClassWithNullableProperties
{
public Thickness? Thickness { get; set; }
public Orientation? Orientation { get; set; }
}
public class NullableConverterTests
{
[Fact]
public void Nullable_Types_Should_Still_Be_Converted_Properly()
{
using (UnitTestApplication.Start(TestServices.MockPlatformWrapper))
{
var xaml = @"<ClassWithNullableProperties
xmlns='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Converters'
Thickness = '5' Orientation='Vertical'
></ClassWithNullableProperties>";
var loader = new AvaloniaXamlLoader();
var data = (ClassWithNullableProperties)loader.Load(xaml, typeof(ClassWithNullableProperties).Assembly);
Assert.Equal(new Thickness(5), data.Thickness);
Assert.Equal(Orientation.Vertical, data.Orientation);
}
}
}
}
Loading…
Cancel
Save