From 0ee80f83cc0ce44fa41d9016eefb904d804015d0 Mon Sep 17 00:00:00 2001 From: jogibear9988 Date: Wed, 19 Nov 2014 22:56:43 +0100 Subject: [PATCH] - Parse of App.Xaml - Parse of Frameworktemplates wich have References to Parent Resources (not yet App.Xaml Resources) - Fixes in Xaml Parser (Attached Events, Attached Properties not always have both, a Setter and a Getter) --- .../WpfDesign.AddIn/Src/MyTypeFinder.cs | 16 +++ .../WpfDesign.AddIn/Src/WpfViewContent.cs | 47 +++++++ .../Tests/XamlDom/SamplesTests.cs | 20 +++ .../Project/TemplateHelper.cs | 121 +++++++++++++++--- .../Project/XamlObjectServiceProvider.cs | 2 +- .../WpfDesign.XamlDom/Project/XamlParser.cs | 58 ++++++++- .../WpfDesign.XamlDom/Project/XamlProperty.cs | 8 +- .../Project/XamlTypeFinder.cs | 6 + 8 files changed, 249 insertions(+), 29 deletions(-) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/MyTypeFinder.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/MyTypeFinder.cs index cb867140e6..e14941e535 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/MyTypeFinder.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/MyTypeFinder.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.IO; using System.Linq; using System.Reflection; using System.Runtime.ExceptionServices; @@ -73,6 +74,21 @@ namespace ICSharpCode.WpfDesign.AddIn } } + public override Uri ConvertUriToLocalUri(Uri uri) + { + if (!uri.IsAbsoluteUri) + { + var compilation = SD.ParserService.GetCompilationForFile(file.FileName); + var assembly = this.typeResolutionService.LoadAssembly(compilation.MainAssembly); + var prj = SD.ProjectService.CurrentProject; + + var newUri = new Uri(("file://" + Path.Combine(prj.Directory, uri.OriginalString)).Replace("\\","/"), UriKind.RelativeOrAbsolute); + return newUri; + } + + return uri; + } + Assembly FindAssemblyInProjectReferences(string name) { IProject pc = GetProject(file); diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/WpfViewContent.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/WpfViewContent.cs index fdca8ae69b..3389ff958f 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/WpfViewContent.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/WpfViewContent.cs @@ -22,6 +22,7 @@ using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Linq; +using System.Reflection; using System.Threading; using System.Threading.Tasks; using System.Windows; @@ -32,6 +33,7 @@ using System.Xml; using ICSharpCode.Core.Presentation; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.SharpDevelop; +using ICSharpCode.SharpDevelop.Designer; using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Gui; @@ -44,6 +46,7 @@ using ICSharpCode.WpfDesign.Designer.OutlineView; using ICSharpCode.WpfDesign.Designer.PropertyGrid; using ICSharpCode.WpfDesign.Designer.Services; using ICSharpCode.WpfDesign.Designer.Xaml; +using ICSharpCode.WpfDesign.XamlDom; namespace ICSharpCode.WpfDesign.AddIn { @@ -60,6 +63,10 @@ namespace ICSharpCode.WpfDesign.AddIn this.TabPageText = "${res:FormsDesigner.DesignTabPages.DesignTabPage}"; this.IsActiveViewContentChanged += OnIsActiveViewContentChanged; + + var compilation = SD.ParserService.GetCompilationForFile(file.FileName); + _path = Path.GetDirectoryName(compilation.MainAssembly.UnresolvedAssembly.Location); + AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; } static WpfViewContent() @@ -101,6 +108,8 @@ namespace ICSharpCode.WpfDesign.AddIn if (outline != null) { outline.Root = null; } + + using (XmlTextReader r = new XmlTextReader(stream)) { XamlLoadSettings settings = new XamlLoadSettings(); settings.DesignerAssemblies.Add(typeof(WpfViewContent).Assembly); @@ -129,9 +138,46 @@ namespace ICSharpCode.WpfDesign.AddIn } catch (Exception e) { this.UserContent = new WpfDocumentError(e); } + + try{ + var appXaml = SD.ProjectService.CurrentProject.Items.FirstOrDefault(x=>x.FileName.GetFileName().ToLower() == ("app.xaml")); + if (appXaml!=null){ + var f=appXaml as FileProjectItem; + OpenedFile a = SD.FileService.GetOrCreateOpenedFile(f.FileName); + + var xml = XmlReader.Create(a.OpenRead()); + var doc=new XmlDocument(); + doc.Load(xml); + var node = doc.FirstChild.ChildNodes.Cast().FirstOrDefault(x=>x.Name=="Application.Resources"); + + foreach (XmlAttribute att in doc.FirstChild.Attributes.Cast().ToList()) + { + if (att.Name.StartsWith("xmlns")) + node.Attributes.Append(att); + } + + var appXamlXml = XmlReader.Create(new StringReader(node.InnerXml)); + var parsed = XamlParser.Parse(appXamlXml, ((XamlDesignContext) designer.DesignContext).ParserSettings); + var dict = (ResourceDictionary)parsed.RootInstance; + designer.DesignPanel.Resources.MergedDictionaries.Add(dict); + } + } + catch (Exception) + { } } } + System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) + { + var assemblyName = (new AssemblyName(args.Name)); + string fileName = Path.Combine(_path, assemblyName.Name) + ".dll"; + if (File.Exists(fileName)) + return typeResolutionService.LoadAssembly(fileName); + return null; + } + + private TypeResolutionService typeResolutionService = new TypeResolutionService(); + private string _path; private MemoryStream _stream; bool wasChangedInDesigner; @@ -285,6 +331,7 @@ namespace ICSharpCode.WpfDesign.AddIn public override void Dispose() { + AppDomain.CurrentDomain.AssemblyResolve -= CurrentDomain_AssemblyResolve; SD.ProjectService.ProjectItemAdded -= OnReferenceAdded; propertyContainer.Clear(); diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/XamlDom/SamplesTests.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/XamlDom/SamplesTests.cs index 6dc0487c85..91c1d4aa35 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/XamlDom/SamplesTests.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/XamlDom/SamplesTests.cs @@ -504,6 +504,26 @@ namespace ICSharpCode.WpfDesign.Tests.XamlDom "); } + [Test] + public void Template2() + { + TestLoading(@" + + + + + + + + + + + + + +"); + } [Test] public void ListBox1() diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/TemplateHelper.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/TemplateHelper.cs index 263659a057..7b868dd28b 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/TemplateHelper.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/TemplateHelper.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; @@ -24,39 +25,119 @@ using System.Reflection; using System.Windows; using System.Windows.Controls; using System.Windows.Markup; +using System.Xaml; using System.Xml; using System.Xml.XPath; namespace ICSharpCode.WpfDesign.XamlDom { - public static class TemplateHelper + public class TemplateHelperResourceDictionary : ResourceDictionary, IDictionary { - public static FrameworkTemplate GetFrameworkTemplate(XmlElement xmlElement) + void IDictionary.Add(object key, object value) { - var nav = xmlElement.CreateNavigator(); + base.Add(key == null ? "$$temp&&ยงยง%%__" : key, value); + } + } - var ns = new Dictionary(); - while (true) + public static class TemplateHelper + { + public static FrameworkTemplate GetFrameworkTemplate(XmlElement xmlElement, XamlObject parentObject) + { + try { - var nsInScope = nav.GetNamespacesInScope(XmlNamespaceScope.ExcludeXml); - foreach (var ak in nsInScope) + var nav = xmlElement.CreateNavigator(); + + var ns = new Dictionary(); + while (true) { - if (!ns.ContainsKey(ak.Key) && ak.Key != "") - ns.Add(ak.Key, ak.Value); + var nsInScope = nav.GetNamespacesInScope(XmlNamespaceScope.ExcludeXml); + foreach (var ak in nsInScope) + { + if (!ns.ContainsKey(ak.Key) && ak.Key != "") + ns.Add(ak.Key, ak.Value); + } + if (!nav.MoveToParent()) + break; } - if (!nav.MoveToParent()) - break; - } - foreach (var dictentry in ns) - { - xmlElement.SetAttribute("xmlns:" + dictentry.Key, dictentry.Value); + foreach (var dictentry in ns) + { + xmlElement.SetAttribute("xmlns:" + dictentry.Key, dictentry.Value); + } + + var xaml = xmlElement.OuterXml; + xaml = "" + xaml + ""; + StringReader stringReader = new StringReader(xaml); + XmlReader xmlReader = XmlReader.Create(stringReader); + var xamlReader = new XamlXmlReader(xmlReader, parentObject.ServiceProvider.SchemaContext); + + var seti = new XamlObjectWriterSettings(); + + var resourceDictionary = new ResourceDictionary(); + var obj = parentObject; + while (obj != null) + { + if (obj.Instance is ResourceDictionary) + { + var r = obj.Instance as ResourceDictionary; + foreach (var k in r.Keys) + { + if (!resourceDictionary.Contains(k)) + resourceDictionary.Add(k, r[k]); + } + } + else if (obj.Instance is FrameworkElement) + { + var r = ((FrameworkElement)obj.Instance).Resources; + foreach (var k in r.Keys) + { + if (!resourceDictionary.Contains(k)) + resourceDictionary.Add(k, r[k]); + } + } + + obj = obj.ParentObject; + } + + seti.BeforePropertiesHandler = (s, e) => + { + if (seti.BeforePropertiesHandler != null) + { + var rr = e.Instance as ResourceDictionary; + rr.MergedDictionaries.Add(resourceDictionary); + seti.BeforePropertiesHandler = null; + } + }; + + var writer = new XamlObjectWriter(parentObject.ServiceProvider.SchemaContext, seti); + + XamlServices.Transform(xamlReader, writer); + + var result = (ResourceDictionary)writer.Result; + + var enr = result.Keys.GetEnumerator(); + enr.MoveNext(); + var rdKey = enr.Current; + + var template = result[rdKey] as FrameworkTemplate; + result.Remove(rdKey); + return template; } - - var xaml = xmlElement.OuterXml; - StringReader stringReader = new StringReader(xaml); - XmlReader xmlReader = XmlReader.Create(stringReader); - return (FrameworkTemplate)XamlReader.Load(xmlReader); + catch (Exception) + { } + + return null; + } + + + private static Stream GenerateStreamFromString(string s) + { + MemoryStream stream = new MemoryStream(); + StreamWriter writer = new StreamWriter(stream); + writer.Write(s); + writer.Flush(); + stream.Position = 0; + return stream; } } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlObjectServiceProvider.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlObjectServiceProvider.cs index 0afa53096f..76fb65d3a4 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlObjectServiceProvider.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlObjectServiceProvider.cs @@ -136,7 +136,7 @@ namespace ICSharpCode.WpfDesign.XamlDom { get { - return iCsharpXamlSchemaContext = iCsharpXamlSchemaContext ?? new XamlSchemaContext(); + return iCsharpXamlSchemaContext = iCsharpXamlSchemaContext ?? System.Windows.Markup.XamlReader.GetWpfSchemaContext(); // new XamlSchemaContext(); } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs index 06f637ddcb..5fc3c57c4e 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs @@ -146,6 +146,8 @@ namespace ICSharpCode.WpfDesign.XamlDom static Type FindType(XamlTypeFinder typeFinder, string namespaceUri, string localName) { Type elementType = typeFinder.GetType(namespaceUri, localName); + if (elementType == null) + elementType = typeFinder.GetType(namespaceUri, localName+"Extension"); if (elementType == null) throw new XamlLoadException("Cannot find type " + localName + " in " + namespaceUri); return elementType; @@ -195,7 +197,7 @@ namespace ICSharpCode.WpfDesign.XamlDom if (typeof (FrameworkTemplate).IsAssignableFrom(elementType)) { - var xamlObj = new XamlObject(document, element, elementType, TemplateHelper.GetFrameworkTemplate(element)); + var xamlObj = new XamlObject(document, element, elementType, TemplateHelper.GetFrameworkTemplate(element, currentXamlObject)); xamlObj.ParentObject = currentXamlObject; return xamlObj; } @@ -323,8 +325,11 @@ namespace ICSharpCode.WpfDesign.XamlDom if (defaultProperty == null && obj.Instance != null && CollectionSupport.IsCollectionType(obj.Instance.GetType())) { XamlObject parentObj = obj.ParentObject; var parentElement = element.ParentNode; - XamlPropertyInfo propertyInfo = GetPropertyInfo(settings.TypeFinder, parentObj.Instance, parentObj.ElementType, parentElement.NamespaceURI, parentElement.LocalName); - collectionProperty = FindExistingXamlProperty(parentObj, propertyInfo); + XamlPropertyInfo propertyInfo; + if (parentObj != null) { + propertyInfo = GetPropertyInfo(settings.TypeFinder, parentObj.Instance, parentObj.ElementType, parentElement.NamespaceURI, parentElement.LocalName); + collectionProperty = FindExistingXamlProperty(parentObj, propertyInfo); + } collectionInstance = obj.Instance; collectionType = obj.ElementType; collectionPropertyElement = element; @@ -500,6 +505,7 @@ namespace ICSharpCode.WpfDesign.XamlDom if (eventInfo != null) { return new XamlEventPropertyInfo(eventInfo); } + throw new XamlLoadException("property " + propertyName + " not found"); } @@ -507,23 +513,42 @@ namespace ICSharpCode.WpfDesign.XamlDom { MethodInfo getMethod = elementType.GetMethod("Get" + propertyName, BindingFlags.Public | BindingFlags.Static); MethodInfo setMethod = elementType.GetMethod("Set" + propertyName, BindingFlags.Public | BindingFlags.Static); - if (getMethod != null && setMethod != null) { + if (getMethod != null || setMethod != null) { FieldInfo field = elementType.GetField(propertyName + "Property", BindingFlags.Public | BindingFlags.Static); if (field != null && field.FieldType == typeof(DependencyProperty)) { return new XamlDependencyPropertyInfo((DependencyProperty)field.GetValue(null), true); } } - + if (elementType.BaseType != null) { return TryFindAttachedProperty(elementType.BaseType, propertyName); } return null; } - + + internal static XamlPropertyInfo TryFindAttachedEvent(Type elementType, string propertyName) + { + FieldInfo fieldEvent = elementType.GetField(propertyName + "Event", BindingFlags.Public | BindingFlags.Static); + if (fieldEvent != null && fieldEvent.FieldType == typeof(RoutedEvent)) + { + return new XamlEventPropertyInfo(TypeDescriptor.GetEvents(elementType)[propertyName]); + } + + if (elementType.BaseType != null) + { + return TryFindAttachedEvent(elementType.BaseType, propertyName); + } + + return null; + } static XamlPropertyInfo FindAttachedProperty(Type elementType, string propertyName) { XamlPropertyInfo pi = TryFindAttachedProperty(elementType, propertyName); + + if (pi == null) { + pi = TryFindAttachedEvent(elementType, propertyName); + } if (pi != null) { return pi; } else { @@ -555,7 +580,12 @@ namespace ICSharpCode.WpfDesign.XamlDom return FindAttachedProperty(typeof(DesignTimeProperties), attribute.LocalName); } else if (attribute.LocalName == "IsLocked" && attribute.NamespaceURI == XamlConstants.DesignTimeNamespace) { return FindAttachedProperty(typeof(DesignTimeProperties), attribute.LocalName); + } else if (attribute.LocalName == "LayoutOverrides" && attribute.NamespaceURI == XamlConstants.DesignTimeNamespace) { + return FindAttachedProperty(typeof(DesignTimeProperties), attribute.LocalName); + } else if (attribute.LocalName == "LayoutRounding" && attribute.NamespaceURI == XamlConstants.DesignTimeNamespace) { + return FindAttachedProperty(typeof(DesignTimeProperties), attribute.LocalName); } + return null; } @@ -759,7 +789,7 @@ namespace ICSharpCode.WpfDesign.XamlDom } } } - + /// /// Method use to parse a piece of Xaml. /// @@ -768,6 +798,19 @@ namespace ICSharpCode.WpfDesign.XamlDom /// Parser settings used by . /// Returns the XamlObject of the parsed . public static XamlObject ParseSnippet(XamlObject root, string xaml, XamlParserSettings settings) + { + return ParseSnippet(root, xaml, settings, null); + } + + /// + /// Method use to parse a piece of Xaml. + /// + /// The Root XamlObject of the current document. + /// The Xaml being parsed. + /// Parser settings used by . + /// Parent Object, where the Parsed snippet will be inserted (Needed for Example for Bindings). + /// Returns the XamlObject of the parsed . + public static XamlObject ParseSnippet(XamlObject root, string xaml, XamlParserSettings settings, XamlObject parentObject) { XmlTextReader reader = new XmlTextReader(new StringReader(xaml)); var element = root.OwnerDocument.XmlDocument.ReadNode(reader); @@ -785,6 +828,7 @@ namespace ICSharpCode.WpfDesign.XamlDom parser.settings = settings; parser.errorSink = (IXamlErrorSink)settings.ServiceProvider.GetService(typeof(IXamlErrorSink)); parser.document = root.OwnerDocument; + parser.currentXamlObject = parentObject; var xamlObject = parser.ParseObject(element as XmlElement); RemoveRootNamespacesFromNodeAndChildNodes(root, element); diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs index 3c5cab4bce..6e2e3fb176 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs @@ -556,7 +556,13 @@ namespace ICSharpCode.WpfDesign.XamlDom } } set { - propertyInfo.SetValue(parentObject.Instance, value); + var setValue = value; + if (propertyInfo.ReturnType == typeof(Uri)) + { + setValue = this.ParentObject.OwnerDocument.TypeFinder.ConvertUriToLocalUri((Uri)value); + } + + propertyInfo.SetValue(parentObject.Instance, setValue); if (ValueOnInstanceChanged != null) ValueOnInstanceChanged(this, EventArgs.Empty); } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlTypeFinder.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlTypeFinder.cs index 7d341859c8..ac8f9ee102 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlTypeFinder.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlTypeFinder.cs @@ -277,6 +277,11 @@ namespace ICSharpCode.WpfDesign.XamlDom return WpfTypeFinder.Instance.Clone(); } + public virtual Uri ConvertUriToLocalUri(Uri uri) + { + return uri; + } + static class WpfTypeFinder { internal static readonly XamlTypeFinder Instance; @@ -291,6 +296,7 @@ namespace ICSharpCode.WpfDesign.XamlDom Instance.RegisterAssembly(typeof(IAddChild).Assembly); // PresentationCore Instance.RegisterAssembly(typeof(XamlReader).Assembly); // PresentationFramework Instance.RegisterAssembly(typeof(XamlType).Assembly); // System.Xaml + Instance.RegisterAssembly(typeof(Type).Assembly); // mscorelib } } }