Пример #1
0
        protected override void BindProperty(object property)
        {
            boundProperty = property as IReadOnlyObservableCollection <T>;

            if (boundProperty == null)
            {
                boundProperty = BoxCollection(property);
            }

            if (boundProperty != null)
            {
                boundProperty.Reset        += OnBoundPropertyReset;
                boundProperty.CountChanged += OnBoundPropertyCountChanged;
                boundProperty.ItemAdded    += OnBoundPropertyItemAdded;
                boundProperty.ItemMoved    += OnBoundPropertyItemMoved;
                boundProperty.ItemRemoved  += OnBoundPropertyItemRemoved;
                boundProperty.ItemReplaced += OnBoundPropertyItemReplaced;

                exposedProperty.Clear();

                foreach (var item in boundProperty)
                {
                    exposedProperty.Add(item);
                }
            }
            else
            {
                Debug.LogError($"Property type ({property.GetType()}) cannot be bound as {typeof(IReadOnlyObservableCollection<T>)}", context);
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="GroupingContainerList{TSource, TKey}"/> class.
        /// </summary>
        /// <param name="owner">The owner.</param>
        /// <param name="collection">The initial container collection.</param>
        /// <param name="keyComparer">The key comparer.</param>
        /// <param name="groups">The initial groups.</param>
        /// <exception cref="System.ArgumentException">At least one of the explicit groups is already in use.</exception>
        protected GroupingContainerList(IReadOnlyObservableCollection <ReadOnlyObservableGroup <TSource, TKey> > owner,
                                        IEnumerable <GroupedItemContainer <TSource, TKey> > collection, IEqualityComparer <TKey> keyComparer,
                                        IReadOnlyObservableCollection <ReadOnlyObservableGroup <TSource, TKey> > groups) : base(collection)
        {
            KeyComparer = keyComparer;
            Groups      = groups;
            Owner       = owner;

            foreach (var group in Groups)
            {
                if (group.Owner != null)
                {
                    throw new ArgumentException("At least one of the explicit groups is already in use.");
                }
                group.Owner = Owner;
            }

            for (var i = 0; i < Items.Count; i++)
            {
                var container = Items[i];
                container.SourceIndex   = i;
                container.GroupIndex    = -1;
                container.Group         = null;
                container.ValueChanged += ContainerOnKeyChanged;
            }
        }
Пример #3
0
 /// <summary>
 /// Initializes a new instance of the <see cref="SetDifferenceReadOnlyObservableCollection{T}"/> class.
 /// </summary>
 /// <param name="originalSource">The source collection.</param>
 /// <param name="substractedSource">The items to exclude from <paramref name="originalSource"/>.</param>
 /// <param name="comparer">The equality comparer.</param>
 public SetDifferenceReadOnlyObservableCollection(IReadOnlyObservableCollection <T> originalSource,
                                                  IReadOnlyObservableCollection <T> substractedSource, IEqualityComparer <T> comparer = null) : base(
         originalSource,
         substractedSource,
         comparer ?? EqualityComparer <T> .Default,
         new ObservableSet <T>(new HashSet <T>(comparer)))
 {
 }
Пример #4
0
 /// <summary>
 /// Observes propertychanges for items in the collection.
 /// </summary>
 /// <typeparam name="TProperty"></typeparam>
 /// <typeparam name="TItem">The type of the items in the collection</typeparam>
 /// <param name="source"></param>
 /// <param name="property">Sample: item => item.SomeProp.SomeNestedProp</param>
 /// <param name="signalInitial">When true a reset is singaled on subscribe.</param>
 /// <returns></returns>
 public static IObservable <EventPattern <ItemPropertyChangedEventArgs <TItem, TProperty> > > ObserveItemPropertyChanged <TItem, TProperty>(
     this IReadOnlyObservableCollection <TItem> source,
     Expression <Func <TItem, TProperty> > property,
     bool signalInitial = true)
     where TItem : class, INotifyPropertyChanged
 {
     return(new ItemsObservable <IReadOnlyObservableCollection <TItem>, TItem, TProperty>(source, property, signalInitial));
 }
        public static IDisposable connect_item_hooks <T>(IReadOnlyObservableCollection <T> source, Func <T, IDisposable> get_item_hook)
        {
            var item_hooks = source.Select(get_item_hook).ToList();

            return(new CompositeDisposable(
                       Disposable.wrap_collection(item_hooks),
                       source.Subscribe((s, e) => CollectionHelper.reflect_change(item_hooks, source, get_item_hook, d => d.Dispose(), e))));
        }
Пример #6
0
 public static ReadOnlyFilteredView <T> AsReadOnlyFilteredView <T>(
     this IReadOnlyObservableCollection <T> collection,
     Func <T, bool> filter,
     params IObservable <object>[] triggers)
 {
     Ensure.NotNull(collection, nameof(collection));
     return(new ReadOnlyFilteredView <T>(collection, filter, TimeSpan.Zero, null, triggers));
 }
        private DistinctReadOnlyObservableCollection(IReadOnlyObservableCollection <T> source, ObservableDictionary <T, int> containers) : base(containers.Keys)
        {
            _source     = source;
            _containers = containers;
            AddRange(_containers, _source);

            CollectionChangedEventManager.AddListener(_source, this);
        }
Пример #8
0
        /// <summary>
        /// Invokes an action for each item in a collection and subsequently each item added or
        /// removed from the collection.
        /// </summary>
        /// <typeparam name="T">The type of the collection items.</typeparam>
        /// <param name="collection">The collection.</param>
        /// <param name="added">
        /// An action called initially for each item in the collection and subsequently for each
        /// item added to the collection.
        /// </param>
        /// <param name="removed">
        /// An action called for each item removed from the collection.
        /// </param>
        /// <param name="reset">
        /// An action called when the collection is reset. This will be followed by calls to
        /// <paramref name="added"/> for each item present in the collection after the reset.
        /// </param>
        /// <returns>A disposable used to terminate the subscription.</returns>
        public static IDisposable ForEachItem <T>(
            this IReadOnlyObservableCollection <T> collection,
            Action <T> added,
            Action <T> removed,
            Action reset)
        {
            Action <IList> add = items =>
            {
                foreach (T item in items)
                {
                    added(item);
                }
            };

            Action <IList> remove = items =>
            {
                for (var i = items.Count - 1; i >= 0; --i)
                {
                    removed((T)items[i]);
                }
            };

            NotifyCollectionChangedEventHandler handler = (_, e) =>
            {
                switch (e.Action)
                {
                case NotifyCollectionChangedAction.Add:
                    add(e.NewItems);
                    break;

                case NotifyCollectionChangedAction.Move:
                case NotifyCollectionChangedAction.Replace:
                    remove(e.OldItems);
                    add(e.NewItems);
                    break;

                case NotifyCollectionChangedAction.Remove:
                    remove(e.OldItems);
                    break;

                case NotifyCollectionChangedAction.Reset:
                    if (reset == null)
                    {
                        throw new InvalidOperationException(
                                  "Reset called on collection without reset handler.");
                    }

                    reset();
                    add((IList)collection);
                    break;
                }
            };

            add((IList)collection);
            collection.CollectionChanged += handler;

            return(new ActionDisposable(() => collection.CollectionChanged -= handler));
        }
Пример #9
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ConditionalSwitchableCollectionSource{T}"/> class.
        /// </summary>
        /// <param name="condition">The condition.</param>
        /// <param name="positiveSource">The positive source.</param>
        /// <param name="negativeSource">The negative source.</param>
        public ConditionalSwitchableCollectionSource(IObservable <bool> condition,
                                                     IReadOnlyObservableCollection <T> positiveSource, IReadOnlyObservableCollection <T> negativeSource)
        {
            _condition      = condition ?? throw new ArgumentNullException(nameof(condition));
            _positiveSource = positiveSource;
            _negativeSource = negativeSource;

            _subscription = condition.Subscribe(this);
        }
Пример #10
0
 /// <summary>
 /// Initializes a new instance of the <see cref="SetDifferenceReadOnlyObservableList{T}"/> class.
 /// </summary>
 /// <param name="originalSource">The source collection.</param>
 /// <param name="substractedSource">The items to exclude from <paramref name="originalSource"/>.</param>
 /// <param name="comparer">The equality comparer.</param>
 public SetDifferenceReadOnlyObservableList(IReadOnlyObservableCollection <T> originalSource,
                                            IReadOnlyObservableCollection <T> substractedSource, IEqualityComparer <T> comparer = null) : this(
         originalSource,
         substractedSource,
         comparer ?? EqualityComparer <T> .Default,
         new ObservableDictionary <T, RefCountItemContainer <T> >(
             new Dictionary <T, RefCountItemContainer <T> >(comparer ?? EqualityComparer <T> .Default)))
 {
 }
Пример #11
0
 /// <summary>
 /// Create a filtered view for <paramref name="source"/>
 /// </summary>
 /// <typeparam name="T">The type of the elements in the source collection.</typeparam>
 /// <param name="source">The source collection</param>
 /// <param name="filter">The predicate to filter by.</param>
 /// <param name="triggers">Triggers for when filtering is updated.</param>
 /// <returns>A <see cref="ReadOnlyFilteredView{T}"/></returns>
 public static ReadOnlyFilteredView <T> AsReadOnlyFilteredView <T>(
     this IReadOnlyObservableCollection <T> source,
     Func <T, bool> filter,
     params IObservable <object>[] triggers)
 {
     Ensure.NotNull(source, nameof(source));
     Ensure.NotNull(filter, nameof(filter));
     return(new ReadOnlyFilteredView <T>(source, filter, TimeSpan.Zero, null, false, triggers));
 }
Пример #12
0
 public static MappingView <TSource, TResult> AsMappingView <TSource, TResult>(
     this IReadOnlyObservableCollection <TSource> source,
     Func <TSource, int, TResult> selector,
     IScheduler scheduler)
 {
     Ensure.NotNull(source, nameof(source));
     Ensure.NotNull(selector, nameof(selector));
     return(new MappingView <TSource, TResult>(source, selector, scheduler, null));
 }
Пример #13
0
 public static MappingView <TSource, TResult> AsMappingView <TSource, TResult>(
     this IReadOnlyObservableCollection <TSource> source,
     Func <TSource, int, TResult> selector,
     params IObservable <object>[] triggers)
 {
     Ensure.NotNull(source, nameof(source));
     Ensure.NotNull(selector, nameof(selector));
     return(new MappingView <TSource, TResult>(source, selector, null, triggers));
 }
Пример #14
0
        private static void OnEventDaysPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            EventsView s = (EventsView)sender;
            IReadOnlyObservableCollection <EventDay> oldValue = (IReadOnlyObservableCollection <EventDay>)e.OldValue;
            IReadOnlyObservableCollection <EventDay> newValue = (IReadOnlyObservableCollection <EventDay>)e.NewValue;

            s.Unsubscribe(oldValue);
            s.Subscrube(newValue);
            s.UpdateViewEvents(newValue);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="SortedReadOnlyObservableList{T}"/> class.
 /// </summary>
 /// <param name="source">The source collection.</param>
 /// <param name="comparison">The comparison used to establish the order of elements.</param>
 /// <param name="comparer">
 /// A comparer for the list items. This is only used if the source collection is not a list
 /// and does not provide index information in its <see cref="NotifyCollectionChangedEventArgs"/> events.
 /// </param>
 /// <param name="triggers">The name of <typeparamref name="T"/>'s properties that can alter the collection's order.</param>
 public SortedReadOnlyObservableList(IReadOnlyObservableCollection <T> source, Comparison <T> comparison, IEqualityComparer <T> comparer,
                                     params string[] triggers)
 {
     _source     = source;
     _eqComparer = new ContainerEqualityComparer <T, Container>(comparer);
     _items      = new ContainerCollection(from item in source select new Container(item),
                                           new ContainerComparer(comparison), triggers);
     _items.SortedCollectionChanged += (sender, args) => RaiseEvents(args);
     CollectionChangedEventManager.AddListener(_source, this);
 }
 /// <summary>
 ///     Initializes a new instance of the <see cref="TransformingReadOnlyObservableList{TSource, TTarget}" /> class.
 /// </summary>
 /// <param name="source">The source collection.</param>
 /// <param name="selector">The transformation to apply to the items in <paramref name="source" />.</param>
 /// <param name="onRemove">The callback to execute when an item is removed from the collection.</param>
 /// <param name="targetComparer">
 /// A comparer for the list items. This is only used if the source collection is not a list
 /// and does not provide index information in its <see cref="NotifyCollectionChangedEventArgs"/> events.
 /// </param>
 public TransformingReadOnlyObservableList(IReadOnlyObservableCollection <TSource> source,
                                           Func <TSource, TTarget> selector, Action <TTarget> onRemove = null, IEqualityComparer <TTarget> targetComparer = null)
     : base(new ObservableCollection <TTarget>(source.Select(selector)))
 {
     _source         = source;
     _selector       = selector;
     _onRemove       = onRemove;
     _sourceComparer = targetComparer ?? EqualityComparer <TTarget> .Default;
     CollectionChangedEventManager.AddListener(source, this);
 }
Пример #17
0
 public CollectionBoxer(IReadOnlyObservableCollection <TBoxed> boxedCollection)
 {
     this.boxedCollection          = boxedCollection;
     boxedCollection.ItemAdded    += BoxedCollectionItemAddedHandler;
     boxedCollection.CountChanged += BoxedCollectionCountChangedHandler;
     boxedCollection.ItemRemoved  += BoxedCollectionItemRemovedHandler;
     boxedCollection.ItemMoved    += BoxedCollectionItemMovedHandler;
     boxedCollection.ItemReplaced += BoxedCollectionItemReplacedHandler;
     boxedCollection.Reset        += BoxedCollectionResetHandler;
 }
        /// <summary>
        /// Observes propertychanges for items in the collection.
        /// </summary>
        /// <typeparam name="TItem">The type of the items in the collection</typeparam>
        /// <typeparam name="TProperty">The type of the property.</typeparam>
        /// <param name="source">The sopurce item to track changes for.</param>
        /// <param name="property">Sample: item => item.SomeProp.SomeNestedProp</param>
        /// <param name="signalInitial">When true a reset is singaled on subscribe.</param>
        public static IObservable <PropertyChangedEventArgs> ObserveItemPropertyChangedSlim <TItem, TProperty>(
            this IReadOnlyObservableCollection <TItem> source,
            Expression <Func <TItem, TProperty> > property,
            bool signalInitial = true)
            where TItem : class, INotifyPropertyChanged
        {
            Ensure.NotNull(source, nameof(source));
            Ensure.NotNull(property, nameof(property));

            return(ObserveItemPropertyChangedSlim <IReadOnlyObservableCollection <TItem>, TItem, TProperty>(source, property, signalInitial));
        }
Пример #19
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="TItem"></typeparam>
        /// <typeparam name="TValue"></typeparam>
        /// <param name="source"></param>
        /// <param name="selector"></param>
        /// <param name="whenEmpty"></param>
        /// <param name="trackItemChanges">If true we subscribe to property changes for each item. This is much slower.</param>
        /// <returns>A tracker with Value synced with source.Max()</returns>
        public static MaxTracker <TValue> TrackMax <TItem, TValue>(this IReadOnlyObservableCollection <TItem> source, Expression <Func <TItem, TValue> > selector, TValue?whenEmpty, bool trackItemChanges)
            where TItem : class, INotifyPropertyChanged
            where TValue : struct, IComparable <TValue>
        {
            var onItemChanged = trackItemChanges
                                    ? source.ObserveItemPropertyChanged(selector, false)
                                    : null;
            var mapped = source.AsMappingView(selector.Compile(), onItemChanged);

            return(new MaxTracker <TValue>(mapped, mapped.ObserveCollectionChangedSlim(false), whenEmpty));
        }
Пример #20
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ContainsObservableResult{T}"/> class.
        /// </summary>
        /// <param name="source">The source.</param>
        /// <param name="value">The value to find.</param>
        /// <param name="comparer">The equality comparer. If it is <c>null</c> the default comparer is used.</param>
        /// <exception cref="System.ArgumentNullException">value</exception>
        public ContainsObservableResult(IReadOnlyObservableCollection <T> source, T value, IEqualityComparer <T> comparer = null) : base(source)
        {
            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }
            Value     = value;
            _comparer = comparer ?? EqualityComparer <T> .Default;

            CurrentValue = source.Contains(value, _comparer);
        }
Пример #21
0
 public static ReadOnlyFilteredView <T> AsReadOnlyFilteredView <T>(
     this IReadOnlyObservableCollection <T> collection,
     Func <T, bool> filter,
     TimeSpan bufferTime,
     IScheduler scheduler,
     params IObservable <object>[] triggers)
 {
     Ensure.NotNull(collection, nameof(collection));
     Ensure.NotNull(filter, nameof(filter));
     Ensure.NotNull(scheduler, nameof(scheduler));
     return(new ReadOnlyFilteredView <T>(collection, filter, bufferTime, scheduler, triggers));
 }
Пример #22
0
 public static MappingView <TSource, TResult> AsMappingView <TSource, TResult>(
     this IReadOnlyObservableCollection <TSource> source,
     Func <TSource, int, TResult> selector,
     Func <TResult, int, TResult> updater,
     IScheduler scheduler)
     where TSource : class
     where TResult : class
 {
     Ensure.NotNull(source, nameof(source));
     Ensure.NotNull(selector, nameof(selector));
     Ensure.NotNull(updater, nameof(updater));
     return(new MappingView <TSource, TResult>(source, selector, updater, scheduler));
 }
        public NestedChanges(TCollection source, Expression <Func <TItem, TValue> > selector)
        {
            var path = NotifyingPath.GetOrCreate(selector);

            this.source = new MappingView <TItem, ValueTracker>(
                source: source,
                factory: Mapper.Create <TItem, ValueTracker>(x => new ValueTracker(this, x, path), x => x.Dispose()),
                bufferTime: TimeSpan.Zero,
                scheduler: null,
                leaveOpen: true);
            this.subscription = source.ObserveCollectionChangedSlim(signalInitial: false)
                                .Subscribe(this.OnSourceChanged);
        }
Пример #24
0
        public TrackingCollection(
            [CanBeNull] IReadOnlyObservableList <TFrom> sourceItems,
            [NotNull] Func <TFrom, TTo> createTargetItemFunc)
        {
            _sourceItems          = sourceItems;
            _createTargetItemFunc = createTargetItemFunc ?? throw new ArgumentNullException(nameof(createTargetItemFunc));
            _targetItemsWrapper   = new ReadOnlyObservableCollectionWrapper <TTo, TTo>(_targetItems);

            if (sourceItems != null)
            {
                SetSource(sourceItems);
            }
        }
Пример #25
0
        protected override void UnbindProperty()
        {
            if (boundProperty != null)
            {
                boundProperty.Reset        -= OnBoundPropertyReset;
                boundProperty.CountChanged -= OnBoundPropertyCountChanged;
                boundProperty.ItemAdded    -= OnBoundPropertyItemAdded;
                boundProperty.ItemMoved    -= OnBoundPropertyItemMoved;
                boundProperty.ItemRemoved  -= OnBoundPropertyItemRemoved;
                boundProperty.ItemReplaced -= OnBoundPropertyItemReplaced;

                boundProperty = null;
            }
        }
Пример #26
0
        /// <summary>
        ///     Initializes a new instance of the <see cref="FilteredReadOnlyObservableCollectionBase{TItem, TContainer}"/> class.
        /// </summary>
        /// <param name="items">The collection of item containers.</param>
        /// <param name="source">The source collection.</param>
        /// <param name="filter">The filter predicate.</param>
        /// <param name="itemComparer">The equality comparer for the items, in case <paramref name="source"/> is an index-less collection.</param>
        protected FilteredReadOnlyObservableCollectionBase(ObservableCollection <TContainer> items,
                                                           IReadOnlyObservableCollection <TItem> source, Func <TItem, IObservable <bool> > filter, IEqualityComparer <TItem> itemComparer)
        {
            Source            = source;
            Filter            = filter;
            Items             = items;
            ContainerComparer = new ContainerEqualityComparer <TItem, TContainer>(itemComparer);

            CollectionChangedEventManager.AddListener(Source, this);
            foreach (var item in source)
            {
                Items.Add(CreateContainer(item));
            }
        }
Пример #27
0
        private static IReadOnlyObservableCollection <T> BoxCollection(object collectionToBox)
        {
            IReadOnlyObservableCollection <T> result = null;

            Type collectionGenericType = collectionToBox.GetType().GetGenericTypeTowardsRoot();

            if (collectionGenericType != null)
            {
                Type exposedType    = typeof(T);
                Type boxedType      = collectionGenericType.GenericTypeArguments[0];
                Type activationType = typeof(CollectionBoxer <,>).MakeGenericType(exposedType, boxedType);
                result = Activator.CreateInstance(activationType, collectionToBox) as IReadOnlyObservableCollection <T>;
            }

            return(result);
        }
Пример #28
0
        protected override NotifyCollectionChangedEventArgs BuildCompositeEventArgs(IReadOnlyObservableCollection <T> sender, NotifyCollectionChangedEventArgs e)
        {
            int GetSenderStartIndex() => ObservableCollections.TakeWhile(x => x != sender).Sum(x => x.Count);
            int GetNewItemsIndex() => GetSenderStartIndex() + (e.NewStartingIndex >= 0 ? e.NewStartingIndex : sender.Count);
            int GetOldItemsIndex() => GetSenderStartIndex() + (e.OldStartingIndex >= 0 ? e.OldStartingIndex : sender.IndexOf(x => EqualityComparer <T> .Default.Equals(x, (T)e.OldItems[0])));

            switch (e.Action)
            {
            case NotifyCollectionChangedAction.Add:
            {
                return(CollectionChangedEventArgs.InsertRange(e.NewItems, GetNewItemsIndex()));
            }

            case NotifyCollectionChangedAction.Remove:
            {
                return(CollectionChangedEventArgs.RemoveRange(e.OldItems, GetOldItemsIndex()));
            }

            case NotifyCollectionChangedAction.Replace:
            {
                return(CollectionChangedEventArgs.ReplaceRange(e.OldItems, e.NewItems, GetOldItemsIndex()));
            }

            case NotifyCollectionChangedAction.Move:
            {
                return(null);
            }

            case NotifyCollectionChangedAction.Reset:
            {
                if (sender.Count == Count)
                {
                    return(CollectionChangedEventArgs.Clear());
                }

                return(CollectionChangedEventArgs.RemoveRange(sender.ToList(), GetSenderStartIndex()));
            }

            default:
                throw new NotSupportedException();
            }
        }
 /// <summary>
 /// Create a <see cref="ReadOnlyThrottledView{T}"/> view for <paramref name="source"/>
 /// </summary>
 /// <typeparam name="T">The type of the elements in the collection.</typeparam>
 /// <param name="source">The source collection</param>
 /// <param name="bufferTime">The time to buffer changes in <paramref name="source"/></param>
 /// <param name="scheduler">The scheduler to notify changes on.</param>
 /// <param name="leaveOpen">True means that the <paramref name="source"/> is not disposed when this instance is disposed.</param>
 /// <returns>A <see cref="ReadOnlyThrottledView{T}"/></returns>
 public static ReadOnlyThrottledView <T> AsReadOnlyThrottledView <T>(this IReadOnlyObservableCollection <T> source, TimeSpan bufferTime, IScheduler scheduler, bool leaveOpen = false)
 {
     return(new ReadOnlyThrottledView <T>(source, bufferTime, scheduler, leaveOpen));
 }
Пример #30
0
 public ReadOnlyThrottledView(IReadOnlyObservableCollection <T> collection, TimeSpan bufferTime, IScheduler scheduler)
     : this(bufferTime, scheduler, collection)
 {
 }