/// <summary> /// Given a targeted binding expression (in the form "foo->bar"), this method extracts the target name, target type, and expression text. /// </summary> private Boolean GetExpressionTargetInfo(IExpressionCompilerState state, DataSourceWrapperInfo dataSourceWrapperInfo, XObject source, ref String expText, out String expTarget, out Type expTargetType) { const string TargetExpressionDelimiter = "->"; var expOriginal = expText; var delimiterIndex = expText.IndexOf(TargetExpressionDelimiter); if (delimiterIndex >= 0) { var expPartTarget = expText.Substring(0, delimiterIndex); var expPartText = expText.Substring(delimiterIndex + TargetExpressionDelimiter.Length); var matchCandidates = (from element in dataSourceWrapperInfo.DataSourceDefinition.Definition.Descendants() where (String)element.Attribute("Name") == expPartTarget select element).ToList(); if (matchCandidates.Count == 0) { throw new BindingExpressionCompilationErrorException(source, dataSourceWrapperInfo.DataSourceDefinition.DefinitionPath, CompilerStrings.ExpressionTargetIsNotFound.Format(expPartTarget)); } if (matchCandidates.Count > 1) { throw new BindingExpressionCompilationErrorException(source, dataSourceWrapperInfo.DataSourceDefinition.DefinitionPath, CompilerStrings.ExpressionTargetIsAmbiguous.Format(expPartTarget)); } var match = matchCandidates.Single(); var matchName = match.Name.LocalName; expText = expPartText; expTargetType = UvmlTypeAnalysis.GetPlaceholderType(dataSourceWrapperInfo.DataSourceType, matchName); if (expTargetType == null && !state.GetKnownType(matchName, out expTargetType)) { throw new BindingExpressionCompilationErrorException(source, dataSourceWrapperInfo.DataSourceDefinition.DefinitionPath, CompilerStrings.ExpressionTargetIsUnrecognizedType.Format(expOriginal, matchName)); } expTarget = String.Format("__UPF_FindName<{0}>(\"{1}\").", CSharpLanguage.GetCSharpTypeName(expTargetType), expPartTarget); return(true); } expTarget = default(String); expTargetType = dataSourceWrapperInfo.DataSourceType; return(false); }
/// <summary> /// Searches the specified XML element tree for binding expressions and adds them to the specified collection. /// </summary> /// <param name="state">The expression compiler's current state.</param> /// <param name="dataSourceDefinition">The data source definition for the data source which is being compiled.</param> /// <param name="dataSourceWrappedType">The type for which a data source wrapper is being compiled.</param> /// <param name="element">The root of the XML element tree to search.</param> /// <param name="expressions">The list to populate with any binding expressions that are found.</param> private static void FindBindingExpressionsInDataSource(IExpressionCompilerState state, DataSourceDefinition dataSourceDefinition, Type dataSourceWrappedType, XElement element, List <BindingExpressionInfo> expressions) { var templateAnnotation = element.Annotation <FrameworkTemplateNameAnnotation>(); if (templateAnnotation != null) { return; } var elementName = element.Name.LocalName; var elementType = UvmlTypeAnalysis.GetPlaceholderType(dataSourceWrappedType, elementName); if (elementType != null || state.GetKnownType(elementName, out elementType)) { var attrs = Enumerable.Union( element.Attributes().Select(x => new { Object = (XObject)x, Name = x.Name.LocalName, Value = x.Value }), element.Elements().Where(x => x.Name.LocalName.StartsWith(elementName + ".")).Select(x => new { Object = (XObject)x, Name = x.Name.LocalName, Value = x.Value })); foreach (var attr in attrs) { var attrValue = attr.Value; if (!BindingExpressions.IsBindingExpression(attrValue)) { continue; } var dprop = FindDependencyOrAttachedPropertyByName(state, attr.Name, elementType); if (dprop == null) { throw new BindingExpressionCompilationErrorException(attr.Object, dataSourceDefinition.DefinitionPath, CompilerStrings.OnlyDependencyPropertiesCanBeBound.Format(attr.Name)); } var expText = BindingExpressions.GetBindingMemberPathPart(attrValue); var expProp = GetBindablePropertyOnDataSource(dataSourceWrappedType, expText); var expType = expProp?.PropertyType ?? dprop.PropertyType; if (typeof(DataTemplate).IsAssignableFrom(expType)) { continue; } expressions.Add(new BindingExpressionInfo(attr.Object, attrValue, expType) { GenerateGetter = true }); } if (element.Nodes().Count() == 1) { var singleChild = element.Nodes().Single(); if (singleChild.NodeType == XmlNodeType.Text) { var elementValue = ((XText)singleChild).Value; if (BindingExpressions.IsBindingExpression(elementValue)) { String defaultProperty; if (!state.GetElementDefaultProperty(elementType, out defaultProperty) || defaultProperty == null) { throw new BindingExpressionCompilationErrorException(singleChild, dataSourceDefinition.DefinitionPath, CompilerStrings.ElementDoesNotHaveDefaultProperty.Format(elementType.Name)); } var dprop = FindDependencyOrAttachedPropertyByName(state, defaultProperty, elementType); if (dprop == null) { throw new BindingExpressionCompilationErrorException(singleChild, dataSourceDefinition.DefinitionPath, CompilerStrings.OnlyDependencyPropertiesCanBeBound.Format(defaultProperty)); } var expText = BindingExpressions.GetBindingMemberPathPart(elementValue); var expProp = GetBindablePropertyOnDataSource(dataSourceWrappedType, expText); expressions.Add(new BindingExpressionInfo(singleChild, elementValue, expProp?.PropertyType ?? dprop.PropertyType) { GenerateGetter = true }); } } } } var children = element.Elements(); foreach (var child in children) { FindBindingExpressionsInDataSource(state, dataSourceDefinition, dataSourceWrappedType, child, expressions); } }