using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
namespace Microsoft.Research.DynamicDataDisplay.Common
{
///
/// This is a base class for some of collections in DynamicDataDisplay assembly.
/// It provides means to be notified when item adding and added events, which enables successors to, for example,
/// check if adding item is not equal to null.
///
///
public abstract class D3Collection : ObservableCollection
{
#region Overrides
protected override void InsertItem(int index, T item)
{
OnItemAdding(item);
base.InsertItem(index, item);
OnItemAdded(item);
}
protected override void ClearItems()
{
foreach (var item in Items)
{
OnItemRemoving(item);
}
base.ClearItems();
}
protected override void RemoveItem(int index)
{
T item = Items[index];
OnItemRemoving(item);
base.RemoveItem(index);
}
protected override void SetItem(int index, T item)
{
T oldItem = Items[index];
OnItemRemoving(oldItem);
OnItemAdding(item);
base.SetItem(index, item);
OnItemAdded(item);
}
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
attemptsToRaiseEvent++;
if (raiseCollectionChangedEvent)
{
base.OnCollectionChanged(e);
}
}
#endregion // end of Overrides
///
/// Called before item added to collection. Enables to perform validation.
///
/// The adding item.
protected virtual void OnItemAdding(T item) { }
///
/// Called when item is added.
///
/// The added item.
protected virtual void OnItemAdded(T item) { }
///
/// Called when item is being removed, but before it is actually removed.
///
/// The removing item.
protected virtual void OnItemRemoving(T item) { }
#region Public
int attemptsToRaiseEvent = 0;
bool raiseCollectionChangedEvent = true;
public void BeginUpdate()
{
attemptsToRaiseEvent = 0;
raiseCollectionChangedEvent = false;
}
public void EndUpdate(bool raiseReset)
{
raiseCollectionChangedEvent = true;
if (attemptsToRaiseEvent > 0 && raiseReset)
{
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}
public IDisposable BlockEvents(bool raiseReset)
{
return new EventBlocker(this, raiseReset);
}
private sealed class EventBlocker : IDisposable
{
private readonly D3Collection collection;
private readonly bool raiseReset = true;
public EventBlocker(D3Collection collection, bool raiseReset)
{
this.collection = collection;
this.raiseReset = raiseReset;
collection.BeginUpdate();
}
#region IDisposable Members
public void Dispose()
{
collection.EndUpdate(raiseReset);
}
#endregion
}
#endregion // end of Public
}
}