public ReadOnlyDispatcherCollection(DispatcherCollection <T> collection) : base(collection)
        {
            if (collection == null)
            {
                throw new ArgumentNullException("collection");
            }

            _list = collection;

            _listeners.Add(new PropertyChangedEventListener(_list, (sender, e) => OnPropertyChanged(e)));
            _listeners.Add(new CollectionChangedEventListener(_list, (sender, e) => OnCollectionChanged(e)));
        }
Esempio n. 2
0
        public ReadOnlyDispatcherCollection([NotNull] DispatcherCollection <T> collection) : base(collection)
        {
            _list = collection ?? throw new ArgumentNullException(nameof(collection));

            _listeners.Add(new PropertyChangedEventListener(
                               _list,
                               (sender, e) =>
            {
                if (e != null)
                {
                    OnPropertyChanged(e);
                }
            }));

            _listeners.Add(new CollectionChangedEventListener(
                               _list,
                               (sender, e) =>
            {
                if (e != null)
                {
                    OnCollectionChanged(e);
                }
            }));
        }
Esempio n. 3
0
        public static ReadOnlyDispatcherCollection <TViewModel> CreateReadOnlyDispatcherCollection <TModel, TViewModel>(
            [NotNull] IList <TModel> source, [NotNull] Func <TModel, TViewModel> converter,
            [NotNull] Dispatcher dispatcher)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (converter == null)
            {
                throw new ArgumentNullException(nameof(converter));
            }
            if (dispatcher == null)
            {
                throw new ArgumentNullException(nameof(dispatcher));
            }

            if (!(source is INotifyCollectionChanged sourceAsNotifyCollection))
            {
                throw new ArgumentException("sourceがINotifyCollectionChangedを実装していません");
            }

            var initCollection = new ObservableCollection <TViewModel>();

            foreach (var model in source)
            {
                initCollection.Add(converter(model));
            }

            var target = new DispatcherCollection <TViewModel>(initCollection, dispatcher);
            var result = new ReadOnlyDispatcherCollection <TViewModel>(target);

            var collectionChangedListener = new CollectionChangedEventListener(sourceAsNotifyCollection);

            result.EventListeners.Add(collectionChangedListener);

            collectionChangedListener.RegisterHandler((sender, e) =>
            {
                if (e == null)
                {
                    throw new ArgumentNullException(nameof(e));
                }
                switch (e.Action)
                {
                case NotifyCollectionChangedAction.Add:
                    var vm = converter((TModel)e.NewItems?[0]);
                    InvokeOnDispatcher(() => target.Insert(e.NewStartingIndex, vm), dispatcher);
                    break;

                case NotifyCollectionChangedAction.Move:
                    InvokeOnDispatcher(() => target.Move(e.OldStartingIndex, e.NewStartingIndex), dispatcher);
                    break;

                case NotifyCollectionChangedAction.Remove:
                    if (typeof(IDisposable).IsAssignableFrom(typeof(TViewModel)))
                    {
                        ((IDisposable)target[e.OldStartingIndex])?.Dispose();
                    }
                    InvokeOnDispatcher(() => target.RemoveAt(e.OldStartingIndex), dispatcher);
                    break;

                case NotifyCollectionChangedAction.Replace:
                    if (typeof(IDisposable).IsAssignableFrom(typeof(TViewModel)))
                    {
                        ((IDisposable)target[e.NewStartingIndex])?.Dispose();
                    }
                    var replaceVm = converter((TModel)e.NewItems?[0]);
                    InvokeOnDispatcher(() => target[e.NewStartingIndex] = replaceVm, dispatcher);
                    break;

                case NotifyCollectionChangedAction.Reset:
                    if (typeof(IDisposable).IsAssignableFrom(typeof(TViewModel)))
                    {
                        foreach (var item in target.OfType <IDisposable>())
                        {
                            item.Dispose();
                        }
                    }

                    InvokeOnDispatcher(target.Clear, dispatcher);
                    break;

                default:
                    throw new ArgumentException();
                }
            });

            return(result);
        }
Esempio n. 4
0
        public static ReadOnlyDispatcherCollection <TViewModel> CreateReadOnlyDispatcherCollection <TModel, TViewModel>(IList <TModel> source, Func <TModel, TViewModel> converter, Dispatcher dispatcher)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            var sourceAsNotifyCollection = source as INotifyCollectionChanged;

            if (sourceAsNotifyCollection == null)
            {
                throw new ArgumentException("sourceがINotifyCollectionChangedを実装していません");
            }

            var initCollection = new ObservableCollection <TViewModel>();
            var internalLock   = new object();

            lock (internalLock)
            {
                var target = new DispatcherCollection <TViewModel>(initCollection, dispatcher);
                var result = new ReadOnlyDispatcherCollection <TViewModel>(target);

                var collectionChangedListener = new CollectionChangedEventListener(sourceAsNotifyCollection);

                result.EventListeners.Add(collectionChangedListener);

                collectionChangedListener.RegisterHandler((sender, e) =>
                {
                    lock (internalLock)
                    {
                        switch (e.Action)
                        {
                        case NotifyCollectionChangedAction.Add:
                            target.Insert(e.NewStartingIndex, converter((TModel)e.NewItems[0]));
                            break;

                        case NotifyCollectionChangedAction.Move:
                            target.Move(e.OldStartingIndex, e.NewStartingIndex);
                            break;

                        case NotifyCollectionChangedAction.Remove:
                            if (typeof(IDisposable).IsAssignableFrom(typeof(TViewModel)))
                            {
                                ((IDisposable)target[e.OldStartingIndex]).Dispose();
                            }
                            target.RemoveAt(e.OldStartingIndex);
                            break;

                        case NotifyCollectionChangedAction.Replace:
                            if (typeof(IDisposable).IsAssignableFrom(typeof(TViewModel)))
                            {
                                ((IDisposable)target[e.NewStartingIndex]).Dispose();
                            }
                            target[e.NewStartingIndex] = converter((TModel)e.NewItems[0]);
                            break;

                        case NotifyCollectionChangedAction.Reset:
                            if (typeof(IDisposable).IsAssignableFrom(typeof(TViewModel)))
                            {
                                foreach (IDisposable item in target)
                                {
                                    item.Dispose();
                                }
                            }
                            target.Clear();
                            break;

                        default:
                            throw new ArgumentException();
                        }
                    }
                });

                foreach (var model in source)
                {
                    initCollection.Add(converter(model));
                }
                return(result);
            }
        }