/// <summary> /// Creates a <see cref="DataSourceDefinition"/> structure for the specified XML document. /// </summary> /// <param name="xdocument">The XML document from which to load a data source definition.</param> /// <param name="namespace">The namespace within which to place the compiled view model.</param> /// <param name="name">The name of the data source's view model.</param> /// <param name="path">The path to the file that defines the data source.</param> /// <returns>The instance of <see cref="DataSourceDefinition"/> that was created, or <see langword="null"/> if the specified /// XML does not contain a valid view.</returns> public static DataSourceDefinition? CreateDataSourceDefinitionFromXml(XDocument xdocument, String @namespace, String name, String path) { if (xdocument.Root.Name.LocalName != "UIPanelDefinition") return null; var viewdef = xdocument.Root.Element("View"); if (viewdef == null) return null; return DataSourceDefinition.FromView(@namespace, name, path, viewdef); }
/// <summary> /// Gets a collection of <see cref="DataSourceDefinition"/> instances for any component templates which /// are currently registered with the Ultraviolet Presentation Foundation. /// </summary> /// <returns>A collection of <see cref="DataSourceDefinition"/> instances which represent UPF component template definitions.</returns> private static IEnumerable<DataSourceDefinition> RetrieveTemplateDefinitions(IExpressionCompilerState state) { if (state.ComponentTemplateManager == null) return Enumerable.Empty<DataSourceDefinition>(); var templateDefs = from template in state.ComponentTemplateManager select DataSourceDefinition.FromComponentTemplate(template.Key, template.Value.Root.Element("View")); var templateDefsList = templateDefs.ToList(); foreach (var templateDef in templateDefsList) UvmlLoader.AddUvmlAnnotations(templateDef.DataSourceWrapperName, templateDef.Definition); return templateDefsList; }
/// <summary> /// Creates a new <see cref="DataSourceWrapperInfo"/> instance which represents a particular framework template. /// </summary> public static DataSourceWrapperInfo GetDataSourceWrapperInfoForFrameworkTemplate(IExpressionCompilerState state, IEnumerable<String> references, IEnumerable<String> imports, DataSourceDefinition definition) { var dataSourceWrappedTypeAttr = definition.Definition.Attribute("ViewModelType"); if (dataSourceWrappedTypeAttr == null) { throw new BindingExpressionCompilationErrorException(definition.Definition, definition.DefinitionPath, PresentationStrings.TemplateMustSpecifyViewModelType); } var dataSourceWrappedType = Type.GetType(dataSourceWrappedTypeAttr.Value, false); if (dataSourceWrappedType == null) { throw new BindingExpressionCompilationErrorException(dataSourceWrappedTypeAttr, definition.DefinitionPath, PresentationStrings.ViewModelTypeNotFound.Format(dataSourceWrappedTypeAttr.Value)); } var dataSourceDefinition = definition; var dataSourceWrapperName = definition.DataSourceWrapperName; var expressions = new List<BindingExpressionInfo>(); foreach (var element in dataSourceDefinition.Definition.Elements()) { FindBindingExpressionsInDataSource(state, dataSourceDefinition, dataSourceWrappedType, element, expressions); } expressions = CollapseDataSourceExpressions(expressions); return new DataSourceWrapperInfo() { References = references, Imports = imports, DataSourceDefinition = dataSourceDefinition, DataSourceType = dataSourceWrappedType, DataSourceWrapperName = dataSourceWrapperName, Expressions = expressions }; }
/// <summary> /// Creates a new instance of <see cref="DataSourceWrapperInfo"/> that represents the specified data source wrapper. /// </summary> /// <param name="state">The expression compiler's current state.</param> /// <param name="dataSourceDefinition">The data source definition for which to retrieve data source wrapper info.</param> /// <returns>The <see cref="DataSourceWrapperInfo"/> that was created to represent the specified data source.</returns> public static DataSourceWrapperInfo GetDataSourceWrapperInfo(IExpressionCompilerState state, DataSourceDefinition dataSourceDefinition) { var dataSourceWrappedType = dataSourceDefinition.TemplatedControl; if (dataSourceWrappedType == null) { var definedDataSourceTypeAttr = dataSourceDefinition.Definition.Attribute("ViewModelType"); var definedDataSourceTypeName = (String)definedDataSourceTypeAttr; if (definedDataSourceTypeName == null) { return(null); } var typeNameCommaIx = definedDataSourceTypeName.IndexOf(','); if (typeNameCommaIx < 0) { throw new BindingExpressionCompilationErrorException(definedDataSourceTypeAttr, dataSourceDefinition.DefinitionPath, CompilerStrings.ViewModelTypeIsNotFullyQualified.Format(definedDataSourceTypeName)); } var definedDataSourceType = Type.GetType(definedDataSourceTypeName); if (definedDataSourceType == null) { throw new BindingExpressionCompilationErrorException(definedDataSourceTypeAttr, dataSourceDefinition.DefinitionPath, PresentationStrings.ViewModelTypeNotFound.Format(definedDataSourceTypeName)); } dataSourceWrappedType = definedDataSourceType; } var dataSourceWrapperName = dataSourceDefinition.DataSourceWrapperName; var dataSourceWrapperExpressions = new List <BindingExpressionInfo>(); foreach (var element in dataSourceDefinition.Definition.Elements()) { FindBindingExpressionsInDataSource(state, dataSourceDefinition, dataSourceWrappedType, element, dataSourceWrapperExpressions); } dataSourceWrapperExpressions = CollapseDataSourceExpressions(dataSourceWrapperExpressions); var dataSourceReferences = new List <String>(); var dataSourceImports = new List <String>(); var xmlRoot = dataSourceDefinition.Definition.Parent; var xmlDirectives = xmlRoot.Elements("Directive"); foreach (var xmlDirective in xmlDirectives) { var xmlDirectiveType = (String)xmlDirective.Attribute("Type"); if (String.IsNullOrEmpty(xmlDirectiveType)) { throw new BindingExpressionCompilationErrorException(xmlDirective, dataSourceDefinition.DefinitionPath, CompilerStrings.ViewDirectiveMustHaveType); } var xmlDirectiveTypeName = xmlDirectiveType.ToLowerInvariant(); var xmlDirectiveValue = xmlDirective.Value.Trim(); switch (xmlDirectiveTypeName) { case "import": { if (String.IsNullOrEmpty(xmlDirectiveValue)) { throw new BindingExpressionCompilationErrorException(xmlDirective, dataSourceDefinition.DefinitionPath, CompilerStrings.ViewDirectiveHasInvalidValue); } dataSourceImports.Add(xmlDirective.Value.Trim()); } break; case "reference": { if (String.IsNullOrEmpty(xmlDirectiveValue)) { throw new BindingExpressionCompilationErrorException(xmlDirective, dataSourceDefinition.DefinitionPath, CompilerStrings.ViewDirectiveHasInvalidValue); } dataSourceReferences.Add(xmlDirective.Value.Trim()); } break; default: throw new BindingExpressionCompilationErrorException(xmlDirective, dataSourceDefinition.DefinitionPath, CompilerStrings.ViewDirectiveNotRecognized.Format(xmlDirectiveTypeName)); } } var frameworkTemplates = new Dictionary <String, XElement>(); FindFrameworkTemplateElements(dataSourceDefinition.Definition, frameworkTemplates); var frameworkTemplateWrapperDefs = frameworkTemplates.Select(x => DataSourceDefinition.FromView(dataSourceDefinition.DataSourceWrapperNamespace, x.Key, dataSourceDefinition.DefinitionPath, x.Value)).ToList(); var frameworkTemplateWrapperInfos = frameworkTemplateWrapperDefs.Select(definition => GetDataSourceWrapperInfoForFrameworkTemplate(state, dataSourceReferences, dataSourceImports, definition)).ToList(); return(new DataSourceWrapperInfo() { References = dataSourceReferences, Imports = dataSourceImports, DataSourceDefinition = dataSourceDefinition, DataSourcePath = dataSourceDefinition.DefinitionPath, DataSourceType = dataSourceWrappedType, DataSourceWrapperName = dataSourceWrapperName, Expressions = dataSourceWrapperExpressions, DependentWrapperInfos = frameworkTemplateWrapperInfos }); }
/// <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); } }