Free cookie consent management tool by TermsFeed Policy Generator

source: branches/WebJobManager/HeuristicLab.Collections/3.3/ObservableCollection.cs @ 13782

Last change on this file since 13782 was 13597, checked in by abeham, 9 years ago

#2575: fixed multiple enumeration of collection in ObservableCollection and ObservableList

File size: 6.8 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
23using System;
24using System.Collections;
25using System.Collections.Generic;
26using System.ComponentModel;
27using System.Linq;
28
29namespace HeuristicLab.Collections {
30  [StorableClass]
31  [Serializable]
32  public class ObservableCollection<T> : IObservableCollection<T> {
33    [Storable]
34    protected List<T> list;
35
36    #region Properties
37    public int Capacity {
38      get { return list.Capacity; }
39      set {
40        if (list.Capacity != value) {
41          list.Capacity = value;
42          OnPropertyChanged("Capacity");
43        }
44      }
45    }
46    public int Count {
47      get { return list.Count; }
48    }
49    bool ICollection<T>.IsReadOnly {
50      get { return ((ICollection<T>)list).IsReadOnly; }
51    }
52    #endregion
53
54    #region Constructors
55    public ObservableCollection() {
56      list = new List<T>();
57    }
58    public ObservableCollection(int capacity) {
59      list = new List<T>(capacity);
60    }
61    public ObservableCollection(IEnumerable<T> collection) {
62      list = new List<T>(collection);
63    }
64    [StorableConstructor]
65    protected ObservableCollection(bool deserializing) { }
66    #endregion
67
68    #region Access
69    public bool Contains(T item) {
70      return list.Contains(item);
71    }
72
73    public bool Exists(Predicate<T> match) {
74      return list.Exists(match);
75    }
76
77    public T Find(Predicate<T> match) {
78      return list.Find(match);
79    }
80    public ICollection<T> FindAll(Predicate<T> match) {
81      return list.FindAll(match);
82    }
83    public T FindLast(Predicate<T> match) {
84      return list.FindLast(match);
85    }
86    #endregion
87
88    #region Manipulation
89    public void Add(T item) {
90      int capacity = list.Capacity;
91      list.Add(item);
92      if (list.Capacity != capacity)
93        OnPropertyChanged("Capacity");
94      OnPropertyChanged("Count");
95      OnItemsAdded(new T[] { item });
96    }
97    public void AddRange(IEnumerable<T> collection) {
98      int capacity = list.Capacity;
99      ICollection<T> items = collection as ICollection<T> ?? collection.ToList();
100      list.AddRange(items);
101      if (items.Count > 0) {
102        if (list.Capacity != capacity)
103          OnPropertyChanged("Capacity");
104        OnPropertyChanged("Count");
105        OnItemsAdded(items);
106      }
107    }
108
109    public bool Remove(T item) {
110      if (list.Remove(item)) {
111        OnPropertyChanged("Count");
112        OnItemsRemoved(new T[] { item });
113        return true;
114      }
115      return false;
116    }
117    public void RemoveRange(IEnumerable<T> collection) {
118      if (collection == null) throw new ArgumentNullException();
119      List<T> items = new List<T>();
120      foreach (T item in collection) {
121        if (list.Remove(item))
122          items.Add(item);
123      }
124      if (items.Count > 0) {
125        OnPropertyChanged("Count");
126        OnItemsRemoved(items);
127      }
128    }
129    public int RemoveAll(Predicate<T> match) {
130      List<T> items = list.FindAll(match);
131      int result = 0;
132      if (items.Count > 0) {
133        result = list.RemoveAll(match);
134        OnPropertyChanged("Count");
135        OnItemsRemoved(items);
136      }
137      return result;
138    }
139
140    public void Clear() {
141      if (list.Count > 0) {
142        T[] items = list.ToArray();
143        list.Clear();
144        OnPropertyChanged("Count");
145        OnCollectionReset(new T[0], items);
146      }
147    }
148    #endregion
149
150    #region Conversion
151    public ReadOnlyObservableCollection<T> AsReadOnly() {
152      return new ReadOnlyObservableCollection<T>(this);
153    }
154    public T[] ToArray() {
155      return list.ToArray();
156    }
157    public void CopyTo(T[] array, int arrayIndex) {
158      list.CopyTo(array, arrayIndex);
159    }
160    public ICollection<TOutput> ConvertAll<TOutput>(Converter<T, TOutput> converter) {
161      return list.ConvertAll<TOutput>(converter);
162    }
163    #endregion
164
165    #region Processing
166    public void ForEach(Action<T> action) {
167      list.ForEach(action);
168    }
169    public bool TrueForAll(Predicate<T> match) {
170      return list.TrueForAll(match);
171    }
172    #endregion
173
174    #region Enumeration
175    public IEnumerator<T> GetEnumerator() {
176      return ((IEnumerable<T>)list).GetEnumerator();
177    }
178    IEnumerator IEnumerable.GetEnumerator() {
179      return ((IEnumerable)list).GetEnumerator();
180    }
181    #endregion
182
183    #region Helpers
184    public void TrimExcess() {
185      int capacity = list.Capacity;
186      list.TrimExcess();
187      if (list.Capacity != capacity)
188        OnPropertyChanged("Capacity");
189    }
190    #endregion
191
192    #region Events
193    [field: NonSerialized]
194    public event CollectionItemsChangedEventHandler<T> ItemsAdded;
195    protected virtual void OnItemsAdded(IEnumerable<T> items) {
196      CollectionItemsChangedEventHandler<T> handler = ItemsAdded;
197      if (handler != null) handler(this, new CollectionItemsChangedEventArgs<T>(items));
198    }
199
200    [field: NonSerialized]
201    public event CollectionItemsChangedEventHandler<T> ItemsRemoved;
202    protected virtual void OnItemsRemoved(IEnumerable<T> items) {
203      CollectionItemsChangedEventHandler<T> handler = ItemsRemoved;
204      if (handler != null) handler(this, new CollectionItemsChangedEventArgs<T>(items));
205    }
206
207    [field: NonSerialized]
208    public event CollectionItemsChangedEventHandler<T> CollectionReset;
209    protected virtual void OnCollectionReset(IEnumerable<T> items, IEnumerable<T> oldItems) {
210      CollectionItemsChangedEventHandler<T> handler = CollectionReset;
211      if (handler != null) handler(this, new CollectionItemsChangedEventArgs<T>(items, oldItems));
212    }
213
214    [field: NonSerialized]
215    public event PropertyChangedEventHandler PropertyChanged;
216    protected virtual void OnPropertyChanged(string propertyName) {
217      PropertyChangedEventHandler handler = PropertyChanged;
218      if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
219    }
220    #endregion
221  }
222}
Note: See TracBrowser for help on using the repository browser.