/// <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); } }
/// <summary> /// Determines whether the specified target is a dependency property, routed event, or standard property/event. /// </summary> private static UvmlMutatorTarget GetMutatorTarget(UltravioletContext uv, String name, String value, Type type, out Object target, out Type targetType) { var upf = uv.GetUI().GetPresentationFoundation(); // If this is an attached property/event, find the owner type. var depname = new DependencyName(name); if (depname.IsAttached) { var attachedOwnerType = default(Type); if (!upf.GetKnownType(depname.Owner, out attachedOwnerType)) { throw new UvmlException(PresentationStrings.UnrecognizedType.Format(depname.Owner)); } type = attachedOwnerType; } // Is it a dependency property? var dprop = DependencyProperty.FindByName(depname.Name, type); if (dprop != null) { target = dprop; if (value != null && BindingExpressions.IsBindingExpression(value)) { targetType = typeof(String); return(UvmlMutatorTarget.DependencyPropertyBinding); } targetType = dprop.PropertyType; return(UvmlMutatorTarget.DependencyProperty); } // Is it a routed event? var revt = EventManager.FindByName(depname.Name, type); if (revt != null) { target = revt; targetType = typeof(String); return(UvmlMutatorTarget.RoutedEvent); } // Is it a standard property? var clrprop = type.GetProperty(depname.Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); if (clrprop != null) { target = clrprop; targetType = clrprop.PropertyType; return(UvmlMutatorTarget.StandardProperty); } // Is it a standard event? var clrevt = type.GetEvent(depname.Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); if (clrevt != null) { target = clrevt; targetType = typeof(String); return(UvmlMutatorTarget.StandardEvent); } throw new UvmlException(PresentationStrings.EventOrPropertyDoesNotExist.Format(depname.Name, type.Name)); }