Browse Source

implement Setter.Value <-> Setter.Property relation without dependsOn logic

pull/916/head
Andrey Kunchev 10 years ago
parent
commit
74f53cf12b
  1. 1
      src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
  2. 48
      src/Markup/Avalonia.Markup.Xaml/Converters/SetterValueTypeConverter.cs
  3. 15
      src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaMemberAttributeProvider.cs
  4. 78
      src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlType.cs

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

@ -52,6 +52,7 @@
</Compile>
<Compile Include="AvaloniaXamlLoaderPortableXaml.cs" />
<Compile Include="AvaloniaXamlLoader.cs" />
<Compile Include="Converters\SetterValueTypeConverter.cs" />
<Compile Include="PortableXaml\XamlBinding.cs" />
<Compile Include="PortableXaml\AttributeExtensions.cs" />
<Compile Include="PortableXaml\AvaloniaMemberAttributeProvider.cs" />

48
src/Markup/Avalonia.Markup.Xaml/Converters/SetterValueTypeConverter.cs

@ -0,0 +1,48 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using Avalonia.Styling;
using Portable.Xaml;
using Portable.Xaml.ComponentModel;
using Portable.Xaml.Markup;
using System;
using System.Globalization;
namespace Avalonia.Markup.Xaml.Converters
{
public class SetterValueTypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
object setter = context.GetService<IProvideValueTarget>().TargetObject;
var schemaContext = context.GetService<IXamlSchemaContextProvider>().SchemaContext;
return ConvertSetterValue(schemaContext, (setter as Setter), value);
}
[Obsolete("TODO: try assosiate Setter.Value property with SetterValueTypeConverter, so far coouldn't make it :(")]
internal static object ConvertSetterValue(XamlSchemaContext context, Setter setter, object value)
{
Type targetType = setter?.Property?.PropertyType;
if (targetType == null)
{
return value;
}
var ttConv = context.GetXamlType(targetType)?.TypeConverter?.ConverterInstance;
if (ttConv != null)
{
value = ttConv.ConvertFromString(value as string);
}
return value;
}
}
}

15
src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaMemberAttributeProvider.cs

@ -1,4 +1,6 @@
using Portable.Xaml.ComponentModel;
using Avalonia.Markup.Xaml.Converters;
using Avalonia.Styling;
using Portable.Xaml.ComponentModel;
using System;
using System.Linq;
using System.Reflection;
@ -23,7 +25,6 @@ namespace Avalonia.Markup.Xaml.PortableXaml
{
Attribute result = null;
if (attributeType == typeof(pm.XamlDeferLoadAttribute))
{
result = _info.GetCustomAttribute<avm.TemplateContentAttribute>(inherit)
@ -34,11 +35,19 @@ namespace Avalonia.Markup.Xaml.PortableXaml
result = _info.GetCustomAttribute<avm.AmbientAttribute>(inherit)
.ToPortableXaml();
}
else if(attributeType == typeof(pm.DependsOnAttribute))
else if (attributeType == typeof(pm.DependsOnAttribute))
{
result = _info.GetCustomAttribute<avm.DependsOnAttribute>(inherit)
.ToPortableXaml();
}
else if (attributeType == typeof(TypeConverterAttribute) &&
_info.DeclaringType == typeof(Setter) &&
_info.Name == nameof(Setter.Value))
{
//actually it never comes here looks like if property type is object
//Portable.Xaml is not searching for Type Converter
result = new TypeConverterAttribute(typeof(SetterValueTypeConverter));
}
if (result == null)
{

78
src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlType.cs

@ -2,6 +2,8 @@
using Avalonia.Data;
using Avalonia.Markup.Xaml.Data;
using Avalonia.Markup.Xaml.MarkupExtensions;
using Avalonia.Metadata;
using Avalonia.Styling;
using Portable.Xaml;
using Portable.Xaml.Schema;
using System;
@ -12,7 +14,7 @@ using System.Xml.Serialization;
namespace Avalonia.Markup.Xaml.PortableXaml
{
using Metadata;
using Converters;
using PropertyKey = Tuple<Type, string>;
public class AvaloniaXamlType : XamlType
@ -190,10 +192,18 @@ namespace Avalonia.Markup.Xaml.PortableXaml
public override void SetValue(object instance, object value)
{
if (Member.DependsOn.Count == 1 &&
//can't make it work to assign TypeConverter to Setter.Value
//so we need it hard coded
//TODO: try to assosiate TypeConverter with Setter.Value
//and remove this lines
if (instance is Setter &&
Member.Name == nameof(Setter.Value) &&
value is string)
{
value = TransformDependsOnValue(instance, value);
value = SetterValueTypeConverter.ConvertSetterValue(
Member.DeclaringType.SchemaContext,
instance as Setter,
value);
}
if (value is XamlBinding)
@ -201,62 +211,42 @@ namespace Avalonia.Markup.Xaml.PortableXaml
value = (value as XamlBinding).Value;
}
if (UpdateListInsteadSet && value != null)
if (UpdateListInsteadSet &&
value != null &&
UpdateListInsteadSetValue(instance, value))
{
object old = GetValue(instance);
if (Equals(old, value))
{
//don't set the same value
//usually a collections
return;
}
else if (old is IList && value is IList)
{
var oldList = (IList)old;
var curList = (IList)value;
oldList.Clear();
foreach (object item in curList)
{
oldList.Add(item);
}
return;
}
return;
}
base.SetValue(instance, value);
}
private object TransformDependsOnValue(object instance, object value)
private bool UpdateListInsteadSetValue(object instance, object value)
{
if (value is string &&
(Member.UnderlyingMember as PropertyInfo)
.PropertyType != typeof(string))
{
var dpm = Member.DependsOn[0];
object old = GetValue(instance);
object depPropValue = dpm.Invoker.GetValue(instance);
if (Equals(old, value))
{
//don't set the same value
//usually a collections
return true;
}
else if (old is IList && value is IList)
{
var oldList = (IList)old;
var curList = (IList)value;
Type targetType = (depPropValue as AvaloniaProperty)?.PropertyType ??
(depPropValue as Type);
oldList.Clear();
if (targetType == null)
foreach (object item in curList)
{
return value;
oldList.Add(item);
}
var xamTargetType = Member.DeclaringType.SchemaContext.GetXamlType(targetType);
var ttConv = xamTargetType?.TypeConverter?.ConverterInstance;
if (ttConv != null)
{
value = ttConv.ConvertFromString(value as string);
}
return true;
}
return value;
return false;
}
}
}

Loading…
Cancel
Save