Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Framework / MS / Internal / Annotations / XmlElementCollection.cs / 1 / XmlElementCollection.cs
//----------------------------------------------------------------------------
//
//
// Copyright (C) 2003 by Microsoft Corporation. All rights reserved.
//
//
//
// Description: Subclass of ObservableCollection which also registers for
// change notifications from the XmlElements it contains. It fires
// CollectionChanged event with action==Reset for any item that
// changed. This is sufficient to let owner objects know an item
// has changed.
//
// History:
// 03/10/2005 : [....] - created
//
//---------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using System.Windows.Data;
using System.Xml;
using MS.Internal;
namespace MS.Internal.Annotations
{
///
///
internal sealed class XmlElementCollection : ObservableCollection
{
//-----------------------------------------------------
//
// Constructors
//
//-----------------------------------------------------
#region Constructors
///
/// Initializes a new instance of XmlElementCollection that is empty and has default initial capacity.
///
public XmlElementCollection() : base()
{
_xmlDocsRefCounts = new Dictionary();
}
#endregion Constructors
//------------------------------------------------------
//
// Public Events
//
//-----------------------------------------------------
//------------------------------------------------------
//
// Protected Methods
//
//------------------------------------------------------
#region Protected Methods
///
/// called by base class Collection<T> when the list is being cleared;
/// unregisters from all items
///
protected override void ClearItems()
{
foreach (XmlElement item in this)
{
UnregisterForElement(item);
}
base.ClearItems();
}
///
/// called by base class Collection<T> when an item is removed from list;
/// unregisters on item being removed
///
protected override void RemoveItem(int index)
{
XmlElement removedItem = this[index];
UnregisterForElement(removedItem);
base.RemoveItem(index);
}
///
/// called by base class Collection<T> when an item is added to list;
/// registers on new item
///
protected override void InsertItem(int index, XmlElement item)
{
if (item != null && this.Contains(item))
{
throw new ArgumentException(SR.Get(SRID.XmlNodeAlreadyOwned, "change", "change"), "item");
}
base.InsertItem(index, item);
RegisterForElement(item);
}
///
/// called by base class Collection<T> when an item is added to list;
/// unregisters on previous item and registers for new item
///
protected override void SetItem(int index, XmlElement item)
{
if (item != null && this.Contains(item))
{
throw new ArgumentException(SR.Get(SRID.XmlNodeAlreadyOwned, "change", "change"), "item");
}
XmlElement originalItem = this[index];
UnregisterForElement(originalItem);
Items[index] = item; // directly set Collection inner Items collection
OnCollectionReset();
RegisterForElement(item);
}
#endregion Protected Methods
//-----------------------------------------------------
//
// Private Methods
//
//------------------------------------------------------
#region Private Methods
///
/// Unregister for change notifications for this element.
/// We decrease the reference count and unregister if the count
/// has reached zero.
///
/// the element to unregister for
private void UnregisterForElement(XmlElement element)
{
// Nulls may exist in the collection in which case we don't need to unregister
if (element == null)
return;
Invariant.Assert(_xmlDocsRefCounts.ContainsKey(element.OwnerDocument), "Not registered on XmlElement");
// Decrease the reference count
_xmlDocsRefCounts[element.OwnerDocument]--;
// If the reference count is at zero, we can unregister for notifications
// from the document and clear out its entry in the hashtable.
if (_xmlDocsRefCounts[element.OwnerDocument] == 0)
{
element.OwnerDocument.NodeChanged -= OnNodeChanged;
element.OwnerDocument.NodeInserted -= OnNodeChanged;
element.OwnerDocument.NodeRemoved -= OnNodeChanged;
_xmlDocsRefCounts.Remove(element.OwnerDocument);
}
}
///
/// Register for change notifications for this element. In
/// reality we regiser on the OwnerDocument, so we keep a count
/// of all the elements from a particular docuemnt we are listening
/// for. If that ref count gets to zero we unregister from the
/// document.
///
/// the element to register for
private void RegisterForElement(XmlElement element)
{
// Nulls may exist in the collection in which case we don't need to register
if (element == null)
return;
if (!_xmlDocsRefCounts.ContainsKey(element.OwnerDocument))
{
// If we aren't register on this document yet, register
// and initialize the reference count to 1.
_xmlDocsRefCounts[element.OwnerDocument] = 1;
XmlNodeChangedEventHandler handler = new XmlNodeChangedEventHandler(OnNodeChanged);
element.OwnerDocument.NodeChanged += handler;
element.OwnerDocument.NodeInserted += handler;
element.OwnerDocument.NodeRemoved += handler;
}
else
{
// Increase the reference count
_xmlDocsRefCounts[element.OwnerDocument]++;
}
}
///
/// We register for node changes on the documents that own the contents
/// of this Resource. Its the only way to know if the contents have
/// changed.
///
/// document whose node has changed
/// args describing the kind of change and specifying the node that changed
private void OnNodeChanged(object sender, XmlNodeChangedEventArgs args)
{
XmlAttribute attr = null;
XmlElement element = null;
// We should only be getting notifications from documents we have registered on
Invariant.Assert(_xmlDocsRefCounts.ContainsKey(sender as XmlDocument), "Not expecting a notification from this sender");
// The node that changed may not be a content but could be a part of a content
// (such as an attribute node). Therefore we must walk up from the node until
// we either a) get to the root or b) find a content we contain. In the case of
// (a) we do nothing. In the case of (b) we must fire a change notification
// for this Resource.
XmlNode current = args.Node;
while (current != null)
{
element = current as XmlElement;
if (element != null && this.Contains(element))
{
OnCollectionReset();
break;
}
// Get the parent of the current node
attr = current as XmlAttribute;
if (attr != null)
{
// ParentNode isn't implemented for XmlAttributes, we must
// use its OwnerElement to continue our walk up the node tree.
current = attr.OwnerElement;
}
else
{
current = current.ParentNode;
}
}
}
private void OnCollectionReset()
{
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
#endregion Private Methods
//-----------------------------------------------------
//
// Private Fields
//
//-----------------------------------------------------
#region Private Fields
Dictionary _xmlDocsRefCounts;
#endregion Private Fields
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ObjectDataSourceMethodEventArgs.cs
- GeometryCombineModeValidation.cs
- Setter.cs
- ImplicitInputBrush.cs
- ImportedPolicyConversionContext.cs
- SponsorHelper.cs
- TreeNode.cs
- DrawingAttributes.cs
- XmlSchemaRedefine.cs
- ActivityScheduledRecord.cs
- EdmItemCollection.cs
- WindowsSecurityTokenAuthenticator.cs
- DataContractSet.cs
- TypeNameHelper.cs
- SqlLiftWhereClauses.cs
- RepeatBehavior.cs
- AutomationProperties.cs
- RegexFCD.cs
- StickyNoteContentControl.cs
- WebCategoryAttribute.cs
- DataGridViewCellCancelEventArgs.cs
- PasswordBoxAutomationPeer.cs
- ToolStripScrollButton.cs
- BinaryFormatterWriter.cs
- BinaryMethodMessage.cs
- ActiveXSite.cs
- CreateUserErrorEventArgs.cs
- SchemaNames.cs
- HTTPNotFoundHandler.cs
- ReferenceEqualityComparer.cs
- HelpInfo.cs
- NamedPipeAppDomainProtocolHandler.cs
- SegmentInfo.cs
- _ProxyChain.cs
- CustomSignedXml.cs
- TransformConverter.cs
- RadialGradientBrush.cs
- InputGestureCollection.cs
- ServiceModelPerformanceCounters.cs
- ImageBrush.cs
- HtmlTernaryTree.cs
- FreezableCollection.cs
- PrintController.cs
- BaseResourcesBuildProvider.cs
- WindowsPrincipal.cs
- EditingCoordinator.cs
- SQLUtility.cs
- Convert.cs
- LineMetrics.cs
- DataGridItemEventArgs.cs
- XslAst.cs
- ThemeDirectoryCompiler.cs
- mda.cs
- XmlSchemaSimpleContentExtension.cs
- DataRowCollection.cs
- ExpressionVisitorHelpers.cs
- DocumentCollection.cs
- DocumentXmlWriter.cs
- SettingsProperty.cs
- Point4D.cs
- ActivityScheduledRecord.cs
- XamlStyleSerializer.cs
- TreeIterators.cs
- PartitionerStatic.cs
- ClockController.cs
- FamilyTypeface.cs
- CustomCategoryAttribute.cs
- DataGridViewAutoSizeColumnsModeEventArgs.cs
- ParseNumbers.cs
- SecUtil.cs
- GPStream.cs
- HtmlButton.cs
- ISO2022Encoding.cs
- ToolTip.cs
- SqlBulkCopyColumnMapping.cs
- DataGridViewButtonColumn.cs
- SoapFormatExtensions.cs
- WizardPanelChangingEventArgs.cs
- panel.cs
- EncoderBestFitFallback.cs
- DBParameter.cs
- CodeRegionDirective.cs
- TextReturnReader.cs
- PlanCompilerUtil.cs
- ApplicationDirectoryMembershipCondition.cs
- Point3DCollection.cs
- MenuItem.cs
- UnmanagedBitmapWrapper.cs
- NamedPipeTransportSecurityElement.cs
- AddressAlreadyInUseException.cs
- WsdlInspector.cs
- PackUriHelper.cs
- WindowsListView.cs
- BamlTreeMap.cs
- SystemWebSectionGroup.cs
- MaskedTextProvider.cs
- RowUpdatedEventArgs.cs
- TcpChannelListener.cs
- QueryContinueDragEventArgs.cs
- FacetValueContainer.cs