コード例 #1
0
        /// <summary>
        /// Converts a <see cref="CollectionModification{T}"/> to a list of <see cref="CollectionNotification{T}"/>.
        /// </summary>
        /// <typeparam name="T">The object that provides modification information.</typeparam>
        /// <param name="modification">The <see cref="CollectionModification{T}"/> to be converted.</param>
        /// <returns>A list of <see cref="CollectionNotification{T}"/> containing
        /// <see cref="CollectionNotificationKind.OnAdded"/> when the specified <paramref name="modification"/> is <see cref="CollectionModificationKind.Add"/>,
        /// <see cref="CollectionNotificationKind.OnRemoved"/> when the specified <paramref name="modification"/> is <see cref="CollectionModificationKind.Remove"/>, or
        /// <see cref="CollectionNotificationKind.OnCleared"/> when the specified <paramref name="modification"/> is <see cref="CollectionModificationKind.Clear"/>.</returns>
        public static IList <CollectionNotification <T> > ToNotifications <T>(this CollectionModification <T> modification)
        {
            Contract.Requires(modification != null);
            Contract.Ensures(Contract.Result <IList <CollectionNotification <T> > >() != null);
            Contract.Ensures(Contract.Result <IList <CollectionNotification <T> > >().IsReadOnly);

            var list = new List <CollectionNotification <T> >();

            IList <T> values;

            switch (modification.Kind)
            {
            case CollectionModificationKind.Add:
                values = modification.Values;

                for (int i = 0; i < values.Count; i++)
                {
                    list.Add(CollectionNotification.CreateOnAdded <T>(values[i]));
                }
                break;

            case CollectionModificationKind.Remove:
                values = modification.Values;

                for (int i = 0; i < values.Count; i++)
                {
                    list.Add(CollectionNotification.CreateOnRemoved <T>(values[i]));
                }
                break;

            case CollectionModificationKind.Clear:
                list.Add(CollectionNotification.CreateOnCleared <T>());
                break;
            }

            IList <CollectionNotification <T> > result = list.AsReadOnly();

            Contract.Assume(result.IsReadOnly);

            return(result);
        }
        /// <summary>
        /// Converts a <see cref="CollectionNotification{T}"/> to a list of <see cref="CollectionModification{T}"/>.
        /// </summary>
        /// <typeparam name="T">The object that provides notification information.</typeparam>
        /// <param name="notification">The <see cref="CollectionNotification{T}"/> to be converted.</param>
        /// <returns>A list of <see cref="CollectionModification{T}"/> containing
        /// <see cref="CollectionModificationKind.Add"/> when the specified <paramref name="notification"/> is <see cref="CollectionNotificationKind.Exists"/> or <see cref="CollectionNotificationKind.OnAdded"/>,
        /// <see cref="CollectionModificationKind.Remove"/> followed by <see cref="CollectionModificationKind.Add"/> when the specified <paramref name="notification"/> is <see cref="CollectionNotificationKind.OnReplaced"/>,
        /// <see cref="CollectionModificationKind.Remove"/> when the specified <paramref name="notification"/> is <see cref="CollectionNotificationKind.OnRemoved"/>, or
        /// <see cref="CollectionModificationKind.Clear"/> when the specified <paramref name="notification"/> is <see cref="CollectionNotificationKind.OnCleared"/>.</returns>
        public static IList <CollectionModification <T> > ToModifications <T>(this CollectionNotification <T> notification)
        {
            Contract.Requires(notification != null);
            Contract.Ensures(Contract.Result <IList <CollectionModification <T> > >() != null);
            Contract.Ensures(Contract.Result <IList <CollectionModification <T> > >().IsReadOnly);

            var list = new List <CollectionModification <T> >();

            switch (notification.Kind)
            {
            case CollectionNotificationKind.Exists:
                list.Add(CollectionModification.CreateAdd <T>(notification.ExistingValues));
                break;

            case CollectionNotificationKind.OnAdded:
                list.Add(CollectionModification.CreateAdd <T>(notification.Value));
                break;

            case CollectionNotificationKind.OnRemoved:
                list.Add(CollectionModification.CreateRemove <T>(notification.Value));
                break;

            case CollectionNotificationKind.OnReplaced:
                list.Add(CollectionModification.CreateRemove <T>(notification.ReplacedValue));
                list.Add(CollectionModification.CreateAdd <T>(notification.Value));
                break;

            case CollectionNotificationKind.OnCleared:
                list.Add(CollectionModification.CreateClear <T>());
                break;
            }

            IList <CollectionModification <T> > result = list.AsReadOnly();

            Contract.Assume(result.IsReadOnly);

            return(result);
        }
        /// <summary>
        /// Converts <see cref="INotifyCollectionChanged.CollectionChanged"/> events into an observable sequence of <see cref="CollectionModification{T}"/>.
        /// </summary>
        /// <typeparam name="T">The object that provides notification information.</typeparam>
        /// <param name="source">An implementation of <see cref="INotifyCollectionChanged"/> that raises events when a collection changes.</param>
        /// <remarks>
        /// An <see cref="NotifyCollectionChangedAction.Add"/> event is projected into zero or more <see cref="CollectionModificationKind.Add"/> modifications.
        /// A <see cref="NotifyCollectionChangedAction.Remove"/> event is projected into zero or more <see cref="CollectionModificationKind.Remove"/> modifications.
        /// A <see cref="NotifyCollectionChangedAction.Move"/> event is ignored.
        /// A <see cref="NotifyCollectionChangedAction.Replace"/> event is projected into zero or more sequential
        /// <see cref="CollectionModificationKind.Remove"/> and <see cref="CollectionModificationKind.Add"/> modifications.
        /// A <see cref="NotifyCollectionChangedAction.Reset"/> event is projected into a single <see cref="CollectionModificationKind.Clear"/> modification.
        /// </remarks>
        /// <returns>An observable sequence of <see cref="CollectionModification{T}"/> objects corresponding to raised events.</returns>
#else
        /// <summary>
        /// Converts <see cref="INotifyCollectionChanged.CollectionChanged"/> events into an observable sequence of <see cref="CollectionModification{T}"/>.
        /// </summary>
        /// <typeparam name="T">The object that provides notification information.</typeparam>
        /// <param name="source">An implementation of <see cref="INotifyCollectionChanged"/> that raises events when a collection changes.</param>
        /// <remarks>
        /// An <see cref="NotifyCollectionChangedAction.Add"/> event is projected into zero or more <see cref="CollectionModificationKind.Add"/> modifications.
        /// A <see cref="NotifyCollectionChangedAction.Remove"/> event is projected into zero or more <see cref="CollectionModificationKind.Remove"/> modifications.
        /// A <see cref="NotifyCollectionChangedAction.Replace"/> event is projected into zero or more sequential
        /// <see cref="CollectionModificationKind.Remove"/> and <see cref="CollectionModificationKind.Add"/> modifications.
        /// A <see cref="NotifyCollectionChangedAction.Reset"/> event is projected into a single <see cref="CollectionModificationKind.Clear"/> modification.
        /// </remarks>
        /// <returns>An observable sequence of <see cref="CollectionModification{T}"/> objects corresponding to raised events.</returns>
#endif
        public static IObservable <CollectionModification <T> > AsCollectionModifications <T>(this INotifyCollectionChanged source)
        {
            Contract.Requires(source != null);
            Contract.Ensures(Contract.Result <IObservable <CollectionModification <T> > >() != null);

            return(Observable.FromEventPattern <NotifyCollectionChangedEventHandler, NotifyCollectionChangedEventArgs>(
                       eh => source.CollectionChanged += eh,
                       eh => source.CollectionChanged -= eh)
                   .SelectMany(e =>
            {
                var args = e.EventArgs;

                switch (args.Action)
                {
                case NotifyCollectionChangedAction.Add:
                    return Observable.Return(CollectionModification.CreateAdd(EnsureList <T>(args.NewItems)));

                case NotifyCollectionChangedAction.Remove:
                    return Observable.Return(CollectionModification.CreateRemove(EnsureList <T>(args.OldItems)));

#if !SILVERLIGHT
                case NotifyCollectionChangedAction.Move:
                    return Observable.Empty <CollectionModification <T> >();
#endif
                case NotifyCollectionChangedAction.Replace:
                    return Observable.Return(CollectionModification.CreateRemove(EnsureList <T>(args.OldItems)))
                    .Concat(Observable.Return(CollectionModification.CreateAdd(EnsureList <T>(args.NewItems))));

                case NotifyCollectionChangedAction.Reset:
                    return Observable.Return(CollectionModification.CreateClear <T>());

                default:
                    throw new InvalidOperationException();
                }
            }));
        }
コード例 #4
0
 /// <summary>
 /// Compares the specified modification for <see cref="Kind"/> and <see cref="Values"/> equality.
 /// </summary>
 /// <param name="other">The other modification to compare.</param>
 /// <returns><see langword="True"/> if the <see cref="Kind"/> and <see cref="Values"/> of each modification are equal;
 /// otherwise, <see langword="false" />.</returns>
 public bool Equals(CollectionModification <T> other)
 {
     return(!object.ReferenceEquals(other, null) &&
            other.Kind == Kind &&
            (!HasValues || other.Values.SequenceEqual(Values)));
 }