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: 8 // 9 // The above copyright notice and this permission notice shall be 10 // included in all copies or substantial portions of the Software. 11 // 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. 19 // 20 // Copyright (c) 2007 Novell, Inc. 21 // 22 23 using System.ComponentModel; 24 using System.Collections; 25 using System.Collections.Generic; 26 using System.Reflection; 27 using System.Text; 28 using System.Text.RegularExpressions; 29 30 namespace System.Windows.Forms { 31 32 [ComplexBindingProperties ("DataSource", "DataMember")] 33 [DefaultEvent ("CurrentChanged")] 34 [DefaultProperty ("DataSource")] 35 [Designer("System.Windows.Forms.Design.BindingSourceDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")] 36 public class BindingSource : Component, 37 ICancelAddNew, IDisposable, ISupportInitialize, 38 IBindingListView, IBindingList, ITypedList, 39 IList, ISupportInitializeNotification, ICollection, 40 IComponent, ICurrencyManagerProvider, IEnumerable 41 { 42 bool is_initialized = true; 43 44 IList list; 45 CurrencyManager currency_manager; 46 Dictionary<string,CurrencyManager> related_currency_managers = new Dictionary<string,CurrencyManager> (); 47 //bool list_defaulted; 48 internal Type item_type; 49 bool item_has_default_ctor; 50 bool list_is_ibinding; 51 52 object datasource; 53 string datamember; 54 55 bool raise_list_changed_events; 56 57 bool allow_new_set; 58 bool allow_new; 59 60 bool add_pending; 61 int pending_add_index; 62 63 string filter; 64 string sort; 65 BindingSource(IContainer container)66 public BindingSource (IContainer container) : this () 67 { 68 container.Add (this); 69 } 70 BindingSource(object dataSource, string dataMember)71 public BindingSource (object dataSource, string dataMember) 72 { 73 datasource = dataSource; 74 datamember = dataMember; 75 76 raise_list_changed_events = true; 77 78 ResetList (); 79 ConnectCurrencyManager (); 80 } 81 BindingSource()82 public BindingSource () : this (null, String.Empty) 83 { 84 } 85 GetListFromEnumerable(IEnumerable enumerable)86 IList GetListFromEnumerable (IEnumerable enumerable) 87 { 88 IList l = null; 89 90 IEnumerator e = enumerable.GetEnumerator(); 91 92 if (enumerable is string) { 93 /* special case this.. seems to be the only one .net special cases? */ 94 l = new BindingList<char> (); 95 } 96 else { 97 /* try to figure out the type based on 98 * the first element, if there is 99 * one */ 100 object first = null; 101 if (e.MoveNext ()) { 102 first = e.Current; 103 } 104 105 if (first == null) { 106 return null; 107 } 108 else { 109 Type t = typeof (BindingList<>).MakeGenericType (new Type[] { first.GetType() }); 110 l = (IList)Activator.CreateInstance (t); 111 } 112 } 113 114 e.Reset (); 115 while (e.MoveNext ()) { 116 l.Add (e.Current); 117 } 118 119 return l; 120 } 121 ConnectCurrencyManager()122 void ConnectCurrencyManager () 123 { 124 currency_manager = new CurrencyManager (this); 125 126 currency_manager.PositionChanged += delegate (object o, EventArgs args) { OnPositionChanged (args); }; 127 currency_manager.CurrentChanged += delegate (object o, EventArgs args) { OnCurrentChanged (args); }; 128 currency_manager.BindingComplete += delegate (object o, BindingCompleteEventArgs args) { OnBindingComplete (args); }; 129 currency_manager.DataError += delegate (object o, BindingManagerDataErrorEventArgs args) { OnDataError (args); }; 130 currency_manager.CurrentChanged += delegate (object o, EventArgs args) { OnCurrentChanged (args); }; 131 currency_manager.CurrentItemChanged += delegate (object o, EventArgs args) { OnCurrentItemChanged (args); }; 132 } 133 ResetList()134 void ResetList () 135 { 136 if (!is_initialized) 137 return; 138 139 IList l; 140 object source = ListBindingHelper.GetList (datasource, datamember); 141 142 // 143 // If original source is null, then create a new object list 144 // Otherwise, try to infer the list item type 145 // 146 147 if (datasource == null) { 148 l = new BindingList<object>(); 149 //list_defaulted = true; 150 } else if (source == null) { 151 //Infer type based on datasource and datamember, 152 // where datasource is an empty IEnumerable 153 // and need to find out the datamember type 154 155 Type property_type = ListBindingHelper.GetListItemProperties (datasource) [datamember].PropertyType; 156 Type t = typeof (BindingList<>).MakeGenericType (new Type [] { property_type } ); 157 l = (IList)Activator.CreateInstance (t); 158 } else if (source is IList) { 159 l = (IList)source; 160 } else if (source is IEnumerable) { 161 IList new_list = GetListFromEnumerable ((IEnumerable)source); 162 l = new_list == null ? list : new_list; 163 } else if (source is Type) { 164 Type t = typeof (BindingList<>).MakeGenericType (new Type [] { (Type)source }); 165 l = (IList)Activator.CreateInstance (t); 166 } else { 167 Type t = typeof (BindingList<>).MakeGenericType (new Type[] { source.GetType() }); 168 l = (IList)Activator.CreateInstance (t); 169 l.Add (source); 170 } 171 172 SetList (l); 173 } 174 SetList(IList l)175 void SetList (IList l) 176 { 177 if (list is IBindingList) 178 ((IBindingList) list).ListChanged -= IBindingListChangedHandler; 179 180 list = l; 181 item_type = ListBindingHelper.GetListItemType (list); 182 item_has_default_ctor = item_type.GetConstructor (Type.EmptyTypes) != null; 183 184 list_is_ibinding = list is IBindingList; 185 if (list_is_ibinding) { 186 ((IBindingList) list).ListChanged += IBindingListChangedHandler; 187 188 if (list is IBindingListView) 189 ((IBindingListView)list).Filter = filter; 190 } 191 192 ResetBindings (true); 193 } 194 ConnectDataSourceEvents(object dataSource)195 private void ConnectDataSourceEvents (object dataSource) 196 { 197 if (dataSource == null) 198 return; 199 200 ICurrencyManagerProvider currencyManagerProvider = dataSource as ICurrencyManagerProvider; 201 if (currencyManagerProvider != null && currencyManagerProvider.CurrencyManager != null) { 202 currencyManagerProvider.CurrencyManager.CurrentItemChanged += OnParentCurrencyManagerChanged; 203 currencyManagerProvider.CurrencyManager.MetaDataChanged += OnParentCurrencyManagerChanged; 204 } 205 } 206 OnParentCurrencyManagerChanged(object sender, EventArgs args)207 private void OnParentCurrencyManagerChanged (object sender, EventArgs args) 208 { 209 // Essentially handles chained data sources (e.g. chained BindingSource) 210 ResetDataMemberIfInvalid (); 211 ResetList (); 212 } 213 DisconnectDataSourceEvents(object dataSource)214 private void DisconnectDataSourceEvents (object dataSource) 215 { 216 if (dataSource == null) 217 return; 218 219 ICurrencyManagerProvider currencyManagerProvider = dataSource as ICurrencyManagerProvider; 220 if (currencyManagerProvider != null && currencyManagerProvider.CurrencyManager != null) { 221 currencyManagerProvider.CurrencyManager.CurrentItemChanged -= OnParentCurrencyManagerChanged; 222 currencyManagerProvider.CurrencyManager.MetaDataChanged -= OnParentCurrencyManagerChanged; 223 } 224 } 225 IBindingListChangedHandler(object o, ListChangedEventArgs args)226 void IBindingListChangedHandler (object o, ListChangedEventArgs args) 227 { 228 if (raise_list_changed_events) 229 OnListChanged (args); 230 } 231 232 [Browsable (false)] 233 public virtual bool AllowEdit { 234 get { 235 if (list == null) 236 return false; 237 238 if (list.IsReadOnly) 239 return false; 240 241 if (list is IBindingList) 242 return ((IBindingList)list).AllowEdit; 243 244 return true; 245 } 246 } 247 248 public virtual bool AllowNew { 249 get { 250 if (allow_new_set) 251 return allow_new; 252 253 if (list is IBindingList) 254 return ((IBindingList)list).AllowNew; 255 256 if (list.IsFixedSize || list.IsReadOnly || !item_has_default_ctor) 257 return false; 258 259 return true; 260 } 261 set { 262 if (value == allow_new && allow_new_set) 263 return; 264 265 if (value && (list.IsReadOnly || list.IsFixedSize)) 266 throw new InvalidOperationException (); 267 268 allow_new_set = true; 269 allow_new = value; 270 271 if (raise_list_changed_events) 272 OnListChanged (new ListChangedEventArgs (ListChangedType.Reset, -1)); 273 } 274 } 275 276 bool IsAddingNewHandled { 277 get { 278 return Events [AddingNewEvent] != null; 279 } 280 } 281 282 [Browsable (false)] 283 public virtual bool AllowRemove { 284 get { 285 if (list == null) 286 return false; 287 288 if (list.IsFixedSize || list.IsReadOnly) 289 return false; 290 291 if (list is IBindingList) 292 return ((IBindingList)list).AllowRemove; 293 294 return true; 295 } 296 } 297 298 [Browsable (false)] 299 public virtual int Count { 300 get { 301 return list.Count; 302 } 303 } 304 305 [Browsable (false)] 306 public virtual CurrencyManager CurrencyManager { 307 get { 308 return currency_manager; 309 } 310 } 311 312 [Browsable (false)] 313 public object Current { 314 get { 315 if (currency_manager.Count > 0) 316 return currency_manager.Current; 317 return null; 318 } 319 } 320 321 [DefaultValue ("")] 322 [Editor("System.Windows.Forms.Design.DataMemberListEditor, " + Consts.AssemblySystem_Design, typeof(System.Drawing.Design.UITypeEditor))] 323 [RefreshProperties (RefreshProperties.Repaint)] 324 public string DataMember { 325 get { return datamember; } 326 set { 327 /* we don't allow null DataMembers */ 328 if (value == null) 329 value = String.Empty; 330 331 if (datamember != value) { 332 this.datamember = value; 333 334 ResetList (); 335 336 OnDataMemberChanged (EventArgs.Empty); 337 } 338 } 339 } 340 341 [AttributeProvider (typeof(IListSource))] 342 [RefreshProperties (RefreshProperties.Repaint)] 343 [DefaultValue (null)] 344 public object DataSource { 345 get { return datasource; } 346 set { 347 if (datasource != value) { 348 if (value == null) 349 datamember = String.Empty; 350 351 DisconnectDataSourceEvents (datasource); 352 datasource = value; 353 ResetDataMemberIfInvalid (); 354 ConnectDataSourceEvents (datasource); 355 ResetList (); 356 357 OnDataSourceChanged (EventArgs.Empty); 358 } 359 } 360 } 361 362 [DefaultValue (null)] 363 public virtual string Filter { 364 get { 365 return filter; 366 } 367 set { 368 if (SupportsFiltering) 369 ((IBindingListView)list).Filter = value; 370 371 filter = value; 372 } 373 } 374 375 [Browsable (false)] 376 public bool IsBindingSuspended { 377 get { return currency_manager.IsBindingSuspended; } 378 } 379 380 [Browsable (false)] 381 public virtual bool IsFixedSize { 382 get { return list.IsFixedSize; } 383 } 384 385 [Browsable (false)] 386 public virtual bool IsReadOnly { 387 get { return list.IsReadOnly; } 388 } 389 390 [Browsable (false)] 391 public virtual bool IsSorted { 392 get { return (list is IBindingList) && ((IBindingList)list).IsSorted; } 393 } 394 395 [Browsable (false)] 396 public virtual bool IsSynchronized { 397 get { 398 return list.IsSynchronized; 399 } 400 } 401 402 [Browsable (false)] 403 public virtual object this [int index] { 404 get { return list[index]; } 405 set 406 { 407 list[index] = value; 408 } 409 } 410 411 [Browsable (false)] 412 public IList List { 413 get { return list; } 414 } 415 416 [DefaultValue (-1)] 417 [Browsable (false)] 418 public int Position { 419 get { 420 return currency_manager.Position; 421 } 422 set { 423 if (value >= Count) value = Count - 1; 424 if (value < 0) value = 0; 425 426 currency_manager.Position = value; 427 } 428 } 429 430 [Browsable (false)] 431 [DefaultValue (true)] 432 public bool RaiseListChangedEvents { 433 get { return raise_list_changed_events; } 434 set { raise_list_changed_events = value; } 435 } 436 437 [DefaultValue (null)] 438 public string Sort { 439 get { 440 return sort; 441 } 442 set { 443 if (value == null || value.Length == 0) { 444 if (list_is_ibinding && SupportsSorting) 445 RemoveSort (); 446 447 sort = value; 448 return; 449 } 450 451 if (!list_is_ibinding || !SupportsSorting) 452 throw new ArgumentException ("value"); 453 454 ProcessSortString (value); 455 sort = value; 456 } 457 } 458 ResetDataMemberIfInvalid()459 void ResetDataMemberIfInvalid () 460 { 461 if (datamember == String.Empty) 462 return; 463 464 // if dataMember doesn't refer to a valid property of dataSource, we need to reset it 465 var property = ListBindingHelper.GetListItemProperties (datasource).Find (datamember, true); 466 if (property == null) { 467 datamember = String.Empty; 468 OnDataMemberChanged (EventArgs.Empty); 469 } 470 } 471 472 // NOTE: Probably the parsing can be improved ProcessSortString(string sort)473 void ProcessSortString (string sort) 474 { 475 // Only keep simple whitespaces in the middle 476 sort = Regex.Replace (sort, "( )+", " "); 477 478 string [] properties = sort.Split (','); 479 PropertyDescriptorCollection prop_descs = GetItemProperties (null); 480 if (properties.Length == 1) { 481 ListSortDescription sort_desc = GetListSortDescription (prop_descs, properties [0]); 482 ApplySort (sort_desc.PropertyDescriptor, sort_desc.SortDirection); 483 } else { 484 if (!SupportsAdvancedSorting) 485 throw new ArgumentException ("value"); 486 487 ListSortDescription [] sort_descs = new ListSortDescription [properties.Length]; 488 for (int i = 0; i < properties.Length; i++) 489 sort_descs [i] = GetListSortDescription (prop_descs, properties [i]); 490 491 ApplySort (new ListSortDescriptionCollection (sort_descs)); 492 } 493 494 } 495 GetListSortDescription(PropertyDescriptorCollection prop_descs, string property)496 ListSortDescription GetListSortDescription (PropertyDescriptorCollection prop_descs, string property) 497 { 498 property = property.Trim (); 499 string [] p = property.Split (new char [] {' '}, 2); 500 501 string prop_name = p [0]; 502 PropertyDescriptor prop_desc = prop_descs [prop_name]; 503 if (prop_desc == null) 504 throw new ArgumentException ("value"); 505 506 ListSortDirection sort_direction = ListSortDirection.Ascending; 507 if (p.Length > 1) { 508 string dir_s = p [1]; 509 if (String.Compare (dir_s, "ASC", true) == 0) 510 sort_direction = ListSortDirection.Ascending; 511 else if (String.Compare (dir_s, "DESC", true) == 0) 512 sort_direction = ListSortDirection.Descending; 513 else 514 throw new ArgumentException ("value"); 515 } 516 517 return new ListSortDescription (prop_desc, sort_direction); 518 } 519 520 [Browsable (false)] 521 [EditorBrowsable (EditorBrowsableState.Never)] 522 public virtual ListSortDescriptionCollection SortDescriptions { 523 get { 524 if (list is IBindingListView) 525 return ((IBindingListView)list).SortDescriptions; 526 527 return null; 528 } 529 } 530 531 [Browsable (false)] 532 [EditorBrowsable (EditorBrowsableState.Never)] 533 public virtual ListSortDirection SortDirection { 534 get { 535 if (list is IBindingList) 536 return ((IBindingList)list).SortDirection; 537 538 return ListSortDirection.Ascending; 539 } 540 } 541 542 [Browsable (false)] 543 [EditorBrowsable (EditorBrowsableState.Never)] 544 public virtual PropertyDescriptor SortProperty { 545 get { 546 if (list is IBindingList) 547 return ((IBindingList)list).SortProperty; 548 549 return null; 550 } 551 } 552 553 [Browsable (false)] 554 public virtual bool SupportsAdvancedSorting { 555 get { return (list is IBindingListView) && ((IBindingListView)list).SupportsAdvancedSorting; } 556 } 557 558 [Browsable (false)] 559 public virtual bool SupportsChangeNotification { 560 get { return true; } 561 } 562 563 [Browsable (false)] 564 public virtual bool SupportsFiltering { 565 get { return (list is IBindingListView) && ((IBindingListView)list).SupportsFiltering; } 566 } 567 568 [Browsable (false)] 569 public virtual bool SupportsSearching { 570 get { 571 return (list is IBindingList) && ((IBindingList)list).SupportsSearching; 572 } 573 } 574 575 [Browsable (false)] 576 public virtual bool SupportsSorting { 577 get { return (list is IBindingList) && ((IBindingList)list).SupportsSorting; } 578 } 579 580 [Browsable (false)] 581 public virtual object SyncRoot { 582 get { 583 return list.SyncRoot; 584 } 585 } 586 587 static object AddingNewEvent = new object (); 588 static object BindingCompleteEvent = new object (); 589 static object CurrentChangedEvent = new object (); 590 static object CurrentItemChangedEvent = new object (); 591 static object DataErrorEvent = new object (); 592 static object DataMemberChangedEvent = new object (); 593 static object DataSourceChangedEvent = new object (); 594 static object ListChangedEvent = new object (); 595 static object PositionChangedEvent= new object (); 596 597 public event AddingNewEventHandler AddingNew { 598 add { Events.AddHandler (AddingNewEvent, value); } 599 remove { Events.RemoveHandler (AddingNewEvent, value); } 600 } 601 602 public event BindingCompleteEventHandler BindingComplete { 603 add { Events.AddHandler (BindingCompleteEvent, value); } 604 remove { Events.RemoveHandler (BindingCompleteEvent, value); } 605 } 606 607 public event EventHandler CurrentChanged { 608 add { Events.AddHandler (CurrentChangedEvent, value); } 609 remove { Events.RemoveHandler (CurrentChangedEvent, value); } 610 } 611 612 public event EventHandler CurrentItemChanged { 613 add { Events.AddHandler (CurrentItemChangedEvent, value); } 614 remove { Events.RemoveHandler (CurrentItemChangedEvent, value); } 615 } 616 617 public event BindingManagerDataErrorEventHandler DataError { 618 add { Events.AddHandler (DataErrorEvent, value); } 619 remove { Events.RemoveHandler (DataErrorEvent, value); } 620 } 621 622 public event EventHandler DataMemberChanged { 623 add { Events.AddHandler (DataMemberChangedEvent, value); } 624 remove { Events.RemoveHandler (DataMemberChangedEvent, value); } 625 } 626 627 public event EventHandler DataSourceChanged { 628 add { Events.AddHandler (DataSourceChangedEvent, value); } 629 remove { Events.RemoveHandler (DataSourceChangedEvent, value); } 630 } 631 632 public event ListChangedEventHandler ListChanged { 633 add { Events.AddHandler (ListChangedEvent, value); } 634 remove { Events.RemoveHandler (ListChangedEvent, value); } 635 } 636 637 public event EventHandler PositionChanged { 638 add { Events.AddHandler (PositionChangedEvent, value); } 639 remove { Events.RemoveHandler (PositionChangedEvent, value); } 640 } 641 Add(object value)642 public virtual int Add (object value) 643 { 644 // 645 // First (re)create the BindingList<T> based on value 646 // if datasource is null and the current list is empty 647 // 648 if (datasource == null && list.Count == 0 && value != null) { 649 Type t = typeof (BindingList<>).MakeGenericType (new Type [] { value.GetType () } ); 650 IList l = (IList) Activator.CreateInstance (t); 651 SetList (l); 652 } 653 654 if (value != null && !item_type.IsAssignableFrom (value.GetType ())) 655 throw new InvalidOperationException ("Objects added to the list must all be of the same type."); 656 if (list.IsReadOnly) 657 throw new NotSupportedException ("Collection is read-only."); 658 if (list.IsFixedSize) 659 throw new NotSupportedException ("Collection has a fixed size."); 660 661 int idx = list.Add (value); 662 if (raise_list_changed_events && !list_is_ibinding) 663 OnListChanged (new ListChangedEventArgs (ListChangedType.ItemAdded, idx)); 664 665 return idx; 666 } 667 AddNew()668 public virtual object AddNew () 669 { 670 if (!AllowEdit) 671 throw new InvalidOperationException ("Item cannot be added to a read-only or fixed-size list."); 672 if (!AllowNew) 673 throw new InvalidOperationException ("AddNew is set to false."); 674 675 EndEdit (); 676 677 AddingNewEventArgs args = new AddingNewEventArgs (); 678 OnAddingNew (args); 679 680 object new_object = args.NewObject; 681 if (new_object != null) { 682 if (!item_type.IsAssignableFrom (new_object.GetType ())) 683 throw new InvalidOperationException ("Objects added to the list must all be of the same type."); 684 } else if (list is IBindingList) { 685 object newObj = ((IBindingList)list).AddNew (); 686 add_pending = true; 687 pending_add_index = list.IndexOf (newObj); 688 return newObj; 689 } else if (!item_has_default_ctor) 690 throw new InvalidOperationException ("AddNew cannot be called on '" + item_type.Name + 691 ", since it does not have a public default ctor. Set AllowNew to true " + 692 ", handling AddingNew and creating the appropriate object."); 693 else // fallback to default .ctor 694 new_object = Activator.CreateInstance (item_type); 695 696 int idx = list.Add (new_object); 697 if (raise_list_changed_events && !list_is_ibinding) 698 OnListChanged (new ListChangedEventArgs (ListChangedType.ItemAdded, idx)); 699 700 add_pending = true; 701 pending_add_index = idx; 702 703 return new_object; 704 } 705 706 [EditorBrowsable (EditorBrowsableState.Never)] ApplySort(PropertyDescriptor property, ListSortDirection sort)707 public virtual void ApplySort (PropertyDescriptor property, ListSortDirection sort) 708 { 709 if (!list_is_ibinding) 710 throw new NotSupportedException ("This operation requires an IBindingList."); 711 712 IBindingList iblist = (IBindingList)list; 713 iblist.ApplySort (property, sort); 714 } 715 716 [EditorBrowsable (EditorBrowsableState.Never)] ApplySort(ListSortDescriptionCollection sorts)717 public virtual void ApplySort (ListSortDescriptionCollection sorts) 718 { 719 if (!(list is IBindingListView)) 720 throw new NotSupportedException ("This operation requires an IBindingListView."); 721 722 IBindingListView iblist_view = (IBindingListView)list; 723 iblist_view.ApplySort (sorts); 724 } 725 CancelEdit()726 public void CancelEdit () 727 { 728 currency_manager.CancelCurrentEdit (); 729 } 730 Clear()731 public virtual void Clear () 732 { 733 if (list.IsReadOnly) 734 throw new NotSupportedException ("Collection is read-only."); 735 736 list.Clear (); 737 if (raise_list_changed_events && !list_is_ibinding) 738 OnListChanged (new ListChangedEventArgs (ListChangedType.Reset, -1)); 739 } 740 Contains(object value)741 public virtual bool Contains (object value) 742 { 743 return list.Contains (value); 744 } 745 CopyTo(Array arr, int index)746 public virtual void CopyTo (Array arr, int index) 747 { 748 list.CopyTo (arr, index); 749 } 750 Dispose(bool disposing)751 protected override void Dispose (bool disposing) 752 { 753 base.Dispose (disposing); 754 } 755 EndEdit()756 public void EndEdit () 757 { 758 currency_manager.EndCurrentEdit (); 759 } 760 Find(string propertyName, object key)761 public int Find (string propertyName, object key) 762 { 763 PropertyDescriptor property = GetItemProperties (null).Find (propertyName, true); 764 if (property == null) 765 throw new ArgumentException ("propertyName"); 766 767 return Find (property, key); 768 } 769 Find(PropertyDescriptor prop, object key)770 public virtual int Find (PropertyDescriptor prop, object key) 771 { 772 if (!list_is_ibinding) 773 throw new NotSupportedException (); 774 775 return ((IBindingList)list).Find (prop, key); 776 } 777 GetEnumerator()778 public virtual IEnumerator GetEnumerator () 779 { 780 return this.List.GetEnumerator (); 781 } 782 GetItemProperties(PropertyDescriptor[] listAccessors)783 public virtual PropertyDescriptorCollection GetItemProperties (PropertyDescriptor[] listAccessors) 784 { 785 return ListBindingHelper.GetListItemProperties (list, listAccessors); 786 } 787 GetListName(PropertyDescriptor[] listAccessors)788 public virtual string GetListName (PropertyDescriptor[] listAccessors) 789 { 790 return ListBindingHelper.GetListName (list, listAccessors); 791 } 792 GetRelatedCurrencyManager(string dataMember)793 public virtual CurrencyManager GetRelatedCurrencyManager (string dataMember) 794 { 795 if (dataMember == null || dataMember.Length == 0) 796 return currency_manager; 797 798 if (related_currency_managers.ContainsKey (dataMember)) 799 return related_currency_managers [dataMember]; 800 801 // FIXME - Why passing invalid dataMembers containing a . return 802 // a null value? 803 if (dataMember.IndexOf ('.') != -1) 804 return null; 805 806 BindingSource source = new BindingSource (this, dataMember); 807 related_currency_managers [dataMember] = source.CurrencyManager; 808 809 return source.CurrencyManager; 810 } 811 IndexOf(object value)812 public virtual int IndexOf (object value) 813 { 814 return list.IndexOf (value); 815 } 816 Insert(int index, object value)817 public virtual void Insert (int index, object value) 818 { 819 if (index < 0 || index > list.Count) 820 throw new ArgumentOutOfRangeException ("index"); 821 if (list.IsReadOnly || list.IsFixedSize) 822 throw new NotSupportedException (); 823 if (!item_type.IsAssignableFrom (value.GetType ())) 824 throw new ArgumentException ("value"); 825 826 list.Insert (index, value); 827 if (raise_list_changed_events && !list_is_ibinding) 828 OnListChanged (new ListChangedEventArgs (ListChangedType.ItemAdded, index)); 829 } 830 MoveFirst()831 public void MoveFirst () 832 { 833 Position = 0; 834 } 835 MoveLast()836 public void MoveLast () 837 { 838 Position = Count - 1; 839 } 840 MoveNext()841 public void MoveNext () 842 { 843 Position ++; 844 } 845 MovePrevious()846 public void MovePrevious () 847 { 848 Position --; 849 } 850 OnAddingNew(AddingNewEventArgs e)851 protected virtual void OnAddingNew (AddingNewEventArgs e) 852 { 853 AddingNewEventHandler eh = (AddingNewEventHandler)Events[AddingNewEvent]; 854 if (eh != null) 855 eh (this, e); 856 } 857 OnBindingComplete(BindingCompleteEventArgs e)858 protected virtual void OnBindingComplete (BindingCompleteEventArgs e) 859 { 860 BindingCompleteEventHandler eh = (BindingCompleteEventHandler) Events[BindingCompleteEvent]; 861 if (eh != null) 862 eh (this, e); 863 } 864 OnCurrentChanged(EventArgs e)865 protected virtual void OnCurrentChanged (EventArgs e) 866 { 867 EventHandler eh = (EventHandler) Events[CurrentChangedEvent]; 868 if (eh != null) 869 eh (this, e); 870 } 871 OnCurrentItemChanged(EventArgs e)872 protected virtual void OnCurrentItemChanged (EventArgs e) 873 { 874 EventHandler eh = (EventHandler) Events[CurrentItemChangedEvent]; 875 if (eh != null) 876 eh (this, e); 877 } 878 OnDataError(BindingManagerDataErrorEventArgs e)879 protected virtual void OnDataError (BindingManagerDataErrorEventArgs e) 880 { 881 BindingManagerDataErrorEventHandler eh = (BindingManagerDataErrorEventHandler) Events[DataErrorEvent]; 882 if (eh != null) 883 eh (this, e); 884 } 885 OnDataMemberChanged(EventArgs e)886 protected virtual void OnDataMemberChanged (EventArgs e) 887 { 888 EventHandler eh = (EventHandler) Events[DataMemberChangedEvent]; 889 if (eh != null) 890 eh (this, e); 891 } 892 OnDataSourceChanged(EventArgs e)893 protected virtual void OnDataSourceChanged (EventArgs e) 894 { 895 EventHandler eh = (EventHandler) Events[DataSourceChangedEvent]; 896 if (eh != null) 897 eh (this, e); 898 } 899 OnListChanged(ListChangedEventArgs e)900 protected virtual void OnListChanged (ListChangedEventArgs e) 901 { 902 ListChangedEventHandler eh = (ListChangedEventHandler) Events[ListChangedEvent]; 903 if (eh != null) 904 eh (this, e); 905 } 906 OnPositionChanged(EventArgs e)907 protected virtual void OnPositionChanged (EventArgs e) 908 { 909 EventHandler eh = (EventHandler) Events[PositionChangedEvent]; 910 if (eh != null) 911 eh (this, e); 912 } 913 Remove(object value)914 public virtual void Remove (object value) 915 { 916 if (list.IsReadOnly) 917 throw new NotSupportedException ("Collection is read-only."); 918 if (list.IsFixedSize) 919 throw new NotSupportedException ("Collection has a fixed size."); 920 921 int idx = list_is_ibinding ? - 1 : list.IndexOf (value); 922 list.Remove (value); 923 924 if (idx != -1 && raise_list_changed_events) 925 OnListChanged (new ListChangedEventArgs (ListChangedType.ItemDeleted, idx)); 926 } 927 RemoveAt(int index)928 public virtual void RemoveAt (int index) 929 { 930 if (index < 0 || index > list.Count) 931 throw new ArgumentOutOfRangeException ("index"); 932 if (list.IsReadOnly || list.IsFixedSize) 933 throw new InvalidOperationException (); 934 935 list.RemoveAt (index); 936 if (raise_list_changed_events && !list_is_ibinding) 937 OnListChanged (new ListChangedEventArgs (ListChangedType.ItemDeleted, index)); 938 } 939 RemoveCurrent()940 public void RemoveCurrent () 941 { 942 if (Position < 0) 943 throw new InvalidOperationException ("Cannot remove item because there is no current item."); 944 if (!AllowRemove) 945 throw new InvalidOperationException ("Cannot remove item because list does not allow removal of items."); 946 947 RemoveAt (Position); 948 } 949 RemoveFilter()950 public virtual void RemoveFilter () 951 { 952 Filter = null; 953 } 954 RemoveSort()955 public virtual void RemoveSort () 956 { 957 if (!list_is_ibinding) 958 return; 959 960 sort = null; 961 ((IBindingList)list).RemoveSort (); 962 } 963 964 [EditorBrowsable (EditorBrowsableState.Advanced)] ResetAllowNew()965 public virtual void ResetAllowNew () 966 { 967 allow_new_set = false; 968 } 969 ResetBindings(bool metadataChanged)970 public void ResetBindings (bool metadataChanged) 971 { 972 if (metadataChanged) 973 OnListChanged (new ListChangedEventArgs (ListChangedType.PropertyDescriptorChanged, null)); 974 975 OnListChanged (new ListChangedEventArgs (ListChangedType.Reset, -1, -1)); 976 } 977 ResetCurrentItem()978 public void ResetCurrentItem () 979 { 980 OnListChanged (new ListChangedEventArgs (ListChangedType.ItemChanged, Position, -1)); 981 } 982 ResetItem(int itemIndex)983 public void ResetItem (int itemIndex) 984 { 985 OnListChanged (new ListChangedEventArgs (ListChangedType.ItemChanged, itemIndex, -1)); 986 } 987 ResumeBinding()988 public void ResumeBinding () 989 { 990 currency_manager.ResumeBinding (); 991 } 992 SuspendBinding()993 public void SuspendBinding () 994 { 995 currency_manager.SuspendBinding (); 996 } 997 998 /* explicit interface implementations */ 999 ICancelAddNew.CancelNew(int position)1000 void ICancelAddNew.CancelNew (int position) 1001 { 1002 if (!add_pending) 1003 return; 1004 1005 if (position != pending_add_index) 1006 return; 1007 1008 add_pending = false; 1009 list.RemoveAt (position); 1010 1011 if (raise_list_changed_events && !list_is_ibinding) 1012 OnListChanged (new ListChangedEventArgs (ListChangedType.ItemDeleted, position)); 1013 } 1014 ICancelAddNew.EndNew(int position)1015 void ICancelAddNew.EndNew (int position) 1016 { 1017 if (!add_pending) 1018 return; 1019 1020 if (position != pending_add_index) 1021 return; 1022 1023 add_pending = false; 1024 } 1025 ISupportInitialize.BeginInit()1026 void ISupportInitialize.BeginInit () 1027 { 1028 is_initialized = false; 1029 } 1030 DataSourceEndInitHandler(object o, EventArgs args)1031 void DataSourceEndInitHandler (object o, EventArgs args) 1032 { 1033 ((ISupportInitializeNotification)datasource).Initialized -= DataSourceEndInitHandler; 1034 1035 ISupportInitializeNotification inotif = (ISupportInitializeNotification)this; 1036 inotif.EndInit (); 1037 } 1038 ISupportInitialize.EndInit()1039 void ISupportInitialize.EndInit () 1040 { 1041 if (datasource != null && datasource is ISupportInitializeNotification) { 1042 ISupportInitializeNotification inotif = (ISupportInitializeNotification)datasource; 1043 if (!inotif.IsInitialized) { 1044 inotif.Initialized += DataSourceEndInitHandler; 1045 return; 1046 } 1047 } 1048 1049 is_initialized = true; 1050 ResetList (); 1051 1052 EventHandler eh = (EventHandler) Events [InitializedEvent]; 1053 if (eh != null) 1054 eh (this, EventArgs.Empty); 1055 } 1056 IBindingList.AddIndex(PropertyDescriptor property)1057 void IBindingList.AddIndex (PropertyDescriptor property) 1058 { 1059 if (!(list is IBindingList)) 1060 throw new NotSupportedException(); 1061 1062 ((IBindingList)list).AddIndex (property); 1063 } 1064 IBindingList.RemoveIndex(PropertyDescriptor prop)1065 void IBindingList.RemoveIndex (PropertyDescriptor prop) 1066 { 1067 if (!(list is IBindingList)) 1068 throw new NotSupportedException(); 1069 1070 ((IBindingList)list).RemoveIndex (prop); 1071 } 1072 1073 bool ISupportInitializeNotification.IsInitialized { 1074 get { 1075 return is_initialized; 1076 } 1077 } 1078 1079 static object InitializedEvent = new object (); 1080 1081 event EventHandler ISupportInitializeNotification.Initialized { 1082 add { Events.AddHandler (InitializedEvent, value); } 1083 remove { Events.RemoveHandler (InitializedEvent, value); } 1084 } 1085 } 1086 } 1087