2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Globalization;
6 using System.Linq.Expressions;
7 using System.Reflection;
9 using Tizen.NUI.Binding.Internals;
11 namespace Tizen.NUI.Binding
13 internal sealed class Binding : BindingBase
15 internal const string SelfPath = ".";
16 IValueConverter _converter;
17 object _converterParameter;
19 BindingExpression _expression;
22 string _updateSourceEventName;
28 public Binding(string path, BindingMode mode = BindingMode.Default, IValueConverter converter = null, object converterParameter = null, string stringFormat = null, object source = null)
31 throw new ArgumentNullException("path");
32 if (string.IsNullOrWhiteSpace(path))
33 throw new ArgumentException("path can not be an empty string", "path");
36 Converter = converter;
37 ConverterParameter = converterParameter;
39 StringFormat = stringFormat;
43 public IValueConverter Converter
45 get { return _converter; }
54 public object ConverterParameter
56 get { return _converterParameter; }
61 _converterParameter = value;
73 _expression = new BindingExpression(this, !string.IsNullOrWhiteSpace(value) ? value : SelfPath);
79 get { return _source; }
87 [EditorBrowsable(EditorBrowsableState.Never)]
88 public string UpdateSourceEventName {
89 get { return _updateSourceEventName; }
92 _updateSourceEventName = value;
97 public static Binding Create<TSource>(Expression<Func<TSource, object>> propertyGetter, BindingMode mode = BindingMode.Default, IValueConverter converter = null, object converterParameter = null,
98 string stringFormat = null)
100 if (propertyGetter == null)
101 throw new ArgumentNullException("propertyGetter");
103 return new Binding(GetBindingPath(propertyGetter), mode, converter, converterParameter, stringFormat);
106 internal override void Apply(bool fromTarget)
108 base.Apply(fromTarget);
110 if (_expression == null)
111 _expression = new BindingExpression(this, SelfPath);
113 _expression.Apply(fromTarget);
116 internal override void Apply(object newContext, BindableObject bindObj, BindableProperty targetProperty, bool fromBindingContextChanged = false)
118 object src = _source;
119 var isApplied = IsApplied;
121 base.Apply(src ?? newContext, bindObj, targetProperty, fromBindingContextChanged: fromBindingContextChanged);
123 if (src != null && isApplied && fromBindingContextChanged)
126 object bindingContext = src ?? Context ?? newContext;
127 if (_expression == null && bindingContext != null)
128 _expression = new BindingExpression(this, SelfPath);
130 _expression?.Apply(bindingContext, bindObj, targetProperty);
133 internal override BindingBase Clone()
135 return new Binding(Path, Mode) { Converter = Converter, ConverterParameter = ConverterParameter, StringFormat = StringFormat, Source = Source, UpdateSourceEventName = UpdateSourceEventName };
138 internal override object GetSourceValue(object value, Type targetPropertyType)
140 if (Converter != null)
141 value = Converter.Convert(value, targetPropertyType, ConverterParameter, CultureInfo.CurrentUICulture);
143 return base.GetSourceValue(value, targetPropertyType);
146 internal override object GetTargetValue(object value, Type sourcePropertyType)
148 if (Converter != null)
149 value = Converter.ConvertBack(value, sourcePropertyType, ConverterParameter, CultureInfo.CurrentUICulture);
151 return base.GetTargetValue(value, sourcePropertyType);
154 internal override void Unapply(bool fromBindingContextChanged = false)
156 if (Source != null && fromBindingContextChanged && IsApplied)
159 base.Unapply(fromBindingContextChanged: fromBindingContextChanged);
161 if (_expression != null)
162 _expression.Unapply();
166 static string GetBindingPath<TSource>(Expression<Func<TSource, object>> propertyGetter)
168 Expression expr = propertyGetter.Body;
170 var unary = expr as UnaryExpression;
172 expr = unary.Operand;
174 var builder = new StringBuilder();
178 var member = expr as MemberExpression;
181 var methodCall = expr as MethodCallExpression;
182 if (methodCall != null)
184 if (methodCall.Arguments.Count == 0)
185 throw new ArgumentException("Method calls are not allowed in binding expression");
187 var arguments = new List<string>(methodCall.Arguments.Count);
188 foreach (Expression arg in methodCall.Arguments)
190 if (arg.NodeType != ExpressionType.Constant)
191 throw new ArgumentException("Only constants can be used as indexer arguments");
193 object value = ((ConstantExpression)arg).Value;
194 arguments.Add(value != null ? value.ToString() : "null");
197 Type declarerType = methodCall.Method.DeclaringType;
198 DefaultMemberAttribute defaultMember = declarerType.GetTypeInfo().GetCustomAttributes(typeof(DefaultMemberAttribute), true).OfType<DefaultMemberAttribute>().FirstOrDefault();
199 string indexerName = defaultMember != null ? defaultMember.MemberName : "Item";
201 MethodInfo getterInfo =
202 declarerType.GetProperties().Where(pi => pi.Name == indexerName && pi.CanRead && pi.GetMethod.IsPublic && !pi.GetMethod.IsStatic).Select(pi => pi.GetMethod).FirstOrDefault();
203 if (getterInfo != null)
205 if (getterInfo == methodCall.Method)
211 foreach (string argument in arguments)
216 builder.Append(argument);
222 member = methodCall.Object as MemberExpression;
225 throw new ArgumentException("Method calls are not allowed in binding expressions");
228 throw new ArgumentException("Public indexer not found");
231 throw new ArgumentException("Invalid expression type");
234 while (member != null)
236 var property = (PropertyInfo)member.Member;
237 if (builder.Length != 0)
240 builder.Insert(0, ".");
245 builder.Insert(0, property.Name);
247 //member = member.Expression as MemberExpression ?? (member.Expression as UnaryExpression)?.Operand as MemberExpression;
248 member = member.Expression as MemberExpression ?? (member.Expression is UnaryExpression ? (member.Expression as UnaryExpression).Operand as MemberExpression : null);
251 return builder.ToString();