1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2007 Novell, Inc.
26 using System.Collections;
27 using System.Collections.Generic;
28 using System.Collections.ObjectModel;
29 using System.Reflection;
31 namespace System.ComponentModel {
32 [SerializableAttribute]
33 public class BindingList<T> : Collection<T>,
34 IBindingList, IList, ICollection,
35 IEnumerable, ICancelAddNew, IRaiseItemChangedEvents
37 bool allow_edit = true;
38 bool allow_remove = true;
42 bool raise_list_changed_events = true;
44 bool type_has_default_ctor;
45 bool type_raises_item_changed_events;
48 int pending_add_index;
52 ConstructorInfo ci = typeof (T).GetConstructor (Type.EmptyTypes);
53 type_has_default_ctor = (ci != null);
54 type_raises_item_changed_events = typeof (INotifyPropertyChanged).IsAssignableFrom (typeof (T));
57 public BindingList (IList<T> list) : base(list)
62 public BindingList () : base ()
67 public bool AllowEdit {
68 get { return allow_edit; }
70 if (allow_edit != value) {
73 if (raise_list_changed_events)
74 OnListChanged (new ListChangedEventArgs (ListChangedType.Reset, -1 /* XXX */));
79 public bool AllowNew {
81 /* if the user explicitly it, return that value */
85 /* if the list type has a default constructor we allow new */
86 if (type_has_default_ctor)
89 /* if the user adds a delegate, we return true even if
90 the type doesn't have a default ctor */
91 if (AddingNew != null)
97 // this funky check (using AllowNew
98 // instead of allow_new allows us to
99 // keep the logic for the 3 cases in
100 // one place (the getter) instead of
101 // spreading them around the file (in
102 // the ctor, in the AddingNew add
104 if (AllowNew != value) {
105 allow_new_set = true;
109 if (raise_list_changed_events)
110 OnListChanged (new ListChangedEventArgs (ListChangedType.Reset, -1 /* XXX */));
115 public bool AllowRemove {
116 get { return allow_remove; }
118 if (allow_remove != value) {
119 allow_remove = value;
121 if (raise_list_changed_events)
122 OnListChanged (new ListChangedEventArgs (ListChangedType.Reset, -1 /* XXX */));
127 protected virtual bool IsSortedCore {
128 get { return false; }
131 public bool RaiseListChangedEvents {
132 get { return raise_list_changed_events; }
133 set { raise_list_changed_events = value; }
136 protected virtual ListSortDirection SortDirectionCore {
137 get { return ListSortDirection.Ascending; }
140 protected virtual PropertyDescriptor SortPropertyCore {
144 protected virtual bool SupportsChangeNotificationCore {
148 protected virtual bool SupportsSearchingCore {
149 get { return false; }
152 protected virtual bool SupportsSortingCore {
153 get { return false; }
156 public event AddingNewEventHandler AddingNew;
157 public event ListChangedEventHandler ListChanged;
161 return (T)AddNewCore ();
164 protected virtual object AddNewCore ()
167 throw new InvalidOperationException ();
169 AddingNewEventArgs args = new AddingNewEventArgs ();
173 T new_obj = (T)args.NewObject;
174 if (new_obj == null) {
175 if (!type_has_default_ctor)
176 throw new InvalidOperationException ();
178 new_obj = (T)Activator.CreateInstance (typeof (T));
182 pending_add_index = IndexOf (new_obj);
185 if (raise_list_changed_events)
186 OnListChanged (new ListChangedEventArgs (ListChangedType.ItemAdded, pending_add_index));
191 protected virtual void ApplySortCore (PropertyDescriptor prop, ListSortDirection direction)
193 throw new NotSupportedException ();
196 public virtual void CancelNew (int itemIndex)
201 if (itemIndex != pending_add_index)
206 base.RemoveItem (itemIndex);
208 if (raise_list_changed_events)
209 OnListChanged (new ListChangedEventArgs (ListChangedType.ItemDeleted, itemIndex));
212 protected override void ClearItems ()
214 EndNew (pending_add_index);
218 OnListChanged (new ListChangedEventArgs (ListChangedType.Reset, -1));
221 public virtual void EndNew (int itemIndex)
226 if (itemIndex != pending_add_index)
232 protected virtual int FindCore (PropertyDescriptor prop, object key)
234 throw new NotSupportedException ();
237 protected override void InsertItem (int index, T item)
239 EndNew (pending_add_index);
241 base.InsertItem (index, item);
243 if (raise_list_changed_events)
244 OnListChanged (new ListChangedEventArgs (ListChangedType.ItemAdded, index));
247 protected virtual void OnAddingNew (AddingNewEventArgs e)
249 if (AddingNew != null)
253 protected virtual void OnListChanged (ListChangedEventArgs e)
255 if (ListChanged != null)
256 ListChanged (this, e);
259 protected override void RemoveItem (int index)
262 throw new NotSupportedException ();
264 EndNew (pending_add_index);
266 base.RemoveItem (index);
268 if (raise_list_changed_events)
269 OnListChanged (new ListChangedEventArgs (ListChangedType.ItemDeleted, index));
272 protected virtual void RemoveSortCore ()
274 throw new NotSupportedException ();
277 public void ResetBindings ()
279 OnListChanged (new ListChangedEventArgs (ListChangedType.Reset, -1));
282 public void ResetItem (int position)
284 OnListChanged (new ListChangedEventArgs (ListChangedType.ItemChanged, position));
287 protected override void SetItem (int index, T item)
289 base.SetItem (index, item);
291 OnListChanged (new ListChangedEventArgs (ListChangedType.ItemChanged, index));
294 void IBindingList.AddIndex (PropertyDescriptor index)
296 /* no implementation by default */
299 object IBindingList.AddNew ()
304 void IBindingList.ApplySort (PropertyDescriptor property, ListSortDirection direction)
306 ApplySortCore (property, direction);
309 int IBindingList.Find (PropertyDescriptor property, object key)
311 return FindCore (property, key);
314 void IBindingList.RemoveIndex (PropertyDescriptor property)
316 /* no implementation by default */
319 void IBindingList.RemoveSort ()
324 bool IBindingList.IsSorted {
325 get { return IsSortedCore; }
328 ListSortDirection IBindingList.SortDirection {
329 get { return SortDirectionCore; }
332 PropertyDescriptor IBindingList.SortProperty {
333 get { return SortPropertyCore; }
336 bool IBindingList.AllowEdit {
337 get { return AllowEdit; }
340 bool IBindingList.AllowNew {
341 get { return AllowNew; }
344 bool IBindingList.AllowRemove {
345 get { return AllowRemove; }
348 bool IBindingList.SupportsChangeNotification {
349 get { return SupportsChangeNotificationCore; }
352 bool IBindingList.SupportsSearching {
353 get { return SupportsSearchingCore; }
356 bool IBindingList.SupportsSorting {
357 get { return SupportsSortingCore; }
360 bool IRaiseItemChangedEvents.RaisesItemChangedEvents {
361 get { return type_raises_item_changed_events; }