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 string path = GetBindingPath(propertyGetter);
104 return new Binding(path, mode, converter, converterParameter, stringFormat);
107 internal override void Apply(bool fromTarget)
109 base.Apply(fromTarget);
111 if (_expression == null)
112 _expression = new BindingExpression(this, SelfPath);
114 _expression.Apply(fromTarget);
117 internal override void Apply(object newContext, BindableObject bindObj, BindableProperty targetProperty, bool fromBindingContextChanged = false)
119 object src = _source;
120 var isApplied = IsApplied;
122 base.Apply(src ?? newContext, bindObj, targetProperty, fromBindingContextChanged: fromBindingContextChanged);
124 if (src != null && isApplied && fromBindingContextChanged)
127 object bindingContext = src ?? Context ?? newContext;
128 if (_expression == null && bindingContext != null)
129 _expression = new BindingExpression(this, SelfPath);
131 _expression?.Apply(bindingContext, bindObj, targetProperty);
134 internal override BindingBase Clone()
136 return new Binding(Path, Mode) { Converter = Converter, ConverterParameter = ConverterParameter, StringFormat = StringFormat, Source = Source, UpdateSourceEventName = UpdateSourceEventName };
139 internal override object GetSourceValue(object value, Type targetPropertyType)
141 if (Converter != null)
142 value = Converter.Convert(value, targetPropertyType, ConverterParameter, CultureInfo.CurrentUICulture);
144 return base.GetSourceValue(value, targetPropertyType);
147 internal override object GetTargetValue(object value, Type sourcePropertyType)
149 if (Converter != null)
150 value = Converter.ConvertBack(value, sourcePropertyType, ConverterParameter, CultureInfo.CurrentUICulture);
152 return base.GetTargetValue(value, sourcePropertyType);
155 internal override void Unapply(bool fromBindingContextChanged = false)
157 if (Source != null && fromBindingContextChanged && IsApplied)
160 base.Unapply(fromBindingContextChanged: fromBindingContextChanged);
162 if (_expression != null)
163 _expression.Unapply();
167 static string GetBindingPath<TSource>(Expression<Func<TSource, object>> propertyGetter)
169 Expression expr = propertyGetter.Body;
171 var unary = expr as UnaryExpression;
173 expr = unary.Operand;
175 var builder = new StringBuilder();
179 var member = expr as MemberExpression;
182 var methodCall = expr as MethodCallExpression;
183 if (methodCall != null)
185 if (methodCall.Arguments.Count == 0)
186 throw new ArgumentException("Method calls are not allowed in binding expression");
188 var arguments = new List<string>(methodCall.Arguments.Count);
189 foreach (Expression arg in methodCall.Arguments)
191 if (arg.NodeType != ExpressionType.Constant)
192 throw new ArgumentException("Only constants can be used as indexer arguments");
194 object value = ((ConstantExpression)arg).Value;
195 arguments.Add(value != null ? value.ToString() : "null");
198 Type declarerType = methodCall.Method.DeclaringType;
199 DefaultMemberAttribute defaultMember = declarerType.GetTypeInfo().GetCustomAttributes(typeof(DefaultMemberAttribute), true).OfType<DefaultMemberAttribute>().FirstOrDefault();
200 string indexerName = defaultMember != null ? defaultMember.MemberName : "Item";
202 MethodInfo getterInfo =
203 declarerType.GetProperties().Where(pi => (pi.GetMethod != null) && pi.Name == indexerName && pi.CanRead && pi.GetMethod.IsPublic && !pi.GetMethod.IsStatic).Select(pi => pi.GetMethod).FirstOrDefault();
204 if (getterInfo != null)
206 if (getterInfo == methodCall.Method)
212 foreach (string argument in arguments)
217 builder.Append(argument);
223 member = methodCall.Object as MemberExpression;
226 throw new ArgumentException("Method calls are not allowed in binding expressions");
229 throw new ArgumentException("Public indexer not found");
232 throw new ArgumentException("Invalid expression type");
235 while (member != null)
237 var property = (PropertyInfo)member.Member;
238 if (builder.Length != 0)
241 builder.Insert(0, ".");
246 builder.Insert(0, property.Name);
248 // member = member.Expression as MemberExpression ?? (member.Expression as UnaryExpression)?.Operand as MemberExpression;
249 member = member.Expression as MemberExpression ?? (member.Expression is UnaryExpression ? (member.Expression as UnaryExpression).Operand as MemberExpression : null);
252 return builder.ToString();