/// <summary>
        /// Construct a NotifyChangeRequestedEventArgs that describes a one-item change.
        /// </summary>
        /// <param name="action">The action that caused the event.</param>
        /// <param name="changedItem">The item affected by the change.</param>
        /// <param name="index">The index where the change occurred.</param>
        public NotifyChangeRequestedEventArgs(NotifyChangeRequestedAction action, T changedItem, int index)
        {
            if ((action != NotifyChangeRequestedAction.Add) && (action != NotifyChangeRequestedAction.Remove) &&
                (action != NotifyChangeRequestedAction.Reset))
            {
                throw new ArgumentException(SR.MustBeResetAddOrRemoveActionForCtor, nameof(action));
            }

            if (action == NotifyChangeRequestedAction.Reset)
            {
                if (changedItem != null)
                {
                    throw new ArgumentException(SR.ResetActionRequiresNullItem, nameof(action));
                }
                if (index != -1)
                {
                    throw new ArgumentException(SR.ResetActionRequiresIndexMinus1, nameof(action));
                }

                InitializeAdd(action, null, -1);
            }
            else
            {
                InitializeAddOrRemove(action, new T[] { changedItem }, index);
            }
        }
        /// <summary>
        /// Construct a NotifyChangeRequestedEventArgs that describes a multi-item change (or a reset).
        /// </summary>
        /// <param name="action">The action that caused the event.</param>
        /// <param name="changedItems">The items affected by the change.</param>
        /// <param name="startingIndex">The index where the change occurred.</param>
        public NotifyChangeRequestedEventArgs(NotifyChangeRequestedAction action, IList <T> changedItems, int startingIndex)
        {
            if ((action != NotifyChangeRequestedAction.Add) && (action != NotifyChangeRequestedAction.Remove) &&
                (action != NotifyChangeRequestedAction.Reset))
            {
                throw new ArgumentException(SR.MustBeResetAddOrRemoveActionForCtor, nameof(action));
            }

            if (action == NotifyChangeRequestedAction.Reset)
            {
                if (changedItems != null)
                {
                    throw new ArgumentException(SR.ResetActionRequiresNullItem, nameof(action));
                }
                if (startingIndex != -1)
                {
                    throw new ArgumentException(SR.ResetActionRequiresIndexMinus1, nameof(action));
                }

                InitializeAdd(action, null, -1);
            }
            else
            {
                if (changedItems == null)
                {
                    throw new ArgumentNullException(nameof(changedItems));
                }
                if (startingIndex < -1)
                {
                    throw new ArgumentException(SR.IndexCannotBeNegative, nameof(startingIndex));
                }

                InitializeAddOrRemove(action, changedItems, startingIndex);
            }
        }
        /// <summary>
        /// Construct a NotifyChangeRequestedEventArgs that describes a multi-item change.
        /// </summary>
        /// <param name="action">The action that caused the event.</param>
        /// <param name="changedItems">The items affected by the change.</param>
        public NotifyChangeRequestedEventArgs(NotifyChangeRequestedAction action, IList <T> changedItems)
        {
            if ((action != NotifyChangeRequestedAction.Add) && (action != NotifyChangeRequestedAction.Remove) &&
                (action != NotifyChangeRequestedAction.Reset))
            {
                throw new ArgumentException(SR.MustBeResetAddOrRemoveActionForCtor, nameof(action));
            }

            if (action == NotifyChangeRequestedAction.Reset)
            {
                if (changedItems != null)
                {
                    throw new ArgumentException(SR.ResetActionRequiresNullItem, nameof(action));
                }

                InitializeAdd(action, null, -1);
            }
            else
            {
                if (changedItems == null)
                {
                    throw new ArgumentNullException(nameof(changedItems));
                }

                InitializeAddOrRemove(action, changedItems, -1);
            }
        }
 /// <summary>
 /// Construct a NotifyChangeRequestedEventArgs with given fields (no validation). Used by WinRT marshaling.
 /// </summary>
 internal NotifyChangeRequestedEventArgs(NotifyChangeRequestedAction action, IList <T> newItems, IList <T> oldItems, int newIndex, int oldIndex)
 {
     _action           = action;
     _newItems         = (newItems == null) ? null : new ReadOnlyList <T>(newItems);
     _oldItems         = (oldItems == null) ? null : new ReadOnlyList <T>(oldItems);
     _newStartingIndex = newIndex;
     _oldStartingIndex = oldIndex;
 }
        /// <summary>
        /// Construct a NotifyChangeRequestedEventArgs that describes a reset change.
        /// </summary>
        /// <param name="action">The action that caused the event (must be Reset).</param>
        public NotifyChangeRequestedEventArgs(NotifyChangeRequestedAction action)
        {
            if (action != NotifyChangeRequestedAction.Reset)
            {
                throw new ArgumentException(string.Format(SR.WrongActionForCtor, NotifyChangeRequestedAction.Reset), nameof(action));
            }

            InitializeAdd(action, null, -1);
        }
        /// <summary>
        /// Construct a NotifyChangeRequestedEventArgs that describes a one-item Replace event.
        /// </summary>
        /// <param name="action">Can only be a Replace action.</param>
        /// <param name="newItem">The new item replacing the original item.</param>
        /// <param name="oldItem">The original item that is replaced.</param>
        /// <param name="index">The index of the item being replaced.</param>
        public NotifyChangeRequestedEventArgs(NotifyChangeRequestedAction action, T newItem, T oldItem, int index)
        {
            if (action != NotifyChangeRequestedAction.Replace)
            {
                throw new ArgumentException(string.Format(SR.WrongActionForCtor, NotifyChangeRequestedAction.Replace), nameof(action));
            }

            InitializeMoveOrReplace(action, new T[] { newItem }, new T[] { oldItem }, index, index);
        }
 private void InitializeAddOrRemove(NotifyChangeRequestedAction action, IList <T> changedItems, int startingIndex)
 {
     if (action == NotifyChangeRequestedAction.Add)
     {
         InitializeAdd(action, changedItems, startingIndex);
     }
     else
     {
         Debug.Assert(action == NotifyChangeRequestedAction.Remove, $"Unsupported action: {action}");
         InitializeRemove(action, changedItems, startingIndex);
     }
 }
        /// <summary>
        /// Construct a NotifyChangeRequestedEventArgs that describes a multi-item Move event.
        /// </summary>
        /// <param name="action">The action that caused the event.</param>
        /// <param name="changedItems">The items affected by the change.</param>
        /// <param name="index">The new index for the changed items.</param>
        /// <param name="oldIndex">The old index for the changed items.</param>
        public NotifyChangeRequestedEventArgs(NotifyChangeRequestedAction action, IList <T> changedItems, int index, int oldIndex)
        {
            if (action != NotifyChangeRequestedAction.Move)
            {
                throw new ArgumentException(string.Format(SR.WrongActionForCtor, NotifyChangeRequestedAction.Move), nameof(action));
            }
            if (index < 0)
            {
                throw new ArgumentException(SR.IndexCannotBeNegative, nameof(index));
            }

            InitializeMoveOrReplace(action, changedItems, changedItems, index, oldIndex);
        }
        /// <summary>
        /// Construct a NotifyChangeRequestedEventArgs that describes a multi-item Replace event.
        /// </summary>
        /// <param name="action">Can only be a Replace action.</param>
        /// <param name="newItems">The new items replacing the original items.</param>
        /// <param name="oldItems">The original items that are replaced.</param>
        /// <param name="startingIndex">The starting index of the items being replaced.</param>
        public NotifyChangeRequestedEventArgs(NotifyChangeRequestedAction action, IList <T> newItems, IList <T> oldItems, int startingIndex)
        {
            if (action != NotifyChangeRequestedAction.Replace)
            {
                throw new ArgumentException(string.Format(SR.WrongActionForCtor, NotifyChangeRequestedAction.Replace), nameof(action));
            }
            if (newItems == null)
            {
                throw new ArgumentNullException(nameof(newItems));
            }
            if (oldItems == null)
            {
                throw new ArgumentNullException(nameof(oldItems));
            }

            InitializeMoveOrReplace(action, newItems, oldItems, startingIndex, startingIndex);
        }
 private void InitializeMoveOrReplace(NotifyChangeRequestedAction action, IList <T> newItems, IList <T> oldItems, int startingIndex, int oldStartingIndex)
 {
     InitializeAdd(action, newItems, startingIndex);
     InitializeRemove(action, oldItems, oldStartingIndex);
 }
 private void InitializeRemove(NotifyChangeRequestedAction action, IList <T> oldItems, int oldStartingIndex)
 {
     _action           = action;
     _oldItems         = (oldItems == null) ? null : new ReadOnlyList <T>(oldItems);
     _oldStartingIndex = oldStartingIndex;
 }
 private void InitializeAdd(NotifyChangeRequestedAction action, IList <T> newItems, int newStartingIndex)
 {
     _action           = action;
     _newItems         = (newItems == null) ? null : new ReadOnlyList <T>(newItems);
     _newStartingIndex = newStartingIndex;
 }