#if !NETFX_CORE
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections;
using System.Diagnostics;
namespace PlatformSupport.Collections.Specialized
{
public delegate void NotifyCollectionChangedEventHandler(object sender, PlatformSupport.Collections.Specialized.NotifyCollectionChangedEventArgs e);
public interface INotifyCollectionChanged
{
event NotifyCollectionChangedEventHandler CollectionChanged;
}
///
/// This enum describes the action that caused a CollectionChanged event.
///
public enum NotifyCollectionChangedAction
{
/// One or more items were added to the collection.
Add,
/// One or more items were removed from the collection.
Remove,
/// One or more items were replaced in the collection.
Replace,
/// One or more items were moved within the collection.
Move,
/// The contents of the collection changed dramatically.
Reset,
}
///
/// Arguments for the CollectionChanged event.
/// A collection that supports INotifyCollectionChangedThis raises this event
/// whenever an item is added or removed, or when the contents of the collection
/// changes dramatically.
///
public class NotifyCollectionChangedEventArgs : EventArgs
{
//------------------------------------------------------
//
// Constructors
//
//------------------------------------------------------
///
/// Construct a NotifyCollectionChangedEventArgs that describes a reset change.
///
/// The action that caused the event (must be Reset).
public NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action)
{
if (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Reset)
throw new ArgumentException("action");
InitializeAdd(action, null, -1);
}
///
/// Construct a NotifyCollectionChangedEventArgs that describes a one-item change.
///
/// The action that caused the event; can only be Reset, Add or Remove action.
/// The item affected by the change.
public NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, object changedItem)
{
if ((action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Add) && (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Remove)
&& (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Reset))
throw new ArgumentException("action");
if (action == PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Reset)
{
if (changedItem != null)
throw new ArgumentException("action");
InitializeAdd(action, null, -1);
}
else
{
InitializeAddOrRemove(action, new object[] { changedItem }, -1);
}
}
///
/// Construct a NotifyCollectionChangedEventArgs that describes a one-item change.
///
/// The action that caused the event.
/// The item affected by the change.
/// The index where the change occurred.
public NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, object changedItem, int index)
{
if ((action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Add) && (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Remove)
&& (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Reset))
throw new ArgumentException("action");
if (action == PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Reset)
{
if (changedItem != null)
throw new ArgumentException("action");
if (index != -1)
throw new ArgumentException("action");
InitializeAdd(action, null, -1);
}
else
{
InitializeAddOrRemove(action, new object[] { changedItem }, index);
}
}
///
/// Construct a NotifyCollectionChangedEventArgs that describes a multi-item change.
///
/// The action that caused the event.
/// The items affected by the change.
public NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, IList changedItems)
{
if ((action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Add) && (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Remove)
&& (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Reset))
throw new ArgumentException("action");
if (action == PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Reset)
{
if (changedItems != null)
throw new ArgumentException("action");
InitializeAdd(action, null, -1);
}
else
{
if (changedItems == null)
throw new ArgumentNullException("changedItems");
InitializeAddOrRemove(action, changedItems, -1);
}
}
///
/// Construct a NotifyCollectionChangedEventArgs that describes a multi-item change (or a reset).
///
/// The action that caused the event.
/// The items affected by the change.
/// The index where the change occurred.
public NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, IList changedItems, int startingIndex)
{
if ((action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Add) && (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Remove)
&& (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Reset))
throw new ArgumentException("action");
if (action == PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Reset)
{
if (changedItems != null)
throw new ArgumentException("action");
if (startingIndex != -1)
throw new ArgumentException("action");
InitializeAdd(action, null, -1);
}
else
{
if (changedItems == null)
throw new ArgumentNullException("changedItems");
if (startingIndex < -1)
throw new ArgumentException("startingIndex");
InitializeAddOrRemove(action, changedItems, startingIndex);
}
}
///
/// Construct a NotifyCollectionChangedEventArgs that describes a one-item Replace event.
///
/// Can only be a Replace action.
/// The new item replacing the original item.
/// The original item that is replaced.
public NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, object newItem, object oldItem)
{
if (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Replace)
throw new ArgumentException("action");
InitializeMoveOrReplace(action, new object[] { newItem }, new object[] { oldItem }, -1, -1);
}
///
/// Construct a NotifyCollectionChangedEventArgs that describes a one-item Replace event.
///
/// Can only be a Replace action.
/// The new item replacing the original item.
/// The original item that is replaced.
/// The index of the item being replaced.
public NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, object newItem, object oldItem, int index)
{
if (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Replace)
throw new ArgumentException("action");
InitializeMoveOrReplace(action, new object[] { newItem }, new object[] { oldItem }, index, index);
}
///
/// Construct a NotifyCollectionChangedEventArgs that describes a multi-item Replace event.
///
/// Can only be a Replace action.
/// The new items replacing the original items.
/// The original items that are replaced.
public NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, IList newItems, IList oldItems)
{
if (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Replace)
throw new ArgumentException("action");
if (newItems == null)
throw new ArgumentNullException("newItems");
if (oldItems == null)
throw new ArgumentNullException("oldItems");
InitializeMoveOrReplace(action, newItems, oldItems, -1, -1);
}
///
/// Construct a NotifyCollectionChangedEventArgs that describes a multi-item Replace event.
///
/// Can only be a Replace action.
/// The new items replacing the original items.
/// The original items that are replaced.
/// The starting index of the items being replaced.
public NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, IList newItems, IList oldItems, int startingIndex)
{
if (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Replace)
throw new ArgumentException("action");
if (newItems == null)
throw new ArgumentNullException("newItems");
if (oldItems == null)
throw new ArgumentNullException("oldItems");
InitializeMoveOrReplace(action, newItems, oldItems, startingIndex, startingIndex);
}
///
/// Construct a NotifyCollectionChangedEventArgs that describes a one-item Move event.
///
/// Can only be a Move action.
/// The item affected by the change.
/// The new index for the changed item.
/// The old index for the changed item.
public NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, object changedItem, int index, int oldIndex)
{
if (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Move)
throw new ArgumentException("action");
if (index < 0)
throw new ArgumentException("index");
object[] changedItems = new object[] { changedItem };
InitializeMoveOrReplace(action, changedItems, changedItems, index, oldIndex);
}
///
/// Construct a NotifyCollectionChangedEventArgs that describes a multi-item Move event.
///
/// The action that caused the event.
/// The items affected by the change.
/// The new index for the changed items.
/// The old index for the changed items.
public NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, IList changedItems, int index, int oldIndex)
{
if (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Move)
throw new ArgumentException("action");
if (index < 0)
throw new ArgumentException("index");
InitializeMoveOrReplace(action, changedItems, changedItems, index, oldIndex);
}
///
/// Construct a NotifyCollectionChangedEventArgs with given fields (no validation). Used by WinRT marshaling.
///
internal NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, IList newItems, IList oldItems, int newIndex, int oldIndex)
{
_action = action;
_newItems = (newItems == null) ? null : new ReadOnlyList(newItems);
_oldItems = (oldItems == null) ? null : new ReadOnlyList(oldItems);
_newStartingIndex = newIndex;
_oldStartingIndex = oldIndex;
}
private void InitializeAddOrRemove(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, IList changedItems, int startingIndex)
{
if (action == PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Add)
InitializeAdd(action, changedItems, startingIndex);
else if (action == PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Remove)
InitializeRemove(action, changedItems, startingIndex);
else
Debug.Assert(false, String.Format("Unsupported action: {0}", action.ToString()));
}
private void InitializeAdd(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, IList newItems, int newStartingIndex)
{
_action = action;
_newItems = (newItems == null) ? null : new ReadOnlyList(newItems);
_newStartingIndex = newStartingIndex;
}
private void InitializeRemove(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, IList oldItems, int oldStartingIndex)
{
_action = action;
_oldItems = (oldItems == null) ? null : new ReadOnlyList(oldItems);
_oldStartingIndex = oldStartingIndex;
}
private void InitializeMoveOrReplace(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, IList newItems, IList oldItems, int startingIndex, int oldStartingIndex)
{
InitializeAdd(action, newItems, startingIndex);
InitializeRemove(action, oldItems, oldStartingIndex);
}
//------------------------------------------------------
//
// Public Properties
//
//------------------------------------------------------
///
/// The action that caused the event.
///
public PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction Action
{
get { return _action; }
}
///
/// The items affected by the change.
///
public IList NewItems
{
get { return _newItems; }
}
///
/// The old items affected by the change (for Replace events).
///
public IList OldItems
{
get { return _oldItems; }
}
///
/// The index where the change occurred.
///
public int NewStartingIndex
{
get { return _newStartingIndex; }
}
///
/// The old index where the change occurred (for Move events).
///
public int OldStartingIndex
{
get { return _oldStartingIndex; }
}
//------------------------------------------------------
//
// Private Fields
//
//------------------------------------------------------
private PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction _action;
private IList _newItems, _oldItems;
private int _newStartingIndex = -1;
private int _oldStartingIndex = -1;
}
internal sealed class ReadOnlyList : IList
{
private readonly IList _list;
internal ReadOnlyList(IList list)
{
Debug.Assert(list != null);
_list = list;
}
public int Count
{
get { return _list.Count; }
}
public bool IsReadOnly
{
get { return true; }
}
public bool IsFixedSize
{
get { return true; }
}
public bool IsSynchronized
{
get { return _list.IsSynchronized; }
}
public object this[int index]
{
get
{
return _list[index];
}
set
{
throw new NotSupportedException();
}
}
public object SyncRoot
{
get { return _list.SyncRoot; }
}
public int Add(object value)
{
throw new NotSupportedException();
}
public void Clear()
{
throw new NotSupportedException();
}
public bool Contains(object value)
{
return _list.Contains(value);
}
public void CopyTo(Array array, int index)
{
_list.CopyTo(array, index);
}
public IEnumerator GetEnumerator()
{
return _list.GetEnumerator();
}
public int IndexOf(object value)
{
return _list.IndexOf(value);
}
public void Insert(int index, object value)
{
throw new NotSupportedException();
}
public void Remove(object value)
{
throw new NotSupportedException();
}
public void RemoveAt(int index)
{
throw new NotSupportedException();
}
}
}
#endif