/// <summary> /// Gets all data context on the path to root /// </summary> public static object[] GetDataContexts(DotvvmBindableControl contextControl, bool seeThis) { var context = seeThis ? contextControl.GetValue(DotvvmBindableControl.DataContextProperty, false) : null; return (context == null ? new object[0] : new[] { context }) .Concat(contextControl.GetAllAncestors().OfType<DotvvmBindableControl>() .Where(c => c.properties.ContainsKey(DotvvmBindableControl.DataContextProperty)) .Select(c => c.GetValue(DotvvmBindableControl.DataContextProperty, false))) .ToArray(); }
/// <summary> /// Evaluates the data context path and returns the visitor with hierarchy. /// </summary> private ExpressionEvaluationVisitor EvaluateDataContextPath(DotvvmBindableControl contextControl) { // get the hierarchy of DataContext the control is in var dataContexts = contextControl.GetAllAncestors().OfType<DotvvmBindableControl>() .Select(c => new { Binding = c.GetBinding(DotvvmBindableControl.DataContextProperty, false), Control = c }) .Where(b => b.Binding != null) .ToList(); // evaluate the DataContext path var viewRoot = contextControl.GetRoot(); var visitor = new ExpressionEvaluationVisitor(GetRootDataContext(viewRoot), viewRoot) { AllowMethods = AllowMethods }; for (var i = dataContexts.Count - 1; i >= 0; i--) { var binding = dataContexts[i].Binding; if (!(binding is ValueBindingExpression)) { throw new Exception("The DataContext property can only contain value bindings!"); // TODO: exception handling } var pathExpression = ((ValueBindingExpression)binding).GetViewModelPathExpression(dataContexts[i].Control, DotvvmBindableControl.DataContextProperty); EvaluateBinding(visitor, binding.Expression, pathExpression); } return visitor; }