PageRenderTime 60ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/class/Managed.Windows.Forms/System.Windows.Forms/BindingSource.cs

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