summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Core/Setter.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Xamarin.Forms.Core/Setter.cs')
-rw-r--r--Xamarin.Forms.Core/Setter.cs88
1 files changed, 88 insertions, 0 deletions
diff --git a/Xamarin.Forms.Core/Setter.cs b/Xamarin.Forms.Core/Setter.cs
new file mode 100644
index 00000000..b260e8f0
--- /dev/null
+++ b/Xamarin.Forms.Core/Setter.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Xml;
+using Xamarin.Forms.Internals;
+using Xamarin.Forms.Xaml;
+
+namespace Xamarin.Forms
+{
+ [ContentProperty("Value")]
+ public sealed class Setter : IValueProvider
+ {
+ readonly ConditionalWeakTable<BindableObject, object> _originalValues = new ConditionalWeakTable<BindableObject, object>();
+
+ public BindableProperty Property { get; set; }
+
+ public object Value { get; set; }
+
+ object IValueProvider.ProvideValue(IServiceProvider serviceProvider)
+ {
+ if (Property == null)
+ {
+ var lineInfoProvider = serviceProvider.GetService(typeof(IXmlLineInfoProvider)) as IXmlLineInfoProvider;
+ IXmlLineInfo lineInfo = lineInfoProvider != null ? lineInfoProvider.XmlLineInfo : new XmlLineInfo();
+ throw new XamlParseException("Property not set", lineInfo);
+ }
+ var valueconverter = serviceProvider.GetService(typeof(IValueConverterProvider)) as IValueConverterProvider;
+
+ Func<MemberInfo> minforetriever =
+ () =>
+ (MemberInfo)Property.DeclaringType.GetRuntimeProperty(Property.PropertyName) ?? (MemberInfo)Property.DeclaringType.GetRuntimeMethod("Get" + Property.PropertyName, new[] { typeof(BindableObject) });
+
+ object value = valueconverter.Convert(Value, Property.ReturnType, minforetriever, serviceProvider);
+ Value = value;
+ return this;
+ }
+
+ internal void Apply(BindableObject target, bool fromStyle = false)
+ {
+ if (target == null)
+ throw new ArgumentNullException("target");
+ if (Property == null)
+ return;
+
+ object originalValue = target.GetValue(Property);
+ if (!Equals(originalValue, Property.DefaultValue))
+ {
+ _originalValues.Remove(target);
+ _originalValues.Add(target, originalValue);
+ }
+
+ var dynamicResource = Value as DynamicResource;
+ var binding = Value as BindingBase;
+ if (binding != null)
+ target.SetBinding(Property, binding.Clone(), fromStyle);
+ else if (dynamicResource != null)
+ target.SetDynamicResource(Property, dynamicResource.Key, fromStyle);
+ else
+ target.SetValue(Property, Value, fromStyle);
+ }
+
+ internal void UnApply(BindableObject target, bool fromStyle = false)
+ {
+ if (target == null)
+ throw new ArgumentNullException("target");
+ if (Property == null)
+ return;
+
+ object actual = target.GetValue(Property);
+ if (!fromStyle && !Equals(actual, Value))
+ {
+ //Do not reset default value if the value has been changed
+ _originalValues.Remove(target);
+ return;
+ }
+
+ object defaultValue;
+ if (_originalValues.TryGetValue(target, out defaultValue))
+ {
+ //reset default value, unapply bindings and dynamicResource
+ target.SetValue(Property, defaultValue, fromStyle);
+ _originalValues.Remove(target);
+ }
+ else
+ target.ClearValue(Property);
+ }
+ }
+} \ No newline at end of file