/// <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);
            }
        }
Beispiel #2
0
        /// <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));
        }