This commit is contained in:
jkuehner 2018-07-01 22:42:23 +02:00
Родитель 95cc86c484
Коммит 9623569472
3 изменённых файлов: 1567 добавлений и 1567 удалений

Просмотреть файл

@ -1,358 +1,358 @@
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// enable this define to test that event handlers are removed correctly
//#define EventHandlerDebugging
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using System.Windows.Data;
using ICSharpCode.WpfDesign.XamlDom;
using ICSharpCode.WpfDesign.Designer.Services;
using System.Windows.Markup;
namespace ICSharpCode.WpfDesign.Designer.Xaml
{
[DebuggerDisplay("XamlDesignItem: {ComponentType.Name}")]
public sealed class XamlDesignItem : DesignItem
{
readonly XamlObject _xamlObject;
readonly XamlDesignContext _designContext;
readonly XamlModelPropertyCollection _properties;
UIElement _view;
public XamlDesignItem(XamlObject xamlObject, XamlDesignContext designContext)
{
this._xamlObject = xamlObject;
this._designContext = designContext;
this._properties = new XamlModelPropertyCollection(this);
}
internal XamlComponentService ComponentService {
get {
return _designContext._componentService;
}
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// enable this define to test that event handlers are removed correctly
//#define EventHandlerDebugging
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using System.Windows.Data;
using ICSharpCode.WpfDesign.XamlDom;
using ICSharpCode.WpfDesign.Designer.Services;
using System.Windows.Markup;
namespace ICSharpCode.WpfDesign.Designer.Xaml
{
[DebuggerDisplay("XamlDesignItem: {ComponentType.Name}")]
public sealed class XamlDesignItem : DesignItem
{
readonly XamlObject _xamlObject;
readonly XamlDesignContext _designContext;
readonly XamlModelPropertyCollection _properties;
UIElement _view;
public XamlDesignItem(XamlObject xamlObject, XamlDesignContext designContext)
{
this._xamlObject = xamlObject;
this._designContext = designContext;
this._properties = new XamlModelPropertyCollection(this);
}
internal XamlComponentService ComponentService {
get {
return _designContext._componentService;
}
}
public XamlObject XamlObject {
get { return _xamlObject; }
}
public override object Component {
get {
return _xamlObject.Instance;
}
}
public override Type ComponentType {
get { return _xamlObject.ElementType; }
}
void SetNameInternal(string newName)
{
var oldName = Name;
_xamlObject.Name = newName;
FixDesignItemReferencesOnNameChange(oldName, Name);
}
public override string Name {
get { return _xamlObject.Name; }
set {
UndoService undoService = this.Services.GetService<UndoService>();
if (undoService != null)
undoService.Execute(new SetNameAction(this, value));
else
{
SetNameInternal(value);
}
}
}
/// <summary>
/// Fixes {x:Reference and {Binding ElementName to this Element in XamlDocument
/// </summary>
/// <param name="oldName"></param>
/// <param name="newName"></param>
public void FixDesignItemReferencesOnNameChange(string oldName, string newName)
{
if (!string.IsNullOrEmpty(oldName) && !string.IsNullOrEmpty(newName)) {
var root = GetRootXamlObject(this.XamlObject);
var references = GetAllChildXamlObjects(root).Where(x => x.ElementType == typeof(Reference) && Equals(x.FindOrCreateProperty("Name").ValueOnInstance, oldName));
foreach (var designItem in references)
{
var property = designItem.FindOrCreateProperty("Name");
var propertyValue = designItem.OwnerDocument.CreatePropertyValue(newName, property);
this.ComponentService.RegisterXamlComponentRecursive(propertyValue as XamlObject);
property.PropertyValue = propertyValue;
}
root = GetRootXamlObject(this.XamlObject, true);
var bindings = GetAllChildXamlObjects(root, true).Where(x => x.ElementType == typeof(Binding) && Equals(x.FindOrCreateProperty("ElementName").ValueOnInstance, oldName));
foreach (var designItem in bindings)
{
var property = designItem.FindOrCreateProperty("ElementName");
var propertyValue = designItem.OwnerDocument.CreatePropertyValue(newName, property);
this.ComponentService.RegisterXamlComponentRecursive(propertyValue as XamlObject);
property.PropertyValue = propertyValue;
}
}
}
/// <summary>
/// Find's the Root XamlObject (real Root, or Root Object in Namescope)
/// </summary>
/// <param name="item"></param>
/// <param name="onlyFromSameNamescope"></param>
/// <returns></returns>
internal static XamlObject GetRootXamlObject(XamlObject item, bool onlyFromSameNamescope = false)
{
var root = item;
while (root.ParentObject != null)
{
if (onlyFromSameNamescope && NameScopeHelper.GetNameScopeFromObject(root) != NameScopeHelper.GetNameScopeFromObject(root.ParentObject))
break;
root = root.ParentObject;
}
return root;
}
/// <summary>
/// Get's all Child XamlObject Instances
/// </summary>
/// <param name="item"></param>
/// <param name="onlyFromSameNamescope"></param>
/// <returns></returns>
internal static IEnumerable<XamlObject> GetAllChildXamlObjects(XamlObject item, bool onlyFromSameNamescope = false)
{
foreach (var prop in item.Properties)
{
if (prop.PropertyValue as XamlObject != null)
{
if (!onlyFromSameNamescope || NameScopeHelper.GetNameScopeFromObject(item) == NameScopeHelper.GetNameScopeFromObject(prop.PropertyValue as XamlObject))
yield return prop.PropertyValue as XamlObject;
foreach (var i in GetAllChildXamlObjects(prop.PropertyValue as XamlObject))
{
if (!onlyFromSameNamescope || NameScopeHelper.GetNameScopeFromObject(item) == NameScopeHelper.GetNameScopeFromObject(i))
yield return i;
}
}
if (prop.IsCollection)
{
foreach (var collectionElement in prop.CollectionElements)
{
if (collectionElement as XamlObject != null)
{
if (!onlyFromSameNamescope || NameScopeHelper.GetNameScopeFromObject(item) == NameScopeHelper.GetNameScopeFromObject(collectionElement as XamlObject))
yield return collectionElement as XamlObject;
foreach (var i in GetAllChildXamlObjects(collectionElement as XamlObject))
{
if (!onlyFromSameNamescope || NameScopeHelper.GetNameScopeFromObject(item) == NameScopeHelper.GetNameScopeFromObject(i))
yield return i;
}
}
}
}
}
}
public override string Key {
get { return XamlObject.GetXamlAttribute("Key"); }
set { XamlObject.SetXamlAttribute("Key", value); }
}
#if EventHandlerDebugging
static int totalEventHandlerCount;
#endif
/// <summary>
/// Is raised when the name of the design item changes.
/// </summary>
public override event EventHandler NameChanged {
add {
#if EventHandlerDebugging
Debug.WriteLine("Add event handler to " + this.ComponentType.Name + " (handler count=" + (++totalEventHandlerCount) + ")");
#endif
_xamlObject.NameChanged += value;
}
remove {
#if EventHandlerDebugging
Debug.WriteLine("Remove event handler from " + this.ComponentType.Name + " (handler count=" + (--totalEventHandlerCount) + ")");
#endif
_xamlObject.NameChanged -= value;
}
}
public override DesignItem Parent {
get {
if (_xamlObject.ParentProperty == null)
return null;
else
return ComponentService.GetDesignItem(_xamlObject.ParentProperty.ParentObject.Instance);
}
}
public override DesignItemProperty ParentProperty {
get {
DesignItem parent = this.Parent;
if (parent == null)
return null;
XamlProperty prop = _xamlObject.ParentProperty;
if (prop.IsAttached) {
return parent.Properties.GetAttachedProperty(prop.PropertyTargetType, prop.PropertyName);
} else {
return parent.Properties.GetProperty(prop.PropertyName);
}
}
}
/// <summary>
/// Occurs when the parent of this design item changes.
/// </summary>
public override event EventHandler ParentChanged {
add { _xamlObject.ParentPropertyChanged += value; }
remove { _xamlObject.ParentPropertyChanged -= value; }
}
public override UIElement View {
get {
if (_view != null)
return _view;
else
return this.Component as UIElement;
}
}
public override void SetView(UIElement newView)
{
_view = newView;
}
public override DesignContext Context {
get { return _designContext; }
}
public override DesignItemPropertyCollection Properties {
get { return _properties; }
}
public override IEnumerable<DesignItemProperty> AllSetProperties {
get { return _xamlObject.Properties.Select(x => new XamlModelProperty(this, x)); }
}
internal void NotifyPropertyChanged(XamlModelProperty property)
{
Debug.Assert(property != null);
OnPropertyChanged(new System.ComponentModel.PropertyChangedEventArgs(property.Name));
((XamlComponentService)this.Services.Component).RaisePropertyChanged(property);
}
public override string ContentPropertyName {
get {
return XamlObject.ContentPropertyName;
}
}
/// <summary>
/// Item is Locked at Design Time
/// </summary>
public bool IsDesignTimeLocked {
get {
var locked = Properties.GetAttachedProperty(DesignTimeProperties.IsLockedProperty).ValueOnInstance;
return (locked != null && (bool) locked == true);
}
set {
if (value)
Properties.GetAttachedProperty(DesignTimeProperties.IsLockedProperty).SetValue(true);
else
Properties.GetAttachedProperty(DesignTimeProperties.IsLockedProperty).Reset();
}
}
public override DesignItem Clone()
{
DesignItem item = null;
var xaml = XamlStaticTools.GetXaml(this.XamlObject);
XamlDesignItem rootItem = Context.RootItem as XamlDesignItem;
var obj = XamlParser.ParseSnippet(rootItem.XamlObject, xaml, ((XamlDesignContext) Context).ParserSettings);
if (obj != null)
{
item = ((XamlDesignContext)Context)._componentService.RegisterXamlComponentRecursive(obj);
}
return item;
}
sealed class SetNameAction : ITransactionItem
{
XamlDesignItem designItem;
string oldName;
string newName;
public SetNameAction(XamlDesignItem designItem, string newName)
{
this.designItem = designItem;
this.newName = newName;
oldName = designItem.Name;
}
public string Title {
get {
return "Set name";
}
}
public void Do()
{
designItem.SetNameInternal(newName);
}
public void Undo()
{
designItem.SetNameInternal(oldName);
}
public System.Collections.Generic.ICollection<DesignItem> AffectedElements {
get {
return new DesignItem[] { designItem };
}
}
public bool MergeWith(ITransactionItem other)
{
SetNameAction o = other as SetNameAction;
if (o != null && designItem == o.designItem) {
newName = o.newName;
return true;
}
return false;
}
}
}
}
public XamlObject XamlObject {
get { return _xamlObject; }
}
public override object Component {
get {
return _xamlObject.Instance;
}
}
public override Type ComponentType {
get { return _xamlObject.ElementType; }
}
void SetNameInternal(string newName)
{
var oldName = Name;
_xamlObject.Name = newName;
FixDesignItemReferencesOnNameChange(oldName, Name);
}
public override string Name {
get { return _xamlObject.Name; }
set {
UndoService undoService = this.Services.GetService<UndoService>();
if (undoService != null)
undoService.Execute(new SetNameAction(this, value));
else
{
SetNameInternal(value);
}
}
}
/// <summary>
/// Fixes {x:Reference and {Binding ElementName to this Element in XamlDocument
/// </summary>
/// <param name="oldName"></param>
/// <param name="newName"></param>
public void FixDesignItemReferencesOnNameChange(string oldName, string newName)
{
if (!string.IsNullOrEmpty(oldName) && !string.IsNullOrEmpty(newName)) {
var root = GetRootXamlObject(this.XamlObject);
var references = GetAllChildXamlObjects(root).Where(x => x.ElementType == typeof(Reference) && Equals(x.FindOrCreateProperty("Name").ValueOnInstance, oldName));
foreach (var designItem in references)
{
var property = designItem.FindOrCreateProperty("Name");
var propertyValue = designItem.OwnerDocument.CreatePropertyValue(newName, property);
this.ComponentService.RegisterXamlComponentRecursive(propertyValue as XamlObject);
property.PropertyValue = propertyValue;
}
root = GetRootXamlObject(this.XamlObject, true);
var bindings = GetAllChildXamlObjects(root, true).Where(x => x.ElementType == typeof(Binding) && Equals(x.FindOrCreateProperty("ElementName").ValueOnInstance, oldName));
foreach (var designItem in bindings)
{
var property = designItem.FindOrCreateProperty("ElementName");
var propertyValue = designItem.OwnerDocument.CreatePropertyValue(newName, property);
this.ComponentService.RegisterXamlComponentRecursive(propertyValue as XamlObject);
property.PropertyValue = propertyValue;
}
}
}
/// <summary>
/// Find's the Root XamlObject (real Root, or Root Object in Namescope)
/// </summary>
/// <param name="item"></param>
/// <param name="onlyFromSameNamescope"></param>
/// <returns></returns>
internal static XamlObject GetRootXamlObject(XamlObject item, bool onlyFromSameNamescope = false)
{
var root = item;
while (root.ParentObject != null)
{
if (onlyFromSameNamescope && NameScopeHelper.GetNameScopeFromObject(root) != NameScopeHelper.GetNameScopeFromObject(root.ParentObject))
break;
root = root.ParentObject;
}
return root;
}
/// <summary>
/// Get's all Child XamlObject Instances
/// </summary>
/// <param name="item"></param>
/// <param name="onlyFromSameNamescope"></param>
/// <returns></returns>
internal static IEnumerable<XamlObject> GetAllChildXamlObjects(XamlObject item, bool onlyFromSameNamescope = false)
{
foreach (var prop in item.Properties)
{
if (prop.PropertyValue as XamlObject != null)
{
if (!onlyFromSameNamescope || NameScopeHelper.GetNameScopeFromObject(item) == NameScopeHelper.GetNameScopeFromObject(prop.PropertyValue as XamlObject))
yield return prop.PropertyValue as XamlObject;
foreach (var i in GetAllChildXamlObjects(prop.PropertyValue as XamlObject))
{
if (!onlyFromSameNamescope || NameScopeHelper.GetNameScopeFromObject(item) == NameScopeHelper.GetNameScopeFromObject(i))
yield return i;
}
}
if (prop.IsCollection)
{
foreach (var collectionElement in prop.CollectionElements)
{
if (collectionElement as XamlObject != null)
{
if (!onlyFromSameNamescope || NameScopeHelper.GetNameScopeFromObject(item) == NameScopeHelper.GetNameScopeFromObject(collectionElement as XamlObject))
yield return collectionElement as XamlObject;
foreach (var i in GetAllChildXamlObjects(collectionElement as XamlObject))
{
if (!onlyFromSameNamescope || NameScopeHelper.GetNameScopeFromObject(item) == NameScopeHelper.GetNameScopeFromObject(i))
yield return i;
}
}
}
}
}
}
public override string Key {
get { return XamlObject.GetXamlAttribute("Key"); }
set { XamlObject.SetXamlAttribute("Key", value); }
}
#if EventHandlerDebugging
static int totalEventHandlerCount;
#endif
/// <summary>
/// Is raised when the name of the design item changes.
/// </summary>
public override event EventHandler NameChanged {
add {
#if EventHandlerDebugging
Debug.WriteLine("Add event handler to " + this.ComponentType.Name + " (handler count=" + (++totalEventHandlerCount) + ")");
#endif
_xamlObject.NameChanged += value;
}
remove {
#if EventHandlerDebugging
Debug.WriteLine("Remove event handler from " + this.ComponentType.Name + " (handler count=" + (--totalEventHandlerCount) + ")");
#endif
_xamlObject.NameChanged -= value;
}
}
public override DesignItem Parent {
get {
if (_xamlObject.ParentProperty == null)
return null;
else
return ComponentService.GetDesignItem(_xamlObject.ParentProperty.ParentObject.Instance);
}
}
public override DesignItemProperty ParentProperty {
get {
DesignItem parent = this.Parent;
if (parent == null)
return null;
XamlProperty prop = _xamlObject.ParentProperty;
if (prop.IsAttached) {
return parent.Properties.GetAttachedProperty(prop.PropertyTargetType, prop.PropertyName);
} else {
return parent.Properties.GetProperty(prop.PropertyName);
}
}
}
/// <summary>
/// Occurs when the parent of this design item changes.
/// </summary>
public override event EventHandler ParentChanged {
add { _xamlObject.ParentPropertyChanged += value; }
remove { _xamlObject.ParentPropertyChanged -= value; }
}
public override UIElement View {
get {
if (_view != null)
return _view;
else
return this.Component as UIElement;
}
}
public override void SetView(UIElement newView)
{
_view = newView;
}
public override DesignContext Context {
get { return _designContext; }
}
public override DesignItemPropertyCollection Properties {
get { return _properties; }
}
public override IEnumerable<DesignItemProperty> AllSetProperties {
get { return _xamlObject.Properties.Select(x => new XamlModelProperty(this, x)); }
}
internal void NotifyPropertyChanged(XamlModelProperty property)
{
Debug.Assert(property != null);
OnPropertyChanged(new System.ComponentModel.PropertyChangedEventArgs(property.Name));
((XamlComponentService)this.Services.Component).RaisePropertyChanged(property);
}
public override string ContentPropertyName {
get {
return XamlObject.ContentPropertyName;
}
}
/// <summary>
/// Item is Locked at Design Time
/// </summary>
public bool IsDesignTimeLocked {
get {
var locked = Properties.GetAttachedProperty(DesignTimeProperties.IsLockedProperty).ValueOnInstance;
return (locked != null && (bool) locked == true);
}
set {
if (value)
Properties.GetAttachedProperty(DesignTimeProperties.IsLockedProperty).SetValue(true);
else
Properties.GetAttachedProperty(DesignTimeProperties.IsLockedProperty).Reset();
}
}
public override DesignItem Clone()
{
DesignItem item = null;
var xaml = XamlStaticTools.GetXaml(this.XamlObject);
XamlDesignItem rootItem = Context.RootItem as XamlDesignItem;
var obj = XamlParser.ParseSnippet(rootItem.XamlObject, xaml, ((XamlDesignContext) Context).ParserSettings);
if (obj != null)
{
item = ((XamlDesignContext)Context)._componentService.RegisterXamlComponentRecursive(obj);
}
return item;
}
sealed class SetNameAction : ITransactionItem
{
XamlDesignItem designItem;
string oldName;
string newName;
public SetNameAction(XamlDesignItem designItem, string newName)
{
this.designItem = designItem;
this.newName = newName;
oldName = designItem.Name;
}
public string Title {
get {
return "Set name";
}
}
public void Do()
{
designItem.SetNameInternal(newName);
}
public void Undo()
{
designItem.SetNameInternal(oldName);
}
public System.Collections.Generic.ICollection<DesignItem> AffectedElements {
get {
return new DesignItem[] { designItem };
}
}
public bool MergeWith(ITransactionItem other)
{
SetNameAction o = other as SetNameAction;
if (o != null && designItem == o.designItem) {
newName = o.newName;
return true;
}
return false;
}
}
}
}

Просмотреть файл

@ -1,338 +1,338 @@
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.ComponentModel;
using System.Windows.Markup;
using System.Xml;
using System.IO;
using System.Linq;
using System.Windows.Media;
using System.Collections.Generic;
using System.Reflection;
namespace ICSharpCode.WpfDesign.XamlDom
{
/// <summary>
/// Represents a .xaml document.
/// </summary>
public sealed class XamlDocument
{
static XamlDocument()
{
_colorBrushDictionary = new Dictionary<Color, string>();
foreach (var brushProp in typeof(Brushes).GetProperties(BindingFlags.Static|BindingFlags.Public).Where(p => p.PropertyType == typeof(SolidColorBrush)))
{
var brush = brushProp.GetValue(null, null) as SolidColorBrush;
if (!_colorBrushDictionary.ContainsKey(brush.Color)) {
_colorBrushDictionary.Add(brush.Color, brushProp.Name);
}
}
}
private static Dictionary<Color, string> _colorBrushDictionary;
XmlDocument _xmlDoc;
XamlObject _rootElement;
IServiceProvider _serviceProvider;
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.ComponentModel;
using System.Windows.Markup;
using System.Xml;
using System.IO;
using System.Linq;
using System.Windows.Media;
using System.Collections.Generic;
using System.Reflection;
namespace ICSharpCode.WpfDesign.XamlDom
{
/// <summary>
/// Represents a .xaml document.
/// </summary>
public sealed class XamlDocument
{
static XamlDocument()
{
_colorBrushDictionary = new Dictionary<Color, string>();
foreach (var brushProp in typeof(Brushes).GetProperties(BindingFlags.Static|BindingFlags.Public).Where(p => p.PropertyType == typeof(SolidColorBrush)))
{
var brush = brushProp.GetValue(null, null) as SolidColorBrush;
if (!_colorBrushDictionary.ContainsKey(brush.Color)) {
_colorBrushDictionary.Add(brush.Color, brushProp.Name);
}
}
}
private static Dictionary<Color, string> _colorBrushDictionary;
XmlDocument _xmlDoc;
XamlObject _rootElement;
IServiceProvider _serviceProvider;
private string _currentProjectAssemblyName;
XamlTypeFinder _typeFinder;
int namespacePrefixCounter;
internal XmlDocument XmlDocument {
get { return _xmlDoc; }
}
/// <summary>
/// Gets the type finder used for this XAML document.
/// </summary>
public XamlTypeFinder TypeFinder {
get { return _typeFinder; }
}
/// <summary>
/// Gets the service provider used for markup extensions in this document.
/// </summary>
public IServiceProvider ServiceProvider {
get { return _serviceProvider; }
XamlTypeFinder _typeFinder;
int namespacePrefixCounter;
internal XmlDocument XmlDocument {
get { return _xmlDoc; }
}
/// <summary>
/// Gets the type finder used for this XAML document.
/// </summary>
public XamlTypeFinder TypeFinder {
get { return _typeFinder; }
}
/// <summary>
/// Gets the service provider used for markup extensions in this document.
/// </summary>
public IServiceProvider ServiceProvider {
get { return _serviceProvider; }
}
/// <summary>
/// Gets the Current Projects Assembly Name (if it has any).
/// </summary>
/// <summary>
/// Gets the Current Projects Assembly Name (if it has any).
/// </summary>
public string CurrentProjectAssemblyName
{
get { return _currentProjectAssemblyName; }
{
get { return _currentProjectAssemblyName; }
}
/// <summary>
/// Gets the type descriptor context used for type conversions.
/// </summary>
/// <param name="containingObject">The containing object, used when the
/// type descriptor context needs to resolve an XML namespace.</param>
internal ITypeDescriptorContext GetTypeDescriptorContext(XamlObject containingObject)
{
IServiceProvider serviceProvider;
if (containingObject != null) {
if (containingObject.OwnerDocument != this)
throw new ArgumentException("Containing object must belong to the document!");
serviceProvider = containingObject.ServiceProvider;
} else {
serviceProvider = this.ServiceProvider;
}
return new DummyTypeDescriptorContext(serviceProvider);
}
sealed class DummyTypeDescriptorContext : ITypeDescriptorContext
{
readonly IServiceProvider baseServiceProvider;
public DummyTypeDescriptorContext(IServiceProvider serviceProvider)
{
this.baseServiceProvider = serviceProvider;
}
public IContainer Container {
get { return null; }
}
public object Instance {
get; set;
}
public PropertyDescriptor PropertyDescriptor {
get { return null; }
}
public bool OnComponentChanging()
{
return false;
}
public void OnComponentChanged()
{
}
public object GetService(Type serviceType)
{
return baseServiceProvider.GetService(serviceType);
}
}
/// <summary>
/// Gets the root xaml object.
/// </summary>
public XamlObject RootElement {
get { return _rootElement; }
}
/// <summary>
/// Gets the object instance created by the root xaml object.
/// </summary>
public object RootInstance {
get { return (_rootElement != null) ? _rootElement.Instance : null; }
}
/// <summary>
/// Saves the xaml document into the <paramref name="writer"/>.
/// </summary>
public void Save(XmlWriter writer)
{
if (writer == null)
throw new ArgumentNullException("writer");
_xmlDoc.Save(writer);
}
/// <summary>
/// Internal constructor, used by XamlParser.
/// </summary>
internal XamlDocument(XmlDocument xmlDoc, XamlParserSettings settings)
{
this._xmlDoc = xmlDoc;
this._typeFinder = settings.TypeFinder;
this._serviceProvider = settings.ServiceProvider;
this._currentProjectAssemblyName = settings.CurrentProjectAssemblyName;
}
/// <summary>
/// Called by XamlParser to finish initializing the document.
/// </summary>
internal void ParseComplete(XamlObject rootElement)
{
this._rootElement = rootElement;
}
/// <summary>
/// Create an XamlObject from the instance.
/// </summary>
public XamlObject CreateObject(object instance)
{
return (XamlObject)CreatePropertyValue(instance, null);
}
/// <summary>
/// Creates a value that represents {x:Null}
/// </summary>
public XamlPropertyValue CreateNullValue()
{
return CreateObject(new NullExtension());
}
/// <summary>
/// Create a XamlPropertyValue for the specified value instance.
/// </summary>
public XamlPropertyValue CreatePropertyValue(object instance, XamlProperty forProperty)
{
if (instance == null)
throw new ArgumentNullException("instance");
Type elementType = instance.GetType();
TypeConverter c = TypeDescriptor.GetConverter(instance);
var ctx = new DummyTypeDescriptorContext(this.ServiceProvider);
ctx.Instance = instance;
bool hasStringConverter = c.CanConvertTo(ctx, typeof(string)) && c.CanConvertFrom(typeof(string));
if (forProperty != null && hasStringConverter) {
if (instance is SolidColorBrush && _colorBrushDictionary.ContainsKey(((SolidColorBrush)instance).Color)) {
/// <summary>
/// Gets the type descriptor context used for type conversions.
/// </summary>
/// <param name="containingObject">The containing object, used when the
/// type descriptor context needs to resolve an XML namespace.</param>
internal ITypeDescriptorContext GetTypeDescriptorContext(XamlObject containingObject)
{
IServiceProvider serviceProvider;
if (containingObject != null) {
if (containingObject.OwnerDocument != this)
throw new ArgumentException("Containing object must belong to the document!");
serviceProvider = containingObject.ServiceProvider;
} else {
serviceProvider = this.ServiceProvider;
}
return new DummyTypeDescriptorContext(serviceProvider);
}
sealed class DummyTypeDescriptorContext : ITypeDescriptorContext
{
readonly IServiceProvider baseServiceProvider;
public DummyTypeDescriptorContext(IServiceProvider serviceProvider)
{
this.baseServiceProvider = serviceProvider;
}
public IContainer Container {
get { return null; }
}
public object Instance {
get; set;
}
public PropertyDescriptor PropertyDescriptor {
get { return null; }
}
public bool OnComponentChanging()
{
return false;
}
public void OnComponentChanged()
{
}
public object GetService(Type serviceType)
{
return baseServiceProvider.GetService(serviceType);
}
}
/// <summary>
/// Gets the root xaml object.
/// </summary>
public XamlObject RootElement {
get { return _rootElement; }
}
/// <summary>
/// Gets the object instance created by the root xaml object.
/// </summary>
public object RootInstance {
get { return (_rootElement != null) ? _rootElement.Instance : null; }
}
/// <summary>
/// Saves the xaml document into the <paramref name="writer"/>.
/// </summary>
public void Save(XmlWriter writer)
{
if (writer == null)
throw new ArgumentNullException("writer");
_xmlDoc.Save(writer);
}
/// <summary>
/// Internal constructor, used by XamlParser.
/// </summary>
internal XamlDocument(XmlDocument xmlDoc, XamlParserSettings settings)
{
this._xmlDoc = xmlDoc;
this._typeFinder = settings.TypeFinder;
this._serviceProvider = settings.ServiceProvider;
this._currentProjectAssemblyName = settings.CurrentProjectAssemblyName;
}
/// <summary>
/// Called by XamlParser to finish initializing the document.
/// </summary>
internal void ParseComplete(XamlObject rootElement)
{
this._rootElement = rootElement;
}
/// <summary>
/// Create an XamlObject from the instance.
/// </summary>
public XamlObject CreateObject(object instance)
{
return (XamlObject)CreatePropertyValue(instance, null);
}
/// <summary>
/// Creates a value that represents {x:Null}
/// </summary>
public XamlPropertyValue CreateNullValue()
{
return CreateObject(new NullExtension());
}
/// <summary>
/// Create a XamlPropertyValue for the specified value instance.
/// </summary>
public XamlPropertyValue CreatePropertyValue(object instance, XamlProperty forProperty)
{
if (instance == null)
throw new ArgumentNullException("instance");
Type elementType = instance.GetType();
TypeConverter c = TypeDescriptor.GetConverter(instance);
var ctx = new DummyTypeDescriptorContext(this.ServiceProvider);
ctx.Instance = instance;
bool hasStringConverter = c.CanConvertTo(ctx, typeof(string)) && c.CanConvertFrom(typeof(string));
if (forProperty != null && hasStringConverter) {
if (instance is SolidColorBrush && _colorBrushDictionary.ContainsKey(((SolidColorBrush)instance).Color)) {
var name = _colorBrushDictionary[((SolidColorBrush)instance).Color];
return new XamlTextValue(this, name);
}
return new XamlTextValue(this, c.ConvertToInvariantString(ctx, instance));
}
string ns = GetNamespaceFor(elementType);
string prefix = GetPrefixForNamespace(ns);
XmlElement xml = _xmlDoc.CreateElement(prefix, elementType.Name, ns);
if (hasStringConverter && (XamlObject.GetContentPropertyName(elementType) != null || IsNativeType(instance))) {
xml.InnerText = c.ConvertToInvariantString(instance);
}
return new XamlTextValue(this, c.ConvertToInvariantString(ctx, instance));
}
string ns = GetNamespaceFor(elementType);
string prefix = GetPrefixForNamespace(ns);
XmlElement xml = _xmlDoc.CreateElement(prefix, elementType.Name, ns);
if (hasStringConverter && (XamlObject.GetContentPropertyName(elementType) != null || IsNativeType(instance))) {
xml.InnerText = c.ConvertToInvariantString(instance);
} else if (instance is Brush && forProperty != null) { // TODO: this is a hacky fix, because Brush Editor doesn't
// edit Design Items and so we have no XML, only the Brush
// object and we need to parse the Brush to XAML!
var s = new MemoryStream();
XamlWriter.Save(instance, s);
s.Seek(0, SeekOrigin.Begin);
XmlDocument doc = new XmlDocument();
doc.Load(s);
xml = (XmlElement) _xmlDoc.ImportNode(doc.DocumentElement, true);
var attLst = xml.Attributes.Cast<XmlAttribute>().ToList();
foreach (XmlAttribute att in attLst)
{
if (att.Name.StartsWith(XamlConstants.Xmlns))
{
var rootAtt = doc.DocumentElement.GetAttributeNode(att.Name);
if (rootAtt != null && rootAtt.Value == att.Value)
{
xml.Attributes.Remove(att);
}
}
}
}
return new XamlObject(this, xml, elementType, instance);
}
internal string GetNamespaceFor(Type type, bool getClrNamespace = false)
{
if (type == typeof (DesignTimeProperties))
return XamlConstants.DesignTimeNamespace;
if (type == typeof (MarkupCompatibilityProperties))
return XamlConstants.MarkupCompatibilityNamespace;
if (type == typeof(XamlNamespaceProperties))
return XamlConstants.Xaml2009Namespace;
return _typeFinder.GetXmlNamespaceFor(type.Assembly, type.Namespace, getClrNamespace);
}
internal List<string> GetNamespacesFor(Type type, bool getClrNamespace = false)
{
if (type == typeof (DesignTimeProperties))
return new List<string>(){XamlConstants.DesignTimeNamespace};
if (type == typeof (MarkupCompatibilityProperties))
return new List<string>(){XamlConstants.MarkupCompatibilityNamespace};
if (type == typeof(XamlNamespaceProperties))
return new List<string>() { XamlConstants.Xaml2009Namespace, XamlConstants.XamlNamespace };
return _typeFinder.GetXmlNamespacesFor(type.Assembly, type.Namespace, getClrNamespace);
}
internal string GetPrefixForNamespace(string @namespace)
{
if (@namespace == XamlConstants.PresentationNamespace)
{
return null;
}
string prefix = _xmlDoc.DocumentElement.GetPrefixOfNamespace(@namespace);
if (_xmlDoc.DocumentElement.NamespaceURI == @namespace && _xmlDoc.DocumentElement.Prefix == String.Empty)
{
return string.Empty;
}
if (String.IsNullOrEmpty(prefix))
{
prefix = _typeFinder.GetPrefixForXmlNamespace(@namespace);
string existingNamespaceForPrefix = null;
if (!String.IsNullOrEmpty(prefix))
{
existingNamespaceForPrefix = _xmlDoc.DocumentElement.GetNamespaceOfPrefix(prefix);
}
if (String.IsNullOrEmpty(prefix) ||
!String.IsNullOrEmpty(existingNamespaceForPrefix) &&
existingNamespaceForPrefix != @namespace)
{
do
{
prefix = "Controls" + namespacePrefixCounter++;
} while (!String.IsNullOrEmpty(_xmlDoc.DocumentElement.GetNamespaceOfPrefix(prefix)));
}
string xmlnsPrefix = _xmlDoc.DocumentElement.GetPrefixOfNamespace(XamlConstants.XmlnsNamespace);
System.Diagnostics.Debug.Assert(!String.IsNullOrEmpty(xmlnsPrefix));
_xmlDoc.DocumentElement.SetAttribute(xmlnsPrefix + ":" + prefix, @namespace);
if (@namespace == XamlConstants.DesignTimeNamespace)
{
var ignorableProp = new XamlProperty(this._rootElement,new XamlDependencyPropertyInfo(MarkupCompatibilityProperties.IgnorableProperty,true));
ignorableProp.SetAttribute(prefix);
}
}
return prefix;
}
internal string GetNamespaceForPrefix(string prefix)
{
return _xmlDoc.DocumentElement.GetNamespaceOfPrefix(prefix);
}
bool IsNativeType(object instance)
{
return instance.GetType().Assembly == typeof(String).Assembly || instance.GetType().IsEnum;
}
}
}
// object and we need to parse the Brush to XAML!
var s = new MemoryStream();
XamlWriter.Save(instance, s);
s.Seek(0, SeekOrigin.Begin);
XmlDocument doc = new XmlDocument();
doc.Load(s);
xml = (XmlElement) _xmlDoc.ImportNode(doc.DocumentElement, true);
var attLst = xml.Attributes.Cast<XmlAttribute>().ToList();
foreach (XmlAttribute att in attLst)
{
if (att.Name.StartsWith(XamlConstants.Xmlns))
{
var rootAtt = doc.DocumentElement.GetAttributeNode(att.Name);
if (rootAtt != null && rootAtt.Value == att.Value)
{
xml.Attributes.Remove(att);
}
}
}
}
return new XamlObject(this, xml, elementType, instance);
}
internal string GetNamespaceFor(Type type, bool getClrNamespace = false)
{
if (type == typeof (DesignTimeProperties))
return XamlConstants.DesignTimeNamespace;
if (type == typeof (MarkupCompatibilityProperties))
return XamlConstants.MarkupCompatibilityNamespace;
if (type == typeof(XamlNamespaceProperties))
return XamlConstants.Xaml2009Namespace;
return _typeFinder.GetXmlNamespaceFor(type.Assembly, type.Namespace, getClrNamespace);
}
internal List<string> GetNamespacesFor(Type type, bool getClrNamespace = false)
{
if (type == typeof (DesignTimeProperties))
return new List<string>(){XamlConstants.DesignTimeNamespace};
if (type == typeof (MarkupCompatibilityProperties))
return new List<string>(){XamlConstants.MarkupCompatibilityNamespace};
if (type == typeof(XamlNamespaceProperties))
return new List<string>() { XamlConstants.Xaml2009Namespace, XamlConstants.XamlNamespace };
return _typeFinder.GetXmlNamespacesFor(type.Assembly, type.Namespace, getClrNamespace);
}
internal string GetPrefixForNamespace(string @namespace)
{
if (@namespace == XamlConstants.PresentationNamespace)
{
return null;
}
string prefix = _xmlDoc.DocumentElement.GetPrefixOfNamespace(@namespace);
if (_xmlDoc.DocumentElement.NamespaceURI == @namespace && _xmlDoc.DocumentElement.Prefix == String.Empty)
{
return string.Empty;
}
if (String.IsNullOrEmpty(prefix))
{
prefix = _typeFinder.GetPrefixForXmlNamespace(@namespace);
string existingNamespaceForPrefix = null;
if (!String.IsNullOrEmpty(prefix))
{
existingNamespaceForPrefix = _xmlDoc.DocumentElement.GetNamespaceOfPrefix(prefix);
}
if (String.IsNullOrEmpty(prefix) ||
!String.IsNullOrEmpty(existingNamespaceForPrefix) &&
existingNamespaceForPrefix != @namespace)
{
do
{
prefix = "Controls" + namespacePrefixCounter++;
} while (!String.IsNullOrEmpty(_xmlDoc.DocumentElement.GetNamespaceOfPrefix(prefix)));
}
string xmlnsPrefix = _xmlDoc.DocumentElement.GetPrefixOfNamespace(XamlConstants.XmlnsNamespace);
System.Diagnostics.Debug.Assert(!String.IsNullOrEmpty(xmlnsPrefix));
_xmlDoc.DocumentElement.SetAttribute(xmlnsPrefix + ":" + prefix, @namespace);
if (@namespace == XamlConstants.DesignTimeNamespace)
{
var ignorableProp = new XamlProperty(this._rootElement,new XamlDependencyPropertyInfo(MarkupCompatibilityProperties.IgnorableProperty,true));
ignorableProp.SetAttribute(prefix);
}
}
return prefix;
}
internal string GetNamespaceForPrefix(string prefix)
{
return _xmlDoc.DocumentElement.GetNamespaceOfPrefix(prefix);
}
bool IsNativeType(object instance)
{
return instance.GetType().Assembly == typeof(String).Assembly || instance.GetType().IsEnum;
}
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу