diff --git a/samples/XmlDOM/Window1.xaml b/samples/XmlDOM/Window1.xaml
index ff48e55990..ef7a6460de 100644
--- a/samples/XmlDOM/Window1.xaml
+++ b/samples/XmlDOM/Window1.xaml
@@ -13,7 +13,7 @@
-
+
diff --git a/samples/XmlDOM/Window1.xaml.cs b/samples/XmlDOM/Window1.xaml.cs
index cb883df5c8..7eff91e722 100644
--- a/samples/XmlDOM/Window1.xaml.cs
+++ b/samples/XmlDOM/Window1.xaml.cs
@@ -103,18 +103,5 @@ namespace XmlDOM
sb.Begin();
};
}
-
- void BindElement(object sender, EventArgs e)
- {
- TextBlock textBlock = (TextBlock)sender;
- AXmlElement node = (AXmlElement)textBlock.DataContext;
- node.StartTag.Changed += delegate {
- BindingOperations.GetBindingExpression(textBlock, TextBlock.TextProperty).UpdateTarget();
- textBlock.Background = new SolidColorBrush(Colors.LightGreen);
- Storyboard sb = ((Storyboard)this.FindResource("anim"));
- Storyboard.SetTarget(sb, textBlock);
- sb.Begin();
- };
- }
}
}
\ No newline at end of file
diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/AXmlAttributeCollection.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/AXmlAttributeCollection.cs
index 77a6985026..bbd68e9db1 100644
--- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/AXmlAttributeCollection.cs
+++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/AXmlAttributeCollection.cs
@@ -15,6 +15,12 @@ namespace ICSharpCode.AvalonEdit.Xml
///
public class AXmlAttributeCollection: FilteredCollection>
{
+ /// Empty unbound collection
+ public static AXmlAttributeCollection Empty = new AXmlAttributeCollection();
+
+ /// Create unbound collection
+ protected AXmlAttributeCollection() {}
+
/// Wrap the given collection. Non-attributes are filtered
public AXmlAttributeCollection(AXmlObjectCollection source): base(source) {}
diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/AXmlElement.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/AXmlElement.cs
index 7670b13a81..d6cca5d474 100644
--- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/AXmlElement.cs
+++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/AXmlElement.cs
@@ -28,13 +28,44 @@ namespace ICSharpCode.AvalonEdit.Xml
/// True in wellformed XML
public bool HasEndTag { get; set; }
- /// StartTag of an element.
- public AXmlTag StartTag {
+ ///
+ internal override bool UpdateDataFrom(AXmlObject source)
+ {
+ if (!base.UpdateDataFrom(source)) return false;
+ AXmlElement src = (AXmlElement)source;
+ // Clear the cache for this - quite expensive
+ attributesAndElements = null;
+ if (this.IsProperlyNested != src.IsProperlyNested ||
+ this.HasStartOrEmptyTag != src.HasStartOrEmptyTag ||
+ this.HasEndTag != src.HasEndTag)
+ {
+ OnChanging();
+ this.IsProperlyNested = src.IsProperlyNested;
+ this.HasStartOrEmptyTag = src.HasStartOrEmptyTag;
+ this.HasEndTag = src.HasEndTag;
+ OnChanged();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /// The start or empty-element tag if there is any
+ internal AXmlTag StartTag {
get {
+ Assert(HasStartOrEmptyTag, "Does not have a start tag");
return (AXmlTag)this.Children[0];
}
}
+ /// The end tag if there is any
+ internal AXmlTag EndTag {
+ get {
+ Assert(HasEndTag, "Does not have an end tag");
+ return (AXmlTag)this.Children[this.Children.Count - 1];
+ }
+ }
+
internal override void DebugCheckConsistency(bool checkParentPointers)
{
DebugAssert(Children.Count > 0, "No children");
@@ -43,30 +74,38 @@ namespace ICSharpCode.AvalonEdit.Xml
#region Helpper methods
- AXmlAttributeCollection attributes;
-
/// Gets attributes of the element
+ ///
+ /// Warning: this is a cenvenience method to access the attributes of the start tag.
+ /// However, since the start tag might be moved/replaced, this property might return
+ /// different values over time.
+ ///
public AXmlAttributeCollection Attributes {
get {
- if (attributes == null) {
- attributes = new AXmlAttributeCollection(this.StartTag.Children);
+ if (this.HasStartOrEmptyTag) {
+ return this.StartTag.Attributes;
+ } else {
+ return AXmlAttributeCollection.Empty;
}
- return attributes;
}
}
ObservableCollection attributesAndElements;
- // TODO: Identity
- /// Gets both attributes and elements
+ /// Gets both attributes and elements. Expensive, avoid use.
+ /// Warning: the collection will regenerate after each update
public ObservableCollection AttributesAndElements {
get {
if (attributesAndElements == null) {
- attributesAndElements = new MergedCollection> (
- // New wrapper with RawObject types
- new FilteredCollection>(this.StartTag.Children, x => x is AXmlAttribute),
- new FilteredCollection>(this.Children, x => x is AXmlElement)
- );
+ if (this.HasStartOrEmptyTag) {
+ attributesAndElements = new MergedCollection> (
+ // New wrapper with RawObject types
+ new FilteredCollection>(this.StartTag.Children, x => x is AXmlAttribute),
+ new FilteredCollection>(this.Children, x => x is AXmlElement)
+ );
+ } else {
+ attributesAndElements = new FilteredCollection>(this.Children, x => x is AXmlElement);
+ }
}
return attributesAndElements;
}
@@ -75,7 +114,11 @@ namespace ICSharpCode.AvalonEdit.Xml
/// Name with namespace prefix - exactly as in source
public string Name {
get {
- return this.StartTag.Name;
+ if (this.HasStartOrEmptyTag) {
+ return this.StartTag.Name;
+ } else {
+ return this.EndTag.Name;
+ }
}
}
@@ -83,7 +126,7 @@ namespace ICSharpCode.AvalonEdit.Xml
/// Empty string if not found
public string Prefix {
get {
- return GetNamespacePrefix(this.StartTag.Name);
+ return GetNamespacePrefix(this.Name);
}
}
@@ -91,7 +134,7 @@ namespace ICSharpCode.AvalonEdit.Xml
/// Empty string if not found
public string LocalName {
get {
- return GetLocalName(this.StartTag.Name);
+ return GetLocalName(this.Name);
}
}
@@ -180,7 +223,7 @@ namespace ICSharpCode.AvalonEdit.Xml
///
public override string ToString()
{
- return string.Format("[{0} '{1}{2}{3}' Attr:{4} Chld:{5} Nest:{6}]", base.ToString(), this.StartTag.OpeningBracket, this.StartTag.Name, this.StartTag.ClosingBracket, this.StartTag.Children.Count, this.Children.Count, this.IsProperlyNested ? "Ok" : "Bad");
+ return string.Format("[{0} '{1}' Attr:{2} Chld:{3} Nest:{4}]", base.ToString(), this.Name, this.HasStartOrEmptyTag ? this.StartTag.Children.Count : 0, this.Children.Count, this.IsProperlyNested ? "Ok" : "Bad");
}
}
}
diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/AXmlObject.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/AXmlObject.cs
index 93fdfc1dca..3ae3a0944c 100644
--- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/AXmlObject.cs
+++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/AXmlObject.cs
@@ -74,6 +74,11 @@ namespace ICSharpCode.AvalonEdit.Xml
if (doc != null) {
doc.OnObjectChanging(this);
}
+ // As a convenience, also rasie an event for the parent element
+ AXmlTag me = this as AXmlTag;
+ if (me != null && (me.IsStartOrEmptyTag || me.IsEndTag) && me.Parent is AXmlElement) {
+ me.Parent.OnChanging();
+ }
}
/// Raises Changed event
@@ -87,6 +92,11 @@ namespace ICSharpCode.AvalonEdit.Xml
if (doc != null) {
doc.OnObjectChanged(this);
}
+ // As a convenience, also rasie an event for the parent element
+ AXmlTag me = this as AXmlTag;
+ if (me != null && (me.IsStartOrEmptyTag || me.IsEndTag) && me.Parent is AXmlElement) {
+ me.Parent.OnChanged();
+ }
}
List syntaxErrors;
diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/AXmlTag.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/AXmlTag.cs
index 1cbd57a1a8..236610152f 100644
--- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/AXmlTag.cs
+++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/AXmlTag.cs
@@ -50,6 +50,22 @@ namespace ICSharpCode.AvalonEdit.Xml
/// True if tag starts with "<!"
public bool IsUnknownBang { get { return OpeningBracket == " Gets attributes of the tag (if applicable)
+ public AXmlAttributeCollection Attributes {
+ get {
+ if (attributes == null) {
+ attributes = new AXmlAttributeCollection(this.Children);
+ }
+ return attributes;
+ }
+ }
+
+ #endregion
+
internal override void DebugCheckConsistency(bool checkParentPointers)
{
Assert(OpeningBracket != null, "Null OpeningBracket");
diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/FilteredCollection.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/FilteredCollection.cs
index 626f657542..54f8b1e161 100644
--- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/FilteredCollection.cs
+++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/FilteredCollection.cs
@@ -23,6 +23,9 @@ namespace ICSharpCode.AvalonEdit.Xml
Predicate