Mercurial > pub > bltoolkit
comparison Source/ComponentModel/BindingListImpl.cs @ 0:f990fcb411a9
Копия текущей версии из github
author | cin |
---|---|
date | Thu, 27 Mar 2014 21:46:09 +0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:f990fcb411a9 |
---|---|
1 using System; | |
2 | |
3 using System.Collections; | |
4 using System.Collections.Specialized; | |
5 using System.ComponentModel; | |
6 using System.Diagnostics; | |
7 | |
8 using BLToolkit.EditableObjects; | |
9 using BLToolkit.Reflection; | |
10 | |
11 namespace BLToolkit.ComponentModel | |
12 { | |
13 public class BindingListImpl: IBindingListView, ICancelAddNew, INotifyCollectionChanged | |
14 { | |
15 #region Init | |
16 | |
17 public BindingListImpl(IList list, Type itemType) | |
18 { | |
19 if (list == null) throw new ArgumentNullException("list"); | |
20 if (itemType == null) throw new ArgumentNullException("itemType"); | |
21 | |
22 _list = list; | |
23 _itemType = itemType; | |
24 | |
25 AddInternal(_list); | |
26 } | |
27 | |
28 #endregion | |
29 | |
30 #region Protected Members | |
31 | |
32 private readonly IList _list; | |
33 private readonly Type _itemType; | |
34 | |
35 private void ApplySort(IComparer comparer) | |
36 { | |
37 if (_list is ISortable) | |
38 ((ISortable)_list).Sort(0, _list.Count, comparer); | |
39 else if (_list is ArrayList) | |
40 ((ArrayList)_list).Sort(0, _list.Count, comparer); | |
41 else if (_list is Array) | |
42 Array.Sort((Array)_list, comparer); | |
43 else | |
44 { | |
45 object[] items = new object[_list.Count]; | |
46 | |
47 _list.CopyTo(items, 0); | |
48 Array.Sort(items, comparer); | |
49 | |
50 for (int i = 0; i < _list.Count; i++) | |
51 _list[i] = items[i]; | |
52 } | |
53 | |
54 _isSorted = true; | |
55 } | |
56 | |
57 #endregion | |
58 | |
59 #region IBindingList Members | |
60 | |
61 #region Command | |
62 | |
63 private int _newItemIndex = -1; | |
64 private INotifyObjectEdit _newObject; | |
65 | |
66 public object AddNew() | |
67 { | |
68 if (AllowNew == false) | |
69 throw new NotSupportedException(); | |
70 | |
71 EndNew(); | |
72 | |
73 object o = TypeAccessor.CreateInstanceEx(_itemType); | |
74 _newObject = o as INotifyObjectEdit; | |
75 | |
76 if (_newObject != null) | |
77 _newObject.ObjectEdit += NewObject_ObjectEdit; | |
78 | |
79 _newItemIndex = _list.Add(o); | |
80 OnAddItem(o, _newItemIndex); | |
81 | |
82 Debug.WriteLine(string.Format("AddNew - ({0})", o.GetType().Name)); | |
83 | |
84 return o; | |
85 } | |
86 | |
87 void NewObject_ObjectEdit(object sender, ObjectEditEventArgs args) | |
88 { | |
89 if (sender == _newObject) | |
90 { | |
91 switch (args.EditType) | |
92 { | |
93 case ObjectEditType.End: EndNew(); break; | |
94 case ObjectEditType.Cancel: CancelNew(_newItemIndex); break; | |
95 default: return; | |
96 } | |
97 } | |
98 } | |
99 | |
100 public bool AllowNew | |
101 { | |
102 get { return !_list.IsFixedSize; } | |
103 } | |
104 | |
105 public bool AllowEdit | |
106 { | |
107 get { return !_list.IsReadOnly; } | |
108 } | |
109 | |
110 public bool AllowRemove | |
111 { | |
112 get { return !_list.IsFixedSize; } | |
113 } | |
114 | |
115 #endregion | |
116 | |
117 #region Change Notification | |
118 | |
119 private bool _notifyChanges = true; | |
120 public bool NotifyChanges | |
121 { | |
122 get { return _notifyChanges; } | |
123 set { _notifyChanges = value; } | |
124 } | |
125 | |
126 public bool SupportsChangeNotification | |
127 { | |
128 get { return true; } | |
129 } | |
130 | |
131 public event ListChangedEventHandler ListChanged; | |
132 | |
133 private void FireListChangedEvent(object sender, ListChangedEventArgs e) | |
134 { | |
135 if (_notifyChanges && ListChanged != null) | |
136 ListChanged(sender, e); | |
137 } | |
138 | |
139 protected virtual void OnListChanged(EditableListChangedEventArgs e) | |
140 { | |
141 FireListChangedEvent(this, e); | |
142 } | |
143 | |
144 protected void OnListChanged(ListChangedType listChangedType, int index) | |
145 { | |
146 OnListChanged(new EditableListChangedEventArgs(listChangedType, index)); | |
147 } | |
148 | |
149 private void ItemPropertyChanged(object sender, PropertyChangedEventArgs e) | |
150 { | |
151 if (_notifyChanges && sender != null) | |
152 { | |
153 int indexOfSender = _list.IndexOf(sender); | |
154 | |
155 if (indexOfSender >= 0) | |
156 { | |
157 MemberAccessor ma = TypeAccessor.GetAccessor(sender.GetType())[e.PropertyName]; | |
158 | |
159 if (ma != null) | |
160 OnListChanged(new EditableListChangedEventArgs(indexOfSender, ma.PropertyDescriptor)); | |
161 else | |
162 OnListChanged(new EditableListChangedEventArgs(ListChangedType.ItemChanged, indexOfSender)); | |
163 | |
164 // Do not fire an event for OnCollectionChanged here. | |
165 | |
166 if (_isSorted && _list.Count > 1) | |
167 { | |
168 int newIndex = GetItemSortedPosition(indexOfSender, sender); | |
169 | |
170 if (newIndex != indexOfSender) | |
171 { | |
172 _list.RemoveAt(indexOfSender); | |
173 _list.Insert(newIndex, sender); | |
174 | |
175 OnMoveItem(sender, indexOfSender, newIndex); | |
176 } | |
177 } | |
178 } | |
179 } | |
180 } | |
181 | |
182 #endregion | |
183 | |
184 #region Sorting | |
185 | |
186 public bool SupportsSorting | |
187 { | |
188 get { return true; } | |
189 } | |
190 | |
191 [NonSerialized] | |
192 private bool _isSorted; | |
193 public bool IsSorted | |
194 { | |
195 get { return _isSorted; } | |
196 } | |
197 | |
198 [NonSerialized] | |
199 private PropertyDescriptor _sortProperty; | |
200 public PropertyDescriptor SortProperty | |
201 { | |
202 get { return _sortProperty; } | |
203 } | |
204 | |
205 [NonSerialized] | |
206 private ListSortDirection _sortDirection; | |
207 public ListSortDirection SortDirection | |
208 { | |
209 get { return _sortDirection; } | |
210 } | |
211 | |
212 public void ApplySort(PropertyDescriptor property, ListSortDirection direction) | |
213 { | |
214 Debug.WriteLine(string.Format("Begin ApplySort(\"{0}\", {1})", property.Name, direction)); | |
215 | |
216 _sortProperty = property; | |
217 _sortDirection = direction; | |
218 _sortDescriptions = null; | |
219 | |
220 ApplySort(GetSortComparer(_sortProperty, _sortDirection)); | |
221 | |
222 if (_list.Count > 0) | |
223 OnReset(); | |
224 | |
225 Debug.WriteLine(string.Format("End ApplySort(\"{0}\", {1})", property.Name, direction)); | |
226 } | |
227 | |
228 public void RemoveSort() | |
229 { | |
230 _isSorted = false; | |
231 _sortProperty = null; | |
232 _sortDescriptions = null; | |
233 | |
234 OnReset(); | |
235 } | |
236 | |
237 #endregion | |
238 | |
239 #region Searching | |
240 | |
241 public bool SupportsSearching | |
242 { | |
243 get { return true; } | |
244 } | |
245 | |
246 public int Find(PropertyDescriptor property, object key) | |
247 { | |
248 if (property == null) throw new ArgumentException("property"); | |
249 | |
250 if (key != null) | |
251 for (int i = 0; i < _list.Count; i++) | |
252 if (key.Equals(property.GetValue(_list[i]))) | |
253 return i; | |
254 | |
255 return -1; | |
256 } | |
257 | |
258 #endregion | |
259 | |
260 #region Indexes | |
261 | |
262 public void AddIndex(PropertyDescriptor property) | |
263 { | |
264 } | |
265 | |
266 public void RemoveIndex(PropertyDescriptor property) | |
267 { | |
268 } | |
269 | |
270 #endregion | |
271 | |
272 #endregion | |
273 | |
274 #region ICancelAddNew Members | |
275 | |
276 public void CancelNew(int itemIndex) | |
277 { | |
278 if (itemIndex >= 0 && itemIndex == _newItemIndex) | |
279 { | |
280 _list.RemoveAt(itemIndex); | |
281 OnRemoveItem(_newObject, itemIndex); | |
282 EndNew(); | |
283 } | |
284 } | |
285 | |
286 public void EndNew(int itemIndex) | |
287 { | |
288 if (itemIndex == _newItemIndex) | |
289 EndNew(); | |
290 } | |
291 | |
292 public void EndNew() | |
293 { | |
294 _newItemIndex = -1; | |
295 | |
296 if (_newObject != null) | |
297 _newObject.ObjectEdit -= NewObject_ObjectEdit; | |
298 | |
299 _newObject = null; | |
300 } | |
301 | |
302 #endregion | |
303 | |
304 #region IList Members | |
305 | |
306 public int Add(object value) | |
307 { | |
308 int index; | |
309 | |
310 if (!_isSorted) | |
311 index = _list.Add(value); | |
312 else | |
313 { | |
314 index = GetSortedInsertIndex(value); | |
315 _list.Insert(index, value); | |
316 } | |
317 | |
318 AddInternal(value); | |
319 OnAddItem(value, index); | |
320 | |
321 return index; | |
322 } | |
323 | |
324 public void Clear() | |
325 { | |
326 if (_list.Count > 0) | |
327 { | |
328 RemoveInternal(_list); | |
329 | |
330 _list.Clear(); | |
331 OnReset(); | |
332 } | |
333 } | |
334 | |
335 public bool Contains(object value) | |
336 { | |
337 return _list.Contains(value); | |
338 } | |
339 | |
340 public int IndexOf(object value) | |
341 { | |
342 return _list.IndexOf(value); | |
343 } | |
344 | |
345 public void Insert(int index, object value) | |
346 { | |
347 if (_isSorted) | |
348 index = GetSortedInsertIndex(value); | |
349 | |
350 _list.Insert(index, value); | |
351 AddInternal(value); | |
352 | |
353 OnAddItem(value, index); | |
354 } | |
355 | |
356 public bool IsFixedSize | |
357 { | |
358 get { return _list.IsFixedSize; } | |
359 } | |
360 | |
361 public bool IsReadOnly | |
362 { | |
363 get { return _list.IsReadOnly; } | |
364 } | |
365 | |
366 public void Remove(object value) | |
367 { | |
368 int index = IndexOf(value); | |
369 | |
370 if (index >= 0) | |
371 RemoveInternal(value); | |
372 | |
373 _list.Remove(value); | |
374 | |
375 if (index >= 0) | |
376 OnRemoveItem(value, index); | |
377 } | |
378 | |
379 public void RemoveAt(int index) | |
380 { | |
381 object value = this[index]; | |
382 | |
383 RemoveInternal(value); | |
384 | |
385 _list.RemoveAt(index); | |
386 | |
387 OnRemoveItem(value, index); | |
388 } | |
389 | |
390 public object this[int index] | |
391 { | |
392 get { return _list[index]; } | |
393 set | |
394 { | |
395 object o = _list[index]; | |
396 | |
397 if (o != value) | |
398 { | |
399 RemoveInternal(o); | |
400 | |
401 _list[index] = value; | |
402 | |
403 AddInternal(value); | |
404 | |
405 OnChangeItem(o, value, index); | |
406 | |
407 if (_isSorted) | |
408 { | |
409 int newIndex = GetItemSortedPosition(index, value); | |
410 | |
411 if (newIndex != index) | |
412 { | |
413 _list.RemoveAt(index); | |
414 _list.Insert(newIndex, value); | |
415 } | |
416 | |
417 OnMoveItem(value, index, newIndex); | |
418 } | |
419 } | |
420 } | |
421 } | |
422 | |
423 #endregion | |
424 | |
425 #region ICollection Members | |
426 | |
427 public void CopyTo(Array array, int index) | |
428 { | |
429 _list.CopyTo(array, index); | |
430 } | |
431 | |
432 public int Count | |
433 { | |
434 get { return _list.Count; } | |
435 } | |
436 | |
437 public bool IsSynchronized | |
438 { | |
439 get { return _list.IsSynchronized; } | |
440 } | |
441 | |
442 public object SyncRoot | |
443 { | |
444 get { return _list.SyncRoot; } | |
445 } | |
446 | |
447 #endregion | |
448 | |
449 #region IEnumerable Members | |
450 | |
451 public IEnumerator GetEnumerator() | |
452 { | |
453 return _list.GetEnumerator(); | |
454 } | |
455 | |
456 #endregion | |
457 | |
458 #region SortPropertyComparer | |
459 | |
460 class SortPropertyComparer : IComparer | |
461 { | |
462 readonly PropertyDescriptor _property; | |
463 readonly ListSortDirection _direction; | |
464 | |
465 public SortPropertyComparer(PropertyDescriptor property, ListSortDirection direction) | |
466 { | |
467 _property = property; | |
468 _direction = direction; | |
469 } | |
470 | |
471 public int Compare(object x, object y) | |
472 { | |
473 object a = _property.GetValue(x); | |
474 object b = _property.GetValue(y); | |
475 | |
476 int n = Comparer.Default.Compare(a, b); | |
477 | |
478 return _direction == ListSortDirection.Ascending? n: -n; | |
479 } | |
480 } | |
481 | |
482 #endregion | |
483 | |
484 #region IComparer Accessor | |
485 | |
486 public IComparer GetSortComparer() | |
487 { | |
488 if (_isSorted) | |
489 { | |
490 if (_sortDescriptions != null) | |
491 return GetSortComparer(_sortDescriptions); | |
492 | |
493 return GetSortComparer(_sortProperty, _sortDirection); | |
494 } | |
495 | |
496 return null; | |
497 } | |
498 | |
499 private IComparer GetSortComparer(PropertyDescriptor sortProperty, ListSortDirection sortDirection) | |
500 { | |
501 if (_sortSubstitutions.ContainsKey(sortProperty.Name)) | |
502 sortProperty = ((SortSubstitutionPair)_sortSubstitutions[sortProperty.Name]).Substitute; | |
503 | |
504 return new SortPropertyComparer(sortProperty, sortDirection); | |
505 } | |
506 | |
507 private IComparer GetSortComparer(ListSortDescriptionCollection sortDescriptions) | |
508 { | |
509 bool needSubstitution = false; | |
510 | |
511 if (_sortSubstitutions.Count > 0) | |
512 { | |
513 foreach (ListSortDescription sortDescription in sortDescriptions) | |
514 { | |
515 if (_sortSubstitutions.ContainsKey(sortDescription.PropertyDescriptor.Name)) | |
516 { | |
517 needSubstitution = true; | |
518 break; | |
519 } | |
520 } | |
521 | |
522 if (needSubstitution) | |
523 { | |
524 ListSortDescription[] sorts = new ListSortDescription[sortDescriptions.Count]; | |
525 sortDescriptions.CopyTo(sorts, 0); | |
526 | |
527 for (int i = 0; i < sorts.Length; i++) | |
528 if (_sortSubstitutions.ContainsKey(sorts[i].PropertyDescriptor.Name)) | |
529 sorts[i] = new ListSortDescription(((SortSubstitutionPair)_sortSubstitutions[sorts[i].PropertyDescriptor.Name]).Substitute, | |
530 sorts[i].SortDirection); | |
531 | |
532 sortDescriptions = new ListSortDescriptionCollection(sorts); | |
533 } | |
534 } | |
535 | |
536 return new SortListPropertyComparer(sortDescriptions); | |
537 } | |
538 | |
539 #endregion | |
540 | |
541 #region IBindingListView Members | |
542 | |
543 public bool SupportsAdvancedSorting | |
544 { | |
545 get { return true; } | |
546 } | |
547 | |
548 public void ApplySort(ListSortDescriptionCollection sorts) | |
549 { | |
550 _sortDescriptions = sorts; | |
551 | |
552 _isSorted = true; | |
553 _sortProperty = null; | |
554 | |
555 ApplySort(GetSortComparer(sorts)); | |
556 | |
557 if (_list.Count > 0) | |
558 OnReset(); | |
559 } | |
560 | |
561 [NonSerialized] | |
562 private ListSortDescriptionCollection _sortDescriptions; | |
563 public ListSortDescriptionCollection SortDescriptions | |
564 { | |
565 get { return _sortDescriptions; } | |
566 } | |
567 | |
568 public bool SupportsFiltering | |
569 { | |
570 get { return false; } | |
571 } | |
572 | |
573 public string Filter | |
574 { | |
575 get { throw new NotImplementedException("The method 'BindingListImpl.get_Filter' is not implemented."); } | |
576 set { throw new NotImplementedException("The method 'BindingListImpl.set_Filter' is not implemented."); } | |
577 } | |
578 | |
579 public void RemoveFilter() | |
580 { | |
581 throw new NotImplementedException("The method 'BindingListImpl.RemoveFilter()' is not implemented."); | |
582 } | |
583 | |
584 #endregion | |
585 | |
586 #region SortListPropertyComparer | |
587 | |
588 class SortListPropertyComparer : IComparer | |
589 { | |
590 readonly ListSortDescriptionCollection _sorts; | |
591 | |
592 public SortListPropertyComparer(ListSortDescriptionCollection sorts) | |
593 { | |
594 _sorts = sorts; | |
595 } | |
596 | |
597 public int Compare(object x, object y) | |
598 { | |
599 for (int i = 0; i < _sorts.Count; i++) | |
600 { | |
601 PropertyDescriptor property = _sorts[i].PropertyDescriptor; | |
602 | |
603 object a = property.GetValue(x); | |
604 object b = property.GetValue(y); | |
605 | |
606 int n = Comparer.Default.Compare(a, b); | |
607 | |
608 if (n != 0) | |
609 return _sorts[i].SortDirection == ListSortDirection.Ascending? n: -n; | |
610 } | |
611 | |
612 return 0; | |
613 } | |
614 } | |
615 | |
616 #endregion | |
617 | |
618 #region Sorting enhancement | |
619 | |
620 private readonly Hashtable _sortSubstitutions = new Hashtable(); | |
621 | |
622 private class SortSubstitutionPair | |
623 { | |
624 public SortSubstitutionPair(PropertyDescriptor original, PropertyDescriptor substitute) | |
625 { | |
626 Original = original; | |
627 Substitute = substitute; | |
628 } | |
629 | |
630 public readonly PropertyDescriptor Original; | |
631 public readonly PropertyDescriptor Substitute; | |
632 } | |
633 | |
634 public void CreateSortSubstitution(string originalProperty, string substituteProperty) | |
635 { | |
636 TypeAccessor typeAccessor = TypeAccessor.GetAccessor(_itemType); | |
637 | |
638 PropertyDescriptor originalDescriptor = typeAccessor.PropertyDescriptors[originalProperty]; | |
639 PropertyDescriptor substituteDescriptor = typeAccessor.PropertyDescriptors[substituteProperty]; | |
640 | |
641 if (originalDescriptor == null) throw new InvalidOperationException("Can not retrieve PropertyDescriptor for original property: " + originalProperty); | |
642 if (substituteDescriptor == null) throw new InvalidOperationException("Can not retrieve PropertyDescriptor for substitute property: " + substituteProperty); | |
643 | |
644 _sortSubstitutions[originalProperty] = new SortSubstitutionPair(originalDescriptor, substituteDescriptor); | |
645 } | |
646 | |
647 public void RemoveSortSubstitution(string originalProperty) | |
648 { | |
649 _sortSubstitutions.Remove(originalProperty); | |
650 } | |
651 | |
652 #endregion | |
653 | |
654 #region Sort enforcement | |
655 | |
656 public int GetItemSortedPosition(int index, object sender) | |
657 { | |
658 IComparer comparer = GetSortComparer(); | |
659 | |
660 if (comparer == null) | |
661 return index; | |
662 | |
663 if ((index > 0 && comparer.Compare(_list[index - 1], sender) > 0) || | |
664 (index < _list.Count - 1 && comparer.Compare(_list[index + 1], sender) < 0)) | |
665 { | |
666 for (int i = 0; i < _list.Count; i++) | |
667 { | |
668 if (i != index && comparer.Compare(_list[i], sender) > 0) | |
669 { | |
670 if (i > index) | |
671 return i - 1; | |
672 | |
673 return i; | |
674 } | |
675 } | |
676 | |
677 return _list.Count - 1; | |
678 } | |
679 | |
680 return index; | |
681 } | |
682 | |
683 public int GetSortedInsertIndex(object value) | |
684 { | |
685 IComparer comparer = GetSortComparer(); | |
686 | |
687 if (comparer == null) | |
688 return -1; | |
689 | |
690 for (int i = 0; i < _list.Count; i++) | |
691 if (comparer.Compare(_list[i], value) > 0) | |
692 return i; | |
693 | |
694 return _list.Count; | |
695 } | |
696 | |
697 #endregion | |
698 | |
699 #region Misc/Range Operations | |
700 | |
701 public void Move(int newIndex, int oldIndex) | |
702 { | |
703 if (oldIndex != newIndex) | |
704 { | |
705 EndNew(); | |
706 | |
707 object o = _list[oldIndex]; | |
708 | |
709 _list.RemoveAt(oldIndex); | |
710 if (!_isSorted) | |
711 _list.Insert(newIndex, o); | |
712 else | |
713 _list.Insert(newIndex = GetSortedInsertIndex(o), o); | |
714 | |
715 OnMoveItem(o, oldIndex, newIndex); | |
716 } | |
717 } | |
718 | |
719 public void AddRange(ICollection c) | |
720 { | |
721 foreach (object o in c) | |
722 { | |
723 if (!_isSorted) | |
724 _list.Add(o); | |
725 else | |
726 _list.Insert(GetSortedInsertIndex(o), o); | |
727 } | |
728 | |
729 AddInternal(c); | |
730 | |
731 OnReset(); | |
732 } | |
733 | |
734 public void InsertRange(int index, ICollection c) | |
735 { | |
736 if (c.Count == 0) | |
737 return; | |
738 | |
739 foreach (object o in c) | |
740 { | |
741 if (!_isSorted) | |
742 _list.Insert(index++, o); | |
743 else | |
744 _list.Insert(GetSortedInsertIndex(o), o); | |
745 } | |
746 | |
747 AddInternal(c); | |
748 | |
749 OnReset(); | |
750 } | |
751 | |
752 public void RemoveRange(int index, int count) | |
753 { | |
754 object[] toRemove = new object[count]; | |
755 | |
756 for (int i = index; i < _list.Count && i < index + count; i++) | |
757 toRemove[i - index] = _list[i]; | |
758 | |
759 RemoveInternal(toRemove); | |
760 | |
761 foreach (object o in toRemove) | |
762 _list.Remove(o); | |
763 | |
764 OnReset(); | |
765 } | |
766 | |
767 public void SetRange(int index, ICollection c) | |
768 { | |
769 int cCount = c.Count; | |
770 | |
771 if (index < 0 || index >= _list.Count - cCount) | |
772 throw new ArgumentOutOfRangeException("index"); | |
773 | |
774 bool oldNotifyChanges = _notifyChanges; | |
775 _notifyChanges = false; | |
776 | |
777 int i = index; | |
778 foreach (object newObject in c) | |
779 { | |
780 RemoveInternal(_list[i + index]); | |
781 _list[i + index] = newObject; | |
782 } | |
783 | |
784 AddInternal(c); | |
785 | |
786 if (_isSorted) | |
787 ApplySort(GetSortComparer()); | |
788 | |
789 _notifyChanges = oldNotifyChanges; | |
790 OnReset(); | |
791 } | |
792 | |
793 #endregion | |
794 | |
795 #region Add/Remove Internal | |
796 | |
797 private void AddInternal(object value) | |
798 { | |
799 EndNew(); | |
800 | |
801 if (value is INotifyPropertyChanged) | |
802 ((INotifyPropertyChanged)value).PropertyChanged += | |
803 ItemPropertyChanged; | |
804 } | |
805 | |
806 private void RemoveInternal(object value) | |
807 { | |
808 EndNew(); | |
809 | |
810 if (value is INotifyPropertyChanged) | |
811 ((INotifyPropertyChanged)value).PropertyChanged -= | |
812 ItemPropertyChanged; | |
813 } | |
814 | |
815 private void AddInternal(IEnumerable e) | |
816 { | |
817 foreach (object o in e) | |
818 AddInternal(o); | |
819 } | |
820 | |
821 private void RemoveInternal(IEnumerable e) | |
822 { | |
823 foreach (object o in e) | |
824 RemoveInternal(o); | |
825 } | |
826 | |
827 private void OnAddItem(object item, int index) | |
828 { | |
829 OnListChanged(new EditableListChangedEventArgs(ListChangedType.ItemAdded, index)); | |
830 OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index)); | |
831 } | |
832 | |
833 private void OnRemoveItem(object item, int index) | |
834 { | |
835 OnListChanged(new EditableListChangedEventArgs(ListChangedType.ItemDeleted, index)); | |
836 OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, index)); | |
837 } | |
838 | |
839 private void OnMoveItem(object item, int oldIndex, int newIndex) | |
840 { | |
841 OnListChanged(new EditableListChangedEventArgs(newIndex, oldIndex)); | |
842 OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Move, item, newIndex, oldIndex)); | |
843 } | |
844 | |
845 private void OnChangeItem(object oldValue, object newValue, int index) | |
846 { | |
847 OnListChanged(new EditableListChangedEventArgs(ListChangedType.ItemChanged, index)); | |
848 OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, oldValue, newValue, index)); | |
849 } | |
850 | |
851 private void OnReset() | |
852 { | |
853 OnListChanged(new EditableListChangedEventArgs(ListChangedType.Reset)); | |
854 OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); | |
855 } | |
856 | |
857 #endregion | |
858 | |
859 #region INotifyCollectionChanged Members | |
860 | |
861 public event NotifyCollectionChangedEventHandler CollectionChanged; | |
862 | |
863 private void FireCollectionChangedEvent(object sender, NotifyCollectionChangedEventArgs ea) | |
864 { | |
865 if (_notifyChanges && CollectionChanged != null) | |
866 CollectionChanged(sender, ea); | |
867 } | |
868 | |
869 protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs ea) | |
870 { | |
871 FireCollectionChangedEvent(this, ea); | |
872 } | |
873 | |
874 #endregion | |
875 } | |
876 } |