// (c) Copyright Microsoft Corporation. // This source is subject to the Microsoft Public License (Ms-PL). // Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details. // All other rights reserved. using System; using System.Collections.Specialized; using System.Diagnostics; using System.Linq; using System.Windows; namespace System.Windows.Controls.DataVisualization.Charting { /// /// An axes collection used by a series host. /// internal class SeriesHostAxesCollection : UniqueObservableCollection { /// /// Gets or sets the series host field. /// private ISeriesHost SeriesHost { get; set; } /// /// Gets or sets a collection of axes cannot be removed under any /// circumstances. /// private UniqueObservableCollection PersistentAxes { get; set; } /// /// Instantiates a new instance of the SeriesHostAxesCollection class. /// /// The series host. internal SeriesHostAxesCollection(ISeriesHost seriesHost) { this.SeriesHost = seriesHost; this.PersistentAxes = new UniqueObservableCollection(); this.CollectionChanged += ThisCollectionChanged; } /// /// Instantiates a new instance of the SeriesHostAxesCollection class. /// /// The series host. /// A collection of axes that can never be /// removed from the chart. internal SeriesHostAxesCollection(ISeriesHost seriesHost, UniqueObservableCollection persistentAxes) : this(seriesHost) { Debug.Assert(persistentAxes != null, "Persistent axes collection cannot be null."); this.SeriesHost = seriesHost; this.PersistentAxes = persistentAxes; this.PersistentAxes.CollectionChanged += PersistentAxesCollectionChanged; } /// /// A method that attaches and removes listeners to axes added to this /// collection. /// /// This object. /// Information about the event. private void ThisCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { if (e.NewItems != null) { foreach (IAxis axis in e.NewItems) { axis.RegisteredListeners.CollectionChanged += AxisRegisteredListenersCollectionChanged; } } if (e.OldItems != null) { foreach (IAxis axis in e.OldItems) { axis.RegisteredListeners.CollectionChanged -= AxisRegisteredListenersCollectionChanged; } } } /// /// Remove an axis from the collection if it is no longer used. /// /// The axis that has had its registered /// listeners collection changed. /// Information about the event. private void AxisRegisteredListenersCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { IAxis axis = this.Where(currentAxis => currentAxis.RegisteredListeners == sender).First(); if (e.OldItems != null) { if (!PersistentAxes.Contains(axis) && !SeriesHost.IsUsedByASeries(axis)) { this.Remove(axis); } } } /// /// This method synchronizes the collection with the persistent axes /// collection when it is changed. /// /// The source of the event. /// Information about the event. public void PersistentAxesCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { if (e.NewItems != null) { foreach (IAxis axis in e.NewItems) { if (!this.Contains(axis)) { this.Add(axis); } } } if (e.OldItems != null) { foreach (IAxis axis in e.OldItems) { if (this.Contains(axis) && !SeriesHost.IsUsedByASeries(axis)) { this.Remove(axis); } } } } /// /// Removes an item from the axes collection but throws an exception /// if a series in the series host is listening to it. /// /// The index of the item being removed. protected override void RemoveItem(int index) { IAxis axis = this[index]; if (SeriesHost.IsUsedByASeries(axis)) { throw new InvalidOperationException(Properties.Resources.SeriesHostAxesCollection_RemoveItem_AxisCannotBeRemovedFromASeriesHostWhenOneOrMoreSeriesAreListeningToIt); } else if (PersistentAxes.Contains(axis)) { throw new InvalidOperationException(Properties.Resources.SeriesHostAxesCollection_InvalidAttemptToRemovePermanentAxisFromSeriesHost); } else { base.RemoveItem(index); } } } }