BindingSourceTest.cs 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986
  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. #if NET_2_0
  23. using System;
  24. using System.Data;
  25. using System.Collections;
  26. using System.Collections.Generic;
  27. using System.ComponentModel;
  28. using System.Windows.Forms;
  29. using NUnit.Framework;
  30. using CategoryAttribute = NUnit.Framework.CategoryAttribute;
  31. namespace MonoTests.System.Windows.Forms.DataBinding {
  32. [TestFixture]
  33. public class BindingSourceTest : TestHelper
  34. {
  35. [Test]
  36. public void DefaultDataSource ()
  37. {
  38. BindingSource source = new BindingSource ();
  39. Assert.IsTrue (source.List is BindingList<object>, "1");
  40. Assert.AreEqual (0, source.List.Count, "2");
  41. }
  42. [Test]
  43. public void DataSource_InitialAddChangingType ()
  44. {
  45. BindingSource source = new BindingSource ();
  46. source.Add ((int)32);
  47. Assert.IsTrue (source.List is BindingList<int>, "1");
  48. source = new BindingSource ();
  49. source.DataSource = new ArrayList ();
  50. source.Add ((int)32);
  51. Assert.IsFalse (source.List is BindingList<int>, "2");
  52. }
  53. class EmptyEnumerable : IEnumerable {
  54. class EmptyEnumerator : IEnumerator {
  55. public object Current {
  56. get { throw new InvalidOperationException (); }
  57. }
  58. public void Reset () {
  59. // nada
  60. }
  61. public bool MoveNext () {
  62. return false;
  63. }
  64. }
  65. public IEnumerator GetEnumerator () {
  66. return new EmptyEnumerator ();
  67. }
  68. }
  69. class GenericEnumerable : IEnumerable<int> {
  70. int length;
  71. public GenericEnumerable (int length) {
  72. this.length = length;
  73. }
  74. class MyEnumerator : IEnumerator<int> {
  75. public int count;
  76. public int index;
  77. public int Current {
  78. get { return index; }
  79. }
  80. object IEnumerator.Current {
  81. get { return Current; }
  82. }
  83. public void Reset () {
  84. index = 0;
  85. }
  86. public bool MoveNext () {
  87. if (index++ == count)
  88. return false;
  89. else
  90. return true;
  91. }
  92. void IDisposable.Dispose () {
  93. }
  94. }
  95. public IEnumerator<int> GetEnumerator () {
  96. MyEnumerator e = new MyEnumerator ();
  97. e.count = length;
  98. return e;
  99. }
  100. IEnumerator IEnumerable.GetEnumerator () {
  101. return GetEnumerator ();
  102. }
  103. }
  104. class WorkingEnumerable : IEnumerable {
  105. int length;
  106. public WorkingEnumerable (int length) {
  107. this.length = length;
  108. }
  109. class MyEnumerator : IEnumerator {
  110. public int count;
  111. public int index;
  112. public object Current {
  113. get { return index; }
  114. }
  115. public void Reset () {
  116. index = 0;
  117. }
  118. public bool MoveNext () {
  119. if (index++ == count)
  120. return false;
  121. else
  122. return true;
  123. }
  124. }
  125. public IEnumerator GetEnumerator () {
  126. MyEnumerator e = new MyEnumerator ();
  127. e.count = length;
  128. return e;
  129. }
  130. }
  131. [Test]
  132. public void DataSource_ListRelationship ()
  133. {
  134. BindingSource source = new BindingSource ();
  135. // null
  136. source.DataSource = null;
  137. Assert.IsTrue (source.List is BindingList<object>, "1");
  138. // a non-list object
  139. source.DataSource = new object ();
  140. Assert.IsTrue (source.List is BindingList<object>, "2");
  141. // array instance (value type)
  142. source.DataSource = new int[32];
  143. Assert.IsTrue (source.List is int[], "3");
  144. // an instance array with 0 elements
  145. source.DataSource = new int[0];
  146. Assert.IsTrue (source.List is int[], "4");
  147. // array instance (object type)
  148. source.DataSource = new string[32];
  149. Assert.IsTrue (source.List is string[], "5");
  150. // list type
  151. source.DataSource = new List<bool>();
  152. Assert.IsTrue (source.List is List<bool>, "6");
  153. // an IEnumerable type
  154. source.DataSource = "hi";
  155. Assert.IsTrue (source.List is BindingList<char>, "7");
  156. // an IEnumerable type with 0 items
  157. source.DataSource = "";
  158. Assert.IsTrue (source.List is BindingList<char>, "8");
  159. Assert.AreEqual (0, source.List.Count, "9");
  160. // a generic enumerable with no elements.
  161. // even though we can figure out the type
  162. // through reflection, we shouldn't..
  163. source.DataSource = new GenericEnumerable (0);
  164. Console.WriteLine (source.List.GetType());
  165. Assert.IsTrue (source.List is BindingList<char>, "10");
  166. Assert.AreEqual (0, source.List.Count, "11");
  167. // a non-generic IEnumerable type with 0 items
  168. // this doesn't seem to change the type of the
  169. // binding source's list, probably because it
  170. // can't determine the type of the
  171. // enumerable's elements.
  172. source.DataSource = new EmptyEnumerable ();
  173. Assert.IsTrue (source.List is BindingList<char>, "12");
  174. // an enumerable with some elements
  175. source.DataSource = new WorkingEnumerable (5);
  176. Assert.IsTrue (source.List is BindingList<int>, "13");
  177. Assert.AreEqual (5, source.List.Count, "14");
  178. // IListSource - returns an array
  179. source.DataSource = new ListBindingHelperTest.ListSource (true);
  180. Assert.IsTrue (source.List is Array, "#15");
  181. Assert.AreEqual (1, source.List.Count, "#16");
  182. }
  183. [Test]
  184. public void Filter ()
  185. {
  186. BindingSource source = new BindingSource ();
  187. DataTable table = new DataTable ();
  188. string filter = "Name = 'Mono'";
  189. IBindingListView view;
  190. table.Columns.Add ("Id", typeof (int));
  191. table.Columns.Add ("Name", typeof (string));
  192. table.Rows.Add (0, "Mono");
  193. table.Rows.Add (1, "Miguel");
  194. table.Rows.Add (2, "Paolo");
  195. table.Rows.Add (3, "Mono");
  196. source.DataSource = table;
  197. Assert.AreEqual (null, source.Filter, "A1");
  198. source.Filter = filter;
  199. view = (IBindingListView)((IListSource)table).GetList ();
  200. Assert.AreEqual (filter, source.Filter, "B1");
  201. Assert.AreEqual (filter, view.Filter, "B2");
  202. Assert.AreEqual (2, view.Count, "B3");
  203. Assert.AreEqual (2, source.List.Count, "B4");
  204. source.Filter = String.Empty;
  205. Assert.AreEqual (String.Empty, source.Filter, "C1");
  206. Assert.AreEqual (String.Empty, view.Filter, "C2");
  207. Assert.AreEqual (4, view.Count, "C3");
  208. Assert.AreEqual (4, source.List.Count, "C4");
  209. source.DataSource = null;
  210. Assert.AreEqual (String.Empty, source.Filter, "D1"); // Keep previous value
  211. filter = "Name = 'Miguel'"; // Apply filter before assigning data source
  212. source.Filter = filter;
  213. source.DataSource = table;
  214. view = (IBindingListView)((IListSource)table).GetList ();
  215. Assert.AreEqual (filter, source.Filter, "E1");
  216. Assert.AreEqual (filter, view.Filter, "E2");
  217. Assert.AreEqual (1, view.Count, "E3");
  218. Assert.AreEqual (1, source.List.Count, "E4");
  219. }
  220. [Test]
  221. public void Filter_NonBindingListView ()
  222. {
  223. BindingSource source = new BindingSource ();
  224. List<int> list = new List<int> ();
  225. list.AddRange (new int [] { 0, 1, 2 });
  226. string filter = "NonExistentColumn = 'A'"; ;
  227. source.DataSource = list;
  228. Assert.AreEqual (null, source.Filter, "A1");
  229. // List<> doesn't implement IBindingListView, but
  230. // the filter string is saved
  231. source.Filter = filter;
  232. Assert.AreEqual (filter, source.Filter, "B1");
  233. source.Filter = null;
  234. Assert.AreEqual (null, source.Filter, "C1");
  235. }
  236. [Test]
  237. public void RemoveFilter ()
  238. {
  239. BindingSource source = new BindingSource ();
  240. source.Filter = "Name = 'Something'";
  241. source.RemoveFilter ();
  242. Assert.AreEqual (null, source.Filter, "A1");
  243. }
  244. [Test]
  245. public void RemoveSort ()
  246. {
  247. BindingSource source = new BindingSource ();
  248. DataTable table = CreateTable ();
  249. source.DataSource = table;
  250. source.Sort = "Name";
  251. IBindingListView view = (IBindingListView)source.List;
  252. Assert.AreEqual ("Name", source.Sort, "A1");
  253. Assert.AreEqual ("Name", view.SortProperty.Name, "A2");
  254. source.RemoveSort ();
  255. Assert.AreEqual (null, source.Sort, "B1");
  256. Assert.AreEqual (null, view.SortProperty, "B2");
  257. // Non IBindingListView source - No exception, as opposed to what
  258. // the documentation says
  259. source.Sort = null;
  260. source.DataSource = new List<string> ();
  261. source.RemoveSort ();
  262. }
  263. [Test]
  264. public void ResetItem ()
  265. {
  266. BindingSource source = new BindingSource ();
  267. bool delegate_reached = false;
  268. int old_index = 5;
  269. int new_index = 5;
  270. ListChangedType type = ListChangedType.Reset;
  271. source.ListChanged += delegate (object sender, ListChangedEventArgs e) {
  272. delegate_reached = true;
  273. type = e.ListChangedType;
  274. old_index = e.OldIndex;
  275. new_index = e.NewIndex;
  276. };
  277. source.ResetItem (0);
  278. Assert.IsTrue (delegate_reached, "1");
  279. Assert.AreEqual (-1, old_index, "2");
  280. Assert.AreEqual (0, new_index, "3");
  281. Assert.AreEqual (ListChangedType.ItemChanged, type, "3");
  282. }
  283. DataTable CreateTable ()
  284. {
  285. DataTable table = new DataTable ();
  286. table.Columns.Add ("Id", typeof (int));
  287. table.Columns.Add ("Name", typeof (string));
  288. table.Rows.Add (0, "Mono");
  289. table.Rows.Add (2, "JPobst");
  290. table.Rows.Add (1, "Miguel");
  291. return table;
  292. }
  293. [Test]
  294. public void Sort_IBindingList ()
  295. {
  296. BindingSource source = new BindingSource ();
  297. BindingList<string> list = new BindingList<string> ();
  298. source.DataSource = list;
  299. // Implements IBindingList but SupportsSorting is false
  300. try {
  301. source.Sort = "Name";
  302. Assert.Fail ("A1");
  303. } catch (ArgumentException) {
  304. }
  305. }
  306. [Test]
  307. public void Sort_IBindingListView ()
  308. {
  309. BindingSource source = new BindingSource ();
  310. DataTable table = CreateTable ();
  311. //
  312. // Simple
  313. //
  314. source.DataSource = table;
  315. source.Sort = "Name";
  316. DataView view = (DataView)((IListSource)table).GetList ();
  317. Assert.AreEqual ("Name", source.Sort, "A1");
  318. Assert.AreEqual (ListSortDirection.Ascending, ((IBindingListView) source).SortDirection, "A2");
  319. Assert.AreEqual (ListSortDirection.Ascending, ((IBindingListView)view).SortDirection, "A3");
  320. Assert.AreEqual ("Name", ((IBindingListView)source).SortProperty.Name, "A4");
  321. Assert.AreEqual ("Name", ((IBindingListView)view).SortProperty.Name, "A5");
  322. Assert.AreEqual (1, ((IBindingListView)view).SortDescriptions.Count, "A6");
  323. Assert.AreEqual ("Name", ((IBindingListView)view).SortDescriptions [0].PropertyDescriptor.Name, "A7");
  324. Assert.AreEqual ("JPobst", view [0]["Name"], "A8");
  325. Assert.AreEqual ("Miguel", view [1]["Name"], "A9");
  326. Assert.AreEqual ("Mono", view [2]["Name"], "A10");
  327. //
  328. // Simple with direction (extra white spaces)
  329. //
  330. source.Sort = " Name DESC ";
  331. //Assert.AreEqual ("Name DESC", source.Sort, "B1");
  332. Assert.AreEqual (ListSortDirection.Descending, ((IBindingListView)view).SortDirection, "B2");
  333. Assert.AreEqual ("Name", ((IBindingListView)view).SortProperty.Name, "B3");
  334. Assert.AreEqual ("Mono", view [0]["Name"], "B4");
  335. Assert.AreEqual ("Miguel", view [1]["Name"], "B5");
  336. Assert.AreEqual ("JPobst", view [2]["Name"], "B6");
  337. //
  338. // Multiple
  339. //
  340. source.Sort = "Name DESC, Id asc";
  341. ListSortDescriptionCollection desc_coll = ((IBindingListView)view).SortDescriptions;
  342. Assert.AreEqual ("Name DESC, Id asc", source.Sort, "C1");
  343. Assert.AreEqual (2, desc_coll.Count, "C2");
  344. Assert.AreEqual (ListSortDirection.Descending, desc_coll [0].SortDirection, "C3");
  345. Assert.AreEqual ("Name", desc_coll [0].PropertyDescriptor.Name, "C4");
  346. Assert.AreEqual (ListSortDirection.Ascending, desc_coll [1].SortDirection, "C5");
  347. Assert.AreEqual ("Id", desc_coll [1].PropertyDescriptor.Name, "C6");
  348. }
  349. [Test]
  350. public void Sort_NonBindingList ()
  351. {
  352. BindingSource source = new BindingSource ();
  353. List<int> list = new List<int> (new int [] { 0, 1, 2, 3 });
  354. source.DataSource = list;
  355. Assert.AreEqual (null, source.Sort, "A1");
  356. try {
  357. source.Sort = "Name";
  358. Assert.Fail ("B1");
  359. } catch (ArgumentException) {
  360. }
  361. source.Sort = String.Empty;
  362. Assert.AreEqual (String.Empty, source.Sort, "C1");
  363. }
  364. [Test]
  365. public void Sort_Exceptions ()
  366. {
  367. BindingSource source = new BindingSource ();
  368. DataTable table = CreateTable ();
  369. source.DataSource = table;
  370. // Non-existant property
  371. try {
  372. source.Sort = "Name, DontExist DESC";
  373. Assert.Fail ("exc1");
  374. } catch (ArgumentException) {
  375. }
  376. // Wrong direction
  377. try {
  378. source.Sort = "Name WRONGDIR";
  379. Assert.Fail ("exc2");
  380. } catch (ArgumentException) {
  381. }
  382. // Wrong format
  383. try {
  384. source.Sort = "Name, , Id";
  385. Assert.Fail ("exc3");
  386. } catch (ArgumentException) {
  387. }
  388. }
  389. [Test]
  390. public void Movement ()
  391. {
  392. BindingSource source = new BindingSource ();
  393. source.DataSource = new WorkingEnumerable (5);
  394. int raised = 0;
  395. source.PositionChanged += delegate (object sender, EventArgs e) { raised ++; };
  396. Console.WriteLine ("count = {0}", source.Count);
  397. source.Position = 3;
  398. Assert.AreEqual (3, source.Position, "1");
  399. source.MoveFirst ();
  400. Assert.AreEqual (0, source.Position, "2");
  401. source.MoveNext ();
  402. Assert.AreEqual (1, source.Position, "3");
  403. source.MovePrevious ();
  404. Assert.AreEqual (0, source.Position, "4");
  405. source.MoveLast ();
  406. Assert.AreEqual (4, source.Position, "5");
  407. Assert.AreEqual (5, raised, "6");
  408. }
  409. [Test]
  410. public void Position ()
  411. {
  412. BindingSource source = new BindingSource ();
  413. CurrencyManager currency_manager = source.CurrencyManager;
  414. Assert.AreEqual (-1, source.Position, "A1");
  415. Assert.AreEqual (-1, currency_manager.Position, "A2");
  416. source.DataSource = new WorkingEnumerable (5);
  417. int raised = 0;
  418. int currency_raised = 0;
  419. source.PositionChanged += delegate (object sender, EventArgs e) { raised ++; };
  420. currency_manager.PositionChanged += delegate (object sender, EventArgs e) { currency_raised++; };
  421. Assert.AreEqual (0, source.Position, "B1");
  422. Assert.AreEqual (0, currency_manager.Position, "B2");
  423. source.Position = -1;
  424. Assert.AreEqual (0, source.Position, "C1");
  425. Assert.AreEqual (0, currency_manager.Position, "C2");
  426. Assert.AreEqual (0, raised, "C3");
  427. Assert.AreEqual (0, currency_raised, "C4");
  428. source.Position = 10;
  429. Assert.AreEqual (4, source.Position, "D1");
  430. Assert.AreEqual (4, currency_manager.Position, "D2");
  431. Assert.AreEqual (1, raised, "D3");
  432. Assert.AreEqual (1, currency_raised, "D4");
  433. source.Position = 10;
  434. Assert.AreEqual (4, source.Position, "E1");
  435. Assert.AreEqual (1, raised, "E2");
  436. // Now make some changes in CurrencyManager.Position, which should be visible
  437. // in BindingSource.Position
  438. currency_manager.Position = 0;
  439. Assert.AreEqual (0, source.Position, "F1");
  440. Assert.AreEqual (0, currency_manager.Position, "F2");
  441. Assert.AreEqual (2, raised, "F3");
  442. Assert.AreEqual (2, currency_raised, "F4");
  443. // Finally an etmpy collection
  444. source.DataSource = new List<int> ();
  445. Assert.AreEqual (-1, source.Position, "G1");
  446. Assert.AreEqual (-1, currency_manager.Position, "G2");
  447. }
  448. [Test]
  449. public void ResetCurrentItem ()
  450. {
  451. BindingSource source = new BindingSource ();
  452. bool delegate_reached = false;
  453. int old_index = 5;
  454. int new_index = 5;
  455. ListChangedType type = ListChangedType.Reset;
  456. source.DataSource = new WorkingEnumerable (5);
  457. source.Position = 2;
  458. source.ListChanged += delegate (object sender, ListChangedEventArgs e) {
  459. delegate_reached = true;
  460. type = e.ListChangedType;
  461. old_index = e.OldIndex;
  462. new_index = e.NewIndex;
  463. };
  464. source.ResetCurrentItem ();
  465. Assert.IsTrue (delegate_reached, "1");
  466. Assert.AreEqual (-1, old_index, "2");
  467. Assert.AreEqual (2, new_index, "3");
  468. Assert.AreEqual (ListChangedType.ItemChanged, type, "3");
  469. }
  470. [Test]
  471. public void Remove ()
  472. {
  473. BindingSource source = new BindingSource ();
  474. List<string> list = new List<string> ();
  475. list.Add ("A");
  476. source.DataSource = list;
  477. Assert.AreEqual (1, source.List.Count, "1");
  478. source.Remove ("A");
  479. Assert.AreEqual (0, list.Count, "2");
  480. // Different type, - no exception
  481. source.Remove (7);
  482. // Fixed size
  483. try {
  484. source.DataSource = new int [0];
  485. source.Remove (7);
  486. Assert.Fail ("exc1");
  487. } catch (NotSupportedException) {
  488. }
  489. // Read only
  490. try {
  491. source.DataSource = Array.AsReadOnly (new int [0]);
  492. source.Remove (7);
  493. Assert.Fail ("exc2");
  494. } catch (NotSupportedException) {
  495. }
  496. }
  497. [Test]
  498. public void RemoveCurrent ()
  499. {
  500. BindingSource source = new BindingSource ();
  501. List<string> list = new List<string> ();
  502. list.Add ("A");
  503. list.Add ("B");
  504. list.Add ("C");
  505. source.DataSource = list;
  506. source.Position = 1;
  507. Assert.AreEqual (1, source.Position, "A1");
  508. Assert.AreEqual ("B", source.Current, "A2");
  509. source.RemoveCurrent ();
  510. Assert.AreEqual (1, source.Position, "B1");
  511. Assert.AreEqual ("C", source.Current, "B2");
  512. Assert.AreEqual (2, source.Count, "B3");
  513. Assert.AreEqual ("A", source [0], "B4");
  514. Assert.AreEqual ("C", source [1], "B5");
  515. // Position is -1, since there are no items
  516. source.Clear ();
  517. try {
  518. source.RemoveCurrent ();
  519. Assert.Fail ("exc1");
  520. } catch (InvalidOperationException) {
  521. }
  522. source.DataSource = new int [1];
  523. try {
  524. source.RemoveCurrent ();
  525. Assert.Fail ("exc2");
  526. } catch (InvalidOperationException) {
  527. }
  528. }
  529. [Test]
  530. public void ResetBindings ()
  531. {
  532. BindingSource source;
  533. int event_count = 0;
  534. ListChangedType[] types = new ListChangedType[2];
  535. int[] old_index = new int[2];
  536. int[] new_index = new int[2];
  537. source = new BindingSource ();
  538. source.ListChanged += delegate (object sender, ListChangedEventArgs e) {
  539. types[event_count] = e.ListChangedType;
  540. old_index[event_count] = e.OldIndex;
  541. new_index[event_count] = e.NewIndex;
  542. event_count ++;
  543. };
  544. event_count = 0;
  545. source.ResetBindings (false);
  546. Assert.AreEqual (1, event_count, "1");
  547. Assert.AreEqual (ListChangedType.Reset, types[0], "2");
  548. Assert.AreEqual (-1, old_index[0], "3");
  549. Assert.AreEqual (-1, new_index[0], "4");
  550. event_count = 0;
  551. source.ResetBindings (true);
  552. Assert.AreEqual (2, event_count, "5");
  553. Assert.AreEqual (ListChangedType.PropertyDescriptorChanged, types[0], "6");
  554. Assert.AreEqual (0, old_index[0], "7");
  555. Assert.AreEqual (0, new_index[0], "8");
  556. Assert.AreEqual (ListChangedType.Reset, types[1], "9");
  557. Assert.AreEqual (-1, old_index[1], "10");
  558. Assert.AreEqual (-1, new_index[1], "11");
  559. }
  560. [Test]
  561. public void AllowEdit ()
  562. {
  563. BindingSource source = new BindingSource ();
  564. Assert.IsTrue (source.AllowEdit, "1");
  565. source.DataSource = "";
  566. Assert.IsTrue (source.AllowEdit, "2");
  567. source.DataSource = new int[10];
  568. Assert.IsTrue (source.AllowEdit, "3");
  569. source.DataSource = new WorkingEnumerable (5);
  570. Assert.IsTrue (source.AllowEdit, "4");
  571. ArrayList al = new ArrayList ();
  572. al.Add (5);
  573. source.DataSource = al;
  574. Assert.IsTrue (source.AllowEdit, "5");
  575. source.DataSource = ArrayList.ReadOnly (al);
  576. Assert.IsFalse (source.AllowEdit, "6");
  577. }
  578. [Test]
  579. public void AllowRemove ()
  580. {
  581. BindingSource source = new BindingSource ();
  582. Assert.IsTrue (source.AllowRemove, "1");
  583. source.DataSource = "";
  584. Assert.IsTrue (source.AllowRemove, "2");
  585. source.DataSource = new ArrayList ();
  586. Assert.IsTrue (source.AllowRemove, "3");
  587. source.DataSource = new int[10];
  588. Assert.IsFalse (source.AllowRemove, "4");
  589. source.DataSource = new WorkingEnumerable (5);
  590. Assert.IsTrue (source.AllowRemove, "5");
  591. }
  592. [Test]
  593. public void DataMember_ListRelationship ()
  594. {
  595. ListView lv = new ListView ();
  596. BindingSource source = new BindingSource ();
  597. // Empty IEnumerable, that also implements IList
  598. source.DataSource = lv.Items;
  599. source.DataMember = "Text";
  600. Assert.IsTrue (source.List is BindingList<string>, "1");
  601. Assert.AreEqual (0, source.List.Count, "2");
  602. }
  603. [Test]
  604. public void DataMemberNull ()
  605. {
  606. BindingSource source = new BindingSource ();
  607. Assert.AreEqual ("", source.DataMember, "1");
  608. source.DataMember = null;
  609. Assert.AreEqual ("", source.DataMember, "2");
  610. }
  611. [Test]
  612. public void DataSourceChanged ()
  613. {
  614. ArrayList list = new ArrayList ();
  615. BindingSource source = new BindingSource ();
  616. bool event_raised = false;
  617. source.DataSourceChanged += delegate (object sender, EventArgs e) {
  618. event_raised = true;
  619. };
  620. source.DataSource = list;
  621. Assert.IsTrue (event_raised, "1");
  622. event_raised = false;
  623. source.DataSource = list;
  624. Assert.IsFalse (event_raised, "2");
  625. }
  626. [Test]
  627. [ExpectedException (typeof (ArgumentException))] // DataMember property 'hi' cannot be found on the DataSource.
  628. public void DataMemberArgumentException ()
  629. {
  630. ArrayList list = new ArrayList ();
  631. BindingSource source = new BindingSource ();
  632. source.DataSource = list;
  633. source.DataMember = "hi";
  634. }
  635. [Test]
  636. public void DataMemberBeforeDataSource ()
  637. {
  638. ArrayList list = new ArrayList ();
  639. BindingSource source = new BindingSource ();
  640. source.DataMember = "hi";
  641. Assert.AreEqual ("hi", source.DataMember, "1");
  642. source.DataSource = list;
  643. Assert.AreEqual ("", source.DataMember, "2");
  644. }
  645. [Test]
  646. public void DataSourceAssignToDefaultType()
  647. {
  648. BindingSource source = new BindingSource ();
  649. source.DataMember = "hi";
  650. Assert.AreEqual ("hi", source.DataMember, "1");
  651. Assert.IsTrue (source.List is BindingList<object>, "2");
  652. source.DataSource = new BindingList<object>();
  653. Assert.AreEqual ("", source.DataMember, "3");
  654. }
  655. [Test]
  656. public void DataSourceSetType ()
  657. {
  658. BindingSource source = new BindingSource ();
  659. source.DataSource = typeof (DateTime);
  660. Assert.IsTrue (source.List is BindingList<DateTime>, "A1");
  661. Assert.AreEqual (0, source.List.Count, "A2");
  662. Assert.AreEqual (typeof (DateTime), source.DataSource);
  663. }
  664. [Test]
  665. public void DataMemberChanged ()
  666. {
  667. ArrayList list = new ArrayList ();
  668. BindingSource source = new BindingSource ();
  669. bool event_raised = false;
  670. list.Add ("hi"); // make the type System.String
  671. source.DataMemberChanged += delegate (object sender, EventArgs e) {
  672. event_raised = true;
  673. };
  674. source.DataSource = list;
  675. source.DataMember = "Length";
  676. Assert.IsTrue (event_raised, "1");
  677. event_raised = false;
  678. source.DataMember = "Length";
  679. Assert.IsFalse (event_raised, "2");
  680. }
  681. [Test]
  682. public void DataMemberNullDataSource ()
  683. {
  684. BindingSource source = new BindingSource ();
  685. source.Add ("hellou");
  686. source.DataMember = "SomeProperty"; // Should reset the list, even if data source is null
  687. Assert.IsTrue (source.List is BindingList<object>, "A1");
  688. Assert.AreEqual (0, source.List.Count, "A2");
  689. }
  690. [Test]
  691. public void SuppliedDataSource ()
  692. {
  693. List<string> list = new List<string>();
  694. BindingSource source;
  695. source = new BindingSource (list, "");
  696. Assert.IsTrue (source.List is List<string>, "1");
  697. source.DataMember = "Length";
  698. Assert.IsTrue (source.List is BindingList<int>, "2");
  699. source = new BindingSource (list, "Length");
  700. Assert.IsTrue (source.List is BindingList<int>, "3");
  701. }
  702. [Test]
  703. public void DataSourceMember_set ()
  704. {
  705. BindingSource source = new BindingSource ();
  706. source.DataSource = new List<string>();
  707. source.DataMember = "Length";
  708. Assert.IsNotNull (source.CurrencyManager, "1");
  709. source.DataSource = new List<string>();
  710. Assert.AreEqual ("Length", source.DataMember, "2");
  711. Assert.IsNotNull (source.CurrencyManager, "3");
  712. source.DataSource = new List<string[]>();
  713. Assert.AreEqual ("Length", source.DataMember, "4");
  714. Assert.IsNotNull (source.CurrencyManager, "5");
  715. }
  716. [Test]
  717. public void DataSourceMemberChangedEvents ()
  718. {
  719. BindingSource source = new BindingSource ();
  720. bool data_source_changed = false;
  721. bool data_member_changed = false;
  722. source.DataSourceChanged += delegate (object sender, EventArgs e) {
  723. data_source_changed = true;
  724. };
  725. source.DataMemberChanged += delegate (object sender, EventArgs e) {
  726. data_member_changed = true;
  727. };
  728. data_source_changed = false;
  729. data_member_changed = false;
  730. source.DataSource = new List<string>();
  731. Assert.IsTrue (data_source_changed, "1");
  732. Assert.IsFalse (data_member_changed, "2");
  733. data_source_changed = false;
  734. data_member_changed = false;
  735. source.DataMember = "Length";
  736. Assert.IsFalse (data_source_changed, "3");
  737. Assert.IsTrue (data_member_changed, "4");
  738. }
  739. [Test]
  740. public void IsBindingSuspended ()
  741. {
  742. BindingSource source = new BindingSource ();
  743. CurrencyManager currency_manager = source.CurrencyManager;
  744. source.DataSource = new object [1];
  745. source.SuspendBinding ();
  746. Assert.AreEqual (true, source.IsBindingSuspended, "A1");
  747. Assert.AreEqual (true, currency_manager.IsBindingSuspended, "A2");
  748. source.ResumeBinding ();
  749. Assert.AreEqual (false, source.IsBindingSuspended, "B1");
  750. Assert.AreEqual (false, currency_manager.IsBindingSuspended, "B2");
  751. // Changes made to CurrencyManager should be visible in BindingSource
  752. currency_manager.SuspendBinding ();
  753. Assert.AreEqual (true, source.IsBindingSuspended, "C1");
  754. Assert.AreEqual (true, currency_manager.IsBindingSuspended, "C2");
  755. currency_manager.ResumeBinding ();
  756. Assert.AreEqual (false, source.IsBindingSuspended, "D1");
  757. Assert.AreEqual (false, currency_manager.IsBindingSuspended, "D2");
  758. }
  759. [Test]
  760. public void Add ()
  761. {
  762. BindingSource source = new BindingSource ();
  763. source.DataSource = new List<string> ();
  764. source.Add ("A");
  765. Assert.AreEqual (1, source.List.Count, "2");
  766. // Different item type
  767. try {
  768. source.Add (4);
  769. Assert.Fail ("exc1");
  770. } catch (InvalidOperationException) {
  771. }
  772. // FixedSize
  773. try {
  774. source.DataSource = new int [0];
  775. source.Add (7);
  776. Assert.Fail ("exc2");
  777. } catch (NotSupportedException) {
  778. }
  779. // ReadOnly
  780. try {
  781. source.DataSource = Array.AsReadOnly (new int [0]);
  782. source.Add (7);
  783. Assert.Fail ("exc3");
  784. } catch (NotSupportedException) {
  785. }
  786. }
  787. [Test]
  788. public void Add_NullDataSource ()
  789. {
  790. BindingSource source = new BindingSource ();
  791. source.Add ("A");
  792. Assert.AreEqual (1, source.List.Count, "1");
  793. Assert.IsTrue (source.List is BindingList<string>, "2");
  794. Assert.IsNull (source.DataSource, "3");
  795. source = new BindingSource ();
  796. source.Add (null);
  797. Assert.IsTrue (source.List is BindingList<object>, "4");
  798. Assert.AreEqual (1, source.List.Count, "5");
  799. }
  800. [Test]
  801. public void AddNew ()
  802. {
  803. BindingSource source = new BindingSource ();
  804. source.AddNew ();
  805. Assert.AreEqual (1, source.Count, "1");
  806. }
  807. [Test]
  808. public void AddNew_NonBindingList ()
  809. {
  810. IList list = new List<object> ();
  811. BindingSource source = new BindingSource ();
  812. source.DataSource = list;
  813. Assert.IsTrue (source.List is List<object>, "1");
  814. source.AddNew ();
  815. Assert.AreEqual (1, source.Count, "2");
  816. }
  817. [Test]
  818. public void ApplySort ()
  819. {
  820. BindingSource source = new BindingSource ();
  821. DataTable table = CreateTable ();
  822. source.DataSource = table;
  823. IBindingListView source_view = ((IBindingListView)source);
  824. IBindingListView view = ((IBindingListView)source.List);
  825. PropertyDescriptor property = source.GetItemProperties (null) ["Name"];
  826. source_view.ApplySort (property, ListSortDirection.Ascending);
  827. Assert.AreEqual (property, view.SortProperty, "A1");
  828. // Non IBindingList source - Passing an invalid property
  829. // but the method is not called since source is not of the required type
  830. source.DataSource = new List<string> ();
  831. try {
  832. source_view.ApplySort (property, ListSortDirection.Ascending);
  833. Assert.Fail ("B1");
  834. } catch (NotSupportedException) {
  835. }
  836. }
  837. [Test]
  838. public void AllowNew_getter ()
  839. {
  840. BindingSource source = new BindingSource ();
  841. // true because the default datasource is BindingList<object>
  842. Assert.IsTrue (source.AllowNew, "1");
  843. source.DataSource = new object[10];
  844. // fixed size
  845. Assert.IsFalse (source.AllowNew, "2");
  846. source.DataSource = new BindingList<string>();
  847. // no default ctor
  848. Assert.IsFalse (source.AllowNew, "3");
  849. }
  850. [Test]
  851. public void AllowNew ()
  852. {
  853. BindingSource source = new BindingSource ();
  854. source.AllowNew = false;
  855. Assert.IsFalse (source.AllowNew, "1");
  856. source.ResetAllowNew ();
  857. Assert.IsTrue (source.AllowNew, "2");
  858. }
  859. [Test]
  860. [ExpectedException (typeof (InvalidOperationException))]
  861. // "AllowNew can only be set to true on an
  862. // IBindingList or on a read-write list with a default
  863. // public constructor."
  864. public void AllowNew_FixedSize ()
  865. {
  866. BindingSource source = new BindingSource ();
  867. source.DataSource = new object[10];
  868. source.AllowNew = true;
  869. }
  870. #if false
  871. // According to the MS docs, this should fail with a MissingMethodException
  872. [Test]
  873. public void AllowNew_NoDefaultCtor ()
  874. {
  875. List<string> s = new List<string>();
  876. s.Add ("hi");
  877. BindingSource source = new BindingSource ();
  878. source.DataSource = s;
  879. source.AllowNew = true;
  880. Assert.Fail ();
  881. }
  882. #endif
  883. [Test]
  884. [ExpectedException (typeof (InvalidOperationException))]
  885. // "Item cannot be added to a read-only or fixed-size list."
  886. public void AddNew_BindingListWithoutAllowNew ()
  887. {
  888. BindingList<int> l = new BindingList<int>();
  889. l.AllowNew = false;
  890. BindingSource source = new BindingSource ();
  891. source.DataSource = l;
  892. source.AddNew ();
  893. Assert.AreEqual (1, source.Count, "1");
  894. }
  895. [Test]
  896. [ExpectedException (typeof (InvalidOperationException))]
  897. // "Item cannot be added to a read-only or fixed-size list."
  898. public void AddNew_FixedSize ()
  899. {
  900. BindingSource source = new BindingSource ();
  901. source.DataSource = new int[5];
  902. object o = source.AddNew ();
  903. Assert.IsTrue (o is int, "1");
  904. Assert.AreEqual (6, source.Count, "2");
  905. }
  906. class ReadOnlyList : List<int>, IList {
  907. public int Add (object value) {
  908. throw new Exception ();
  909. }
  910. public bool Contains (object value) {
  911. throw new Exception ();
  912. }
  913. public int IndexOf (object value) {
  914. throw new Exception ();
  915. }
  916. public void Insert (int index, object value) {
  917. throw new Exception ();
  918. }
  919. public void Remove (object value) {
  920. throw new Exception ();
  921. }
  922. public bool IsFixedSize {
  923. get { return false; }
  924. }
  925. public bool IsReadOnly {
  926. get { return true; }
  927. }
  928. }
  929. [Test]
  930. [ExpectedException (typeof (InvalidOperationException))]
  931. // "Item cannot be added to a read-only or fixed-size list."
  932. public void AddNew_ReadOnly ()
  933. {
  934. BindingSource source = new BindingSource ();
  935. source.DataSource = new ReadOnlyList ();
  936. object o = source.AddNew ();
  937. TestHelper.RemoveWarning (o);
  938. }
  939. [Test]
  940. [ExpectedException (typeof (InvalidOperationException))]
  941. // "AddNew cannot be called on the 'System.String' type. This type does not have a public default constructor. You can call AddNew on the 'System.String' type if you set AllowNew=true and handle the AddingNew event."
  942. public void AddNew_Invalid ()
  943. {
  944. BindingSource source = new BindingSource ();
  945. source.DataSource = new List<string>();
  946. object o = source.AddNew ();
  947. TestHelper.RemoveWarning (o);
  948. }
  949. [Test]
  950. public void AddingNew ()
  951. {
  952. // Need to use a class missing a default .ctor
  953. BindingSource source = new BindingSource ();
  954. List<DateTime> list = new List<DateTime> ();
  955. source.DataSource = list;
  956. Assert.AreEqual (false, source.AllowNew, "A1");
  957. source.AllowNew = true;
  958. source.AddingNew += delegate (object o, AddingNewEventArgs args)
  959. {
  960. args.NewObject = DateTime.Now;
  961. };
  962. source.AddNew ();
  963. Assert.AreEqual (1, source.Count, "A1");
  964. }
  965. [Test]
  966. public void AddingNew_Exceptions ()
  967. {
  968. BindingSource source = new BindingSource ();
  969. List<DateTime> list = new List<DateTime> ();
  970. source.DataSource = list;
  971. Assert.AreEqual (false, source.AllowNew, "A1");
  972. source.AllowNew = true;
  973. // No handler for AddingNew
  974. try {
  975. source.AddNew ();
  976. Assert.Fail ("exc1");
  977. } catch (InvalidOperationException) {
  978. }
  979. // Adding new handled, but AddingNew is false
  980. source.AllowNew = false;
  981. source.AddingNew += delegate (object o, AddingNewEventArgs args)
  982. {
  983. args.NewObject = DateTime.Now;
  984. };
  985. try {
  986. source.AddNew ();
  987. Assert.Fail ("exc2");
  988. } catch (InvalidOperationException) {
  989. }
  990. // Wrong type
  991. source = new BindingSource ();
  992. source.DataSource = new List<string> ();
  993. source.AllowNew = true;
  994. source.AddingNew += delegate (object o, AddingNewEventArgs args)
  995. {
  996. args.NewObject = 3.1416;
  997. };
  998. try {
  999. source.AddNew ();
  1000. Assert.Fail ("exc3");
  1001. } catch (InvalidOperationException) {
  1002. }
  1003. // Null value
  1004. source = new BindingSource ();
  1005. source.DataSource = new List<string> ();
  1006. source.AllowNew = true;
  1007. source.AddingNew += delegate (object o, AddingNewEventArgs args)
  1008. {
  1009. args.NewObject = null;
  1010. };
  1011. try {
  1012. source.AddNew ();
  1013. Assert.Fail ("exc4");
  1014. } catch (InvalidOperationException) {
  1015. }
  1016. }
  1017. [Test]
  1018. public void BindingSuspended1 ()
  1019. {
  1020. // Empty collection as datasource means CurrencyManager will remain
  1021. // as suspended
  1022. BindingSource source = new BindingSource ();
  1023. source.DataSource = new List<string>();
  1024. Assert.IsTrue (source.IsBindingSuspended, "1");
  1025. source.SuspendBinding ();
  1026. Assert.IsTrue (source.IsBindingSuspended, "2");
  1027. source.ResumeBinding ();
  1028. Assert.IsTrue (source.IsBindingSuspended, "3");
  1029. source.ResumeBinding ();
  1030. Assert.IsTrue (source.IsBindingSuspended, "4");
  1031. }
  1032. [Test]
  1033. public void ICancelAddNew ()
  1034. {
  1035. BindingSource source = new BindingSource ();
  1036. source.DataSource = new List<string> ();
  1037. source.AddingNew += delegate (object o, AddingNewEventArgs args) { args.NewObject = "A"; };
  1038. source.AllowNew = true;
  1039. // CancelNew
  1040. source.AddNew ();
  1041. Assert.AreEqual (1, source.Count, "A1");
  1042. Assert.AreEqual ("A", source [0], "A2");
  1043. ((ICancelAddNew)source).CancelNew (0);
  1044. Assert.AreEqual (0, source.Count, "A3");
  1045. // EndNew
  1046. source.AddNew ();
  1047. ((ICancelAddNew)source).EndNew (0);
  1048. ((ICancelAddNew)source).CancelNew (0);
  1049. Assert.AreEqual (1, source.Count, "B1");
  1050. Assert.AreEqual ("A", source [0], "B2");
  1051. //
  1052. // Access operations are suppoused to automatically
  1053. // call EndNew, but that only happens with AddNew
  1054. //
  1055. // AddNew
  1056. source.Clear ();
  1057. source.AddNew ();
  1058. source.AddNew ();
  1059. ((ICancelAddNew)source).CancelNew (0);
  1060. Assert.AreEqual (2, source.Count, "C1");
  1061. Assert.AreEqual ("A", source [0], "C2");
  1062. Assert.AreEqual ("A", source [1], "C3");
  1063. // Add - Does not call EndNew
  1064. source.Clear ();
  1065. source.AddNew ();
  1066. source.Add ("B");
  1067. ((ICancelAddNew)source).CancelNew (0);
  1068. Assert.AreEqual (1, source.Count, "D1");
  1069. Assert.AreEqual ("B", source [0], "D2");
  1070. // Remove - Does not neither
  1071. source.Clear ();
  1072. source.AddNew ();
  1073. source.Add ("B");
  1074. source.Remove ("B");
  1075. ((ICancelAddNew)source).CancelNew (0);
  1076. Assert.AreEqual (0, source.Count, "E1");
  1077. // Wrong index param passed to CancelNew
  1078. source.Clear ();
  1079. source.AddNew ();
  1080. source.Add ("B");
  1081. ((ICancelAddNew)source).CancelNew (1); // Should pass 0
  1082. Assert.AreEqual (2, source.Count, "F1");
  1083. // Multiple pending items - Only takes into account the last one
  1084. source.Clear ();
  1085. source.AddNew ();
  1086. source.AddNew ();
  1087. ((ICancelAddNew)source).CancelNew (1);
  1088. ((ICancelAddNew)source).CancelNew (0);
  1089. Assert.AreEqual (1, source.Count, "G1");
  1090. // Bug?
  1091. source.Clear ();
  1092. source.AddNew ();
  1093. source.Add ("B");
  1094. source.RemoveAt (0); // Added with AddNew
  1095. ((ICancelAddNew)source).CancelNew (0); // Removed item that wasn't added with AddNew
  1096. Assert.AreEqual (0, source.Count, "H1");
  1097. }
  1098. [Test]
  1099. public void Clear ()
  1100. {
  1101. BindingSource source = new BindingSource ();
  1102. List<string> list = new List<string> ();
  1103. list.Add ("A");
  1104. list.Add ("B");
  1105. source.DataSource = list;
  1106. source.Clear ();
  1107. Assert.AreEqual (0, source.List.Count, "1");
  1108. Assert.IsTrue (source.List is List<string>, "2");
  1109. // Exception only for ReadOnly, not for fixed size
  1110. source.DataSource = new int [0];
  1111. source.Clear ();
  1112. try {
  1113. source.DataSource = Array.AsReadOnly (new int [0]);
  1114. source.Clear ();
  1115. Assert.Fail ("exc1");
  1116. } catch (NotSupportedException) {
  1117. }
  1118. }
  1119. [Test]
  1120. public void Clear_NullDataSource ()
  1121. {
  1122. BindingSource source = new BindingSource ();
  1123. source.Add ("A");
  1124. Assert.AreEqual (1, source.List.Count, "1");
  1125. Assert.IsTrue (source.List is BindingList<string>, "2");
  1126. Assert.IsNull (source.DataSource, "3");
  1127. source.Clear ();
  1128. Assert.AreEqual (0, source.List.Count, "4");
  1129. Assert.IsTrue (source.List is BindingList<string>, "5");
  1130. // Change list item type after clearing
  1131. source.Add (7);
  1132. Assert.AreEqual (1, source.List.Count, "6");
  1133. Assert.IsTrue (source.List is BindingList<int>, "7");
  1134. }
  1135. [Test]
  1136. public void CurrencyManager ()
  1137. {
  1138. BindingSource source = new BindingSource ();
  1139. CurrencyManager curr_manager;
  1140. //
  1141. // Null data source
  1142. //
  1143. curr_manager = source.CurrencyManager;
  1144. Assert.IsTrue (curr_manager != null, "A1");
  1145. Assert.IsTrue (curr_manager.List != null, "A2");
  1146. Assert.IsTrue (curr_manager.List is BindingSource, "A3");
  1147. Assert.AreEqual (0, curr_manager.List.Count, "A4");
  1148. Assert.AreEqual (0, curr_manager.Count, "A5");
  1149. Assert.AreEqual (-1, curr_manager.Position, "A6");
  1150. Assert.IsTrue (curr_manager.Bindings != null, "A7");
  1151. Assert.AreEqual (0, curr_manager.Bindings.Count, "A8");
  1152. Assert.AreEqual (source, curr_manager.List, "A9");
  1153. //
  1154. // Non null data source
  1155. //
  1156. List<string> list = new List<string> ();
  1157. list.Add ("A");
  1158. list.Add ("B");
  1159. source.DataSource = list;
  1160. curr_manager = source.CurrencyManager;
  1161. Assert.IsTrue (curr_manager != null, "B1");
  1162. Assert.IsTrue (curr_manager.List != null, "B2");
  1163. Assert.IsTrue (curr_manager.List is BindingSource, "B3");
  1164. Assert.AreEqual (2, curr_manager.List.Count, "B4");
  1165. Assert.AreEqual (2, curr_manager.Count, "B5");
  1166. Assert.AreEqual (0, curr_manager.Position, "B6");
  1167. Assert.IsTrue (curr_manager.Bindings != null, "B7");
  1168. Assert.AreEqual (0, curr_manager.Bindings.Count, "B8");
  1169. Assert.AreEqual (source, curr_manager.List, "B9");
  1170. curr_manager.Position = source.Count - 1;
  1171. Assert.AreEqual (1, curr_manager.Position, "C1");
  1172. Assert.AreEqual ("B", curr_manager.Current, "C2");
  1173. Assert.AreEqual (1, source.Position, "C3");
  1174. Assert.AreEqual ("B", source.Current, "C4");
  1175. }
  1176. [Test]
  1177. public void GetRelatedCurrencyManagerList ()
  1178. {
  1179. ListView lv = new ListView ();
  1180. lv.Columns.Add ("A");
  1181. BindingSource source = new BindingSource ();
  1182. source.DataSource = lv;
  1183. CurrencyManager cm = source.GetRelatedCurrencyManager ("Columns");
  1184. BindingSource related_source = (BindingSource)cm.List;
  1185. Assert.AreEqual (1, cm.Count, "A1");
  1186. Assert.AreEqual (1, related_source.Count, "A2");
  1187. Assert.AreEqual ("Columns", related_source.DataMember, "A3");
  1188. Assert.AreSame (source, related_source.DataSource, "A4");
  1189. Assert.IsTrue (related_source.List is ListView.ColumnHeaderCollection, "A5");
  1190. Assert.AreSame (cm, source.GetRelatedCurrencyManager ("Columns"), "A6");
  1191. // A path string returns null
  1192. cm = source.GetRelatedCurrencyManager ("Columns.Count");
  1193. Assert.IsNull (cm, "B1");
  1194. // String.Empty and null
  1195. Assert.AreSame (source.CurrencyManager, source.GetRelatedCurrencyManager (String.Empty), "C1");
  1196. Assert.AreSame (source.CurrencyManager, source.GetRelatedCurrencyManager (null), "C2");
  1197. }
  1198. [Test]
  1199. public void GetRelatedCurrencyManagerObject ()
  1200. {
  1201. BindingSource source = new BindingSource ();
  1202. ListViewItem item = new ListViewItem ();
  1203. source.DataSource = item;
  1204. CurrencyManager font_cm = source.GetRelatedCurrencyManager ("Font");
  1205. CurrencyManager name_cm = source.GetRelatedCurrencyManager ("Font.Name");
  1206. Assert.IsNull (name_cm, "A1");
  1207. }
  1208. class BindingListViewPoker : BindingList<string>, IBindingListView
  1209. {
  1210. public bool supports_filter;
  1211. public bool supports_advanced_sorting;
  1212. public string Filter {
  1213. get { return ""; }
  1214. set { }
  1215. }
  1216. public ListSortDescriptionCollection SortDescriptions {
  1217. get { return null; }
  1218. }
  1219. public bool SupportsAdvancedSorting {
  1220. get { return supports_advanced_sorting; }
  1221. }
  1222. public bool SupportsFiltering {
  1223. get { return supports_filter; }
  1224. }
  1225. public void ApplySort (ListSortDescriptionCollection sorts)
  1226. {
  1227. }
  1228. public void RemoveFilter ()
  1229. {
  1230. }
  1231. }
  1232. [Test]
  1233. public void SupportsFilter ()
  1234. {
  1235. BindingListViewPoker c = new BindingListViewPoker ();
  1236. BindingSource source = new BindingSource ();
  1237. // because the default list is a BindingList<object>
  1238. Assert.IsFalse (source.SupportsFiltering, "1");
  1239. source.DataSource = c;
  1240. // the DataSource is IBindingListView, but
  1241. // SupportsFilter is false.
  1242. Assert.IsFalse (source.SupportsFiltering, "2");
  1243. c.supports_filter = true;
  1244. Assert.IsTrue (source.SupportsFiltering, "3");
  1245. }
  1246. [Test]
  1247. public void SupportsAdvancedSorting ()
  1248. {
  1249. BindingListViewPoker c = new BindingListViewPoker ();
  1250. BindingSource source = new BindingSource ();
  1251. // because the default list is a BindingList<object>
  1252. Assert.IsFalse (source.SupportsAdvancedSorting, "1");
  1253. source.DataSource = c;
  1254. // the DataSource is IBindingListView, but
  1255. // SupportsAdvancedSorting is false.
  1256. Assert.IsFalse (source.SupportsAdvancedSorting, "2");
  1257. c.supports_advanced_sorting = true;
  1258. Assert.IsTrue (source.SupportsAdvancedSorting, "3");
  1259. }
  1260. class IBindingListPoker : BindingList<string>, IBindingList {
  1261. public void AddIndex (PropertyDescriptor property)
  1262. {
  1263. }
  1264. public void ApplySort (PropertyDescriptor property, ListSortDirection direction)
  1265. {
  1266. }
  1267. public int Find (PropertyDescriptor property, object key)
  1268. {
  1269. throw new NotImplementedException ();
  1270. }
  1271. public void RemoveIndex (PropertyDescriptor property)
  1272. {
  1273. }
  1274. public void RemoveSort ()
  1275. {
  1276. }
  1277. public bool IsSorted {
  1278. get { throw new NotImplementedException (); }
  1279. }
  1280. public ListSortDirection SortDirection {
  1281. get { throw new NotImplementedException (); }
  1282. }
  1283. public PropertyDescriptor SortProperty {
  1284. get { throw new NotImplementedException (); }
  1285. }
  1286. public bool SupportsChangeNotification {
  1287. get { return supports_change_notification; }
  1288. }
  1289. public bool SupportsSearching {
  1290. get { return supports_searching; }
  1291. }
  1292. public bool SupportsSorting {
  1293. get { return supports_sorting; }
  1294. }
  1295. public bool supports_change_notification;
  1296. public bool supports_searching;
  1297. public bool supports_sorting;
  1298. }
  1299. [Test]
  1300. public void SupportsSearching ()
  1301. {
  1302. IBindingListPoker c = new IBindingListPoker ();
  1303. BindingSource source = new BindingSource ();
  1304. // because the default list is a BindingList<object>
  1305. Assert.IsFalse (source.SupportsSearching, "1");
  1306. source.DataSource = c;
  1307. // the DataSource is IBindingList, but
  1308. // SupportsSearching is false.
  1309. Assert.IsFalse (source.SupportsSearching, "2");
  1310. c.supports_searching = true;
  1311. Console.WriteLine ("set c.supports_searching to {0}, so c.SupportsSearching = {1}",
  1312. c.supports_searching, c.SupportsSearching);
  1313. Assert.IsTrue (source.SupportsSearching, "3");
  1314. }
  1315. [Test]
  1316. public void SupportsSorting ()
  1317. {
  1318. IBindingListPoker c = new IBindingListPoker ();
  1319. BindingSource source = new BindingSource ();
  1320. // because the default list is a BindingList<object>
  1321. Assert.IsFalse (source.SupportsSorting, "1");
  1322. source.DataSource = c;
  1323. // the DataSource is IBindingList, but
  1324. // SupportsSorting is false.
  1325. Assert.IsFalse (source.SupportsSorting, "2");
  1326. c.supports_sorting = true;
  1327. Assert.IsTrue (source.SupportsSorting, "3");
  1328. }
  1329. [Test]
  1330. public void SupportsChangeNotification ()
  1331. {
  1332. IBindingListPoker c = new IBindingListPoker ();
  1333. BindingSource source = new BindingSource ();
  1334. // because the default list is a BindingList<object>
  1335. Assert.IsTrue (source.SupportsChangeNotification, "1");
  1336. source.DataSource = c;
  1337. // the DataSource is IBindingList, but
  1338. // SupportsChangeNotification is false.
  1339. Assert.IsTrue (source.SupportsChangeNotification, "2");
  1340. c.supports_change_notification = true;
  1341. Assert.IsTrue (source.SupportsChangeNotification, "3");
  1342. }
  1343. [Test]
  1344. public void ISupportInitializeNotification ()
  1345. {
  1346. BindingSource source = new BindingSource ();
  1347. List<string> list = new List<string> ();
  1348. bool initialized_handled = false;
  1349. ISupportInitializeNotification inotification = (ISupportInitializeNotification)source;
  1350. inotification.Initialized += delegate { initialized_handled = true; };
  1351. Assert.AreEqual (true, inotification.IsInitialized, "A1");
  1352. Assert.AreEqual (false, initialized_handled, "A2");
  1353. inotification.BeginInit ();
  1354. Assert.AreEqual (false, inotification.IsInitialized, "B1");
  1355. Assert.AreEqual (false, initialized_handled, "B2");
  1356. source.DataSource = list;
  1357. Assert.AreEqual (list, source.DataSource, "C1");
  1358. Assert.AreEqual (false, initialized_handled, "C2");
  1359. inotification.EndInit ();
  1360. Assert.AreEqual (true, inotification.IsInitialized, "D1");
  1361. Assert.AreEqual (true, initialized_handled, "D2");
  1362. // Reset event info
  1363. initialized_handled = false;
  1364. inotification.EndInit ();
  1365. Assert.AreEqual (true, initialized_handled, "E1");
  1366. //
  1367. // Case 2: use a data source that implements ISupportsInitializeNotification
  1368. //
  1369. InitializableObject init_obj = new InitializableObject ();
  1370. init_obj.BeginInit ();
  1371. source.DataSource = null;
  1372. inotification.BeginInit ();
  1373. initialized_handled = false;
  1374. source.DataSource = init_obj;
  1375. Assert.AreEqual (false, inotification.IsInitialized, "G1");
  1376. Assert.AreEqual (false, initialized_handled, "G2");
  1377. Assert.AreEqual (false, init_obj.IsInitialized, "G3");
  1378. Assert.AreEqual (init_obj, source.DataSource, "G4");
  1379. Assert.IsTrue (source.List is BindingList<object>, "G5"); // Default list
  1380. inotification.EndInit ();
  1381. Assert.AreEqual (false, inotification.IsInitialized, "H1");
  1382. Assert.AreEqual (false, initialized_handled, "H2");
  1383. Assert.AreEqual (false, init_obj.IsInitialized, "H3");
  1384. init_obj.EndInit ();
  1385. Assert.AreEqual (true, inotification.IsInitialized, "J1");
  1386. Assert.AreEqual (true, initialized_handled, "J2");
  1387. Assert.AreEqual (true, init_obj.IsInitialized, "J3");
  1388. Assert.IsTrue (source.List is BindingList<InitializableObject>, "K");
  1389. // Call again EndInit on datasource, which should *not* cause a
  1390. // EndInit call in BindingSource, since it is already initialized
  1391. initialized_handled = false;
  1392. init_obj.EndInit ();
  1393. Assert.AreEqual (false, initialized_handled, "L");
  1394. }
  1395. class InitializableObject : ISupportInitializeNotification
  1396. {
  1397. bool is_initialized = true;
  1398. public void BeginInit ()
  1399. {
  1400. is_initialized = false;
  1401. }
  1402. public void EndInit ()
  1403. {
  1404. is_initialized = true;
  1405. if (Initialized != null)
  1406. Initialized (this, EventArgs.Empty);
  1407. }
  1408. public bool IsInitialized {
  1409. get {
  1410. return is_initialized;
  1411. }
  1412. }
  1413. public event EventHandler Initialized;
  1414. }
  1415. //
  1416. // Events section
  1417. //
  1418. int iblist_raised;
  1419. int ilist_raised;
  1420. ListChangedEventArgs iblist_changed_args;
  1421. ListChangedEventArgs ilist_changed_args;
  1422. BindingSource iblist_source;
  1423. BindingSource ilist_source;
  1424. void ResetEventsInfo ()
  1425. {
  1426. iblist_raised = ilist_raised = 0;
  1427. iblist_source = new BindingSource ();
  1428. ilist_source = new BindingSource ();
  1429. iblist_source.ListChanged += delegate (object o, ListChangedEventArgs e)
  1430. {
  1431. iblist_raised++;
  1432. iblist_changed_args = e;
  1433. };
  1434. ilist_source.ListChanged += delegate (object o, ListChangedEventArgs e)
  1435. {
  1436. ilist_raised++;
  1437. ilist_changed_args = e;
  1438. };
  1439. }
  1440. [Test]
  1441. public void ListChanged_DataSourceSet ()
  1442. {
  1443. IBindingList bindinglist = new BindingList<string> ();
  1444. bindinglist.Add ("A");
  1445. IList arraylist = new ArrayList (bindinglist);
  1446. ResetEventsInfo ();
  1447. iblist_source.DataSource = bindinglist;
  1448. ilist_source.DataSource = arraylist;
  1449. Assert.AreEqual (2, iblist_raised, "A1");
  1450. Assert.AreEqual (2, ilist_raised, "A2");
  1451. Assert.AreEqual (ListChangedType.Reset, iblist_changed_args.ListChangedType, "A3");
  1452. Assert.AreEqual (ListChangedType.Reset, ilist_changed_args.ListChangedType, "A4");
  1453. Assert.AreEqual (-1, iblist_changed_args.NewIndex, "A5");
  1454. Assert.AreEqual (-1, ilist_changed_args.NewIndex, "A6");
  1455. }
  1456. [Test]
  1457. public void ListChanged_ItemAdded ()
  1458. {
  1459. IBindingList bindinglist = new BindingList<string> ();
  1460. bindinglist.Add ("A");
  1461. IList arraylist = new ArrayList (bindinglist);
  1462. ResetEventsInfo ();
  1463. iblist_source.DataSource = bindinglist;
  1464. ilist_source.DataSource = arraylist;
  1465. // Clear after setting DataSource generated some info
  1466. iblist_raised = ilist_raised = 0;
  1467. iblist_changed_args = ilist_changed_args = null;
  1468. iblist_source.Add ("B");
  1469. ilist_source.Add ("B");
  1470. Assert.AreEqual (1, iblist_raised, "A1");
  1471. Assert.AreEqual (1, ilist_raised, "A2");
  1472. Assert.AreEqual (ListChangedType.ItemAdded, iblist_changed_args.ListChangedType, "A3");
  1473. Assert.AreEqual (ListChangedType.ItemAdded, ilist_changed_args.ListChangedType, "A4");
  1474. Assert.AreEqual (1, iblist_changed_args.NewIndex, "A5");
  1475. Assert.AreEqual (1, ilist_changed_args.NewIndex, "A6");
  1476. iblist_raised = ilist_raised = 0;
  1477. iblist_changed_args = ilist_changed_args = null;
  1478. iblist_source.Insert (0, "C");
  1479. ilist_source.Insert (0, "C");
  1480. Assert.AreEqual (1, iblist_raised, "B1");
  1481. Assert.AreEqual (1, ilist_raised, "B2");
  1482. Assert.AreEqual (ListChangedType.ItemAdded, iblist_changed_args.ListChangedType, "B3");
  1483. Assert.AreEqual (ListChangedType.ItemAdded, ilist_changed_args.ListChangedType, "B4");
  1484. Assert.AreEqual (0, iblist_changed_args.NewIndex, "B5");
  1485. Assert.AreEqual (0, ilist_changed_args.NewIndex, "B6");
  1486. // AddNew
  1487. iblist_source.AddingNew += delegate (object o, AddingNewEventArgs e) { e.NewObject = "Z"; };
  1488. ilist_source.AddingNew += delegate (object o, AddingNewEventArgs e) { e.NewObject = "Z"; };
  1489. iblist_source.AllowNew = true;
  1490. ilist_source.AllowNew = true;
  1491. iblist_raised = ilist_raised = 0;
  1492. iblist_changed_args = ilist_changed_args = null;
  1493. iblist_source.AddNew ();
  1494. ilist_source.AddNew ();
  1495. Assert.AreEqual (1, iblist_raised, "C1");
  1496. Assert.AreEqual (1, ilist_raised, "C2");
  1497. Assert.AreEqual (ListChangedType.ItemAdded, iblist_changed_args.ListChangedType, "C3");
  1498. Assert.AreEqual (ListChangedType.ItemAdded, ilist_changed_args.ListChangedType, "C4");
  1499. Assert.AreEqual (3, iblist_changed_args.NewIndex, "C5");
  1500. Assert.AreEqual (3, ilist_changed_args.NewIndex, "C6");
  1501. iblist_raised = ilist_raised = 0;
  1502. iblist_changed_args = ilist_changed_args = null;
  1503. // This only applies to IBindingList - Direct access, not through BindingSource
  1504. bindinglist.Add ("D");
  1505. Assert.AreEqual (1, iblist_raised, "D1");
  1506. Assert.AreEqual (ListChangedType.ItemAdded, iblist_changed_args.ListChangedType, "D2");
  1507. Assert.AreEqual (4, iblist_changed_args.NewIndex, "D3");
  1508. }
  1509. [Test]
  1510. public void ListChanged_ItemDeleted ()
  1511. {
  1512. IBindingList bindinglist = new BindingList<string> ();
  1513. bindinglist.Add ("A");
  1514. bindinglist.Add ("B");
  1515. bindinglist.Add ("C");
  1516. IList arraylist = new ArrayList (bindinglist);
  1517. ResetEventsInfo ();
  1518. iblist_source.DataSource = bindinglist;
  1519. ilist_source.DataSource = arraylist;
  1520. // Clear after setting DataSource generated some info
  1521. iblist_raised = ilist_raised = 0;
  1522. iblist_changed_args = ilist_changed_args = null;
  1523. iblist_source.RemoveAt (2);
  1524. ilist_source.RemoveAt (2);
  1525. Assert.AreEqual (1, iblist_raised, "A1");
  1526. Assert.AreEqual (1, ilist_raised, "A2");
  1527. Assert.AreEqual (ListChangedType.ItemDeleted, iblist_changed_args.ListChangedType, "A3");
  1528. Assert.AreEqual (ListChangedType.ItemDeleted, ilist_changed_args.ListChangedType, "A4");
  1529. Assert.AreEqual (2, iblist_changed_args.NewIndex, "A5");
  1530. Assert.AreEqual (2, ilist_changed_args.NewIndex, "A6");
  1531. iblist_raised = ilist_raised = 0;
  1532. iblist_changed_args = ilist_changed_args = null;
  1533. iblist_source.Remove ("A");
  1534. ilist_source.Remove ("A");
  1535. Assert.AreEqual (1, iblist_raised, "B1");
  1536. Assert.AreEqual (1, ilist_raised, "B2");
  1537. Assert.AreEqual (ListChangedType.ItemDeleted, iblist_changed_args.ListChangedType, "B3");
  1538. Assert.AreEqual (ListChangedType.ItemDeleted, ilist_changed_args.ListChangedType, "B4");
  1539. Assert.AreEqual (0, iblist_changed_args.NewIndex, "B5");
  1540. Assert.AreEqual (0, ilist_changed_args.NewIndex, "B6");
  1541. iblist_raised = ilist_raised = 0;
  1542. iblist_changed_args = ilist_changed_args = null;
  1543. // This only applies to IBindingList - Direct access, not through BindingSource
  1544. bindinglist.Remove ("B");
  1545. Assert.AreEqual (1, iblist_raised, "C1");
  1546. Assert.AreEqual (ListChangedType.ItemDeleted, iblist_changed_args.ListChangedType, "C2");
  1547. Assert.AreEqual (0, iblist_changed_args.NewIndex, "C3");
  1548. }
  1549. [Test]
  1550. public void ListChanged_Reset ()
  1551. {
  1552. IBindingList bindinglist = new BindingList<string> ();
  1553. bindinglist.Add ("A");
  1554. bindinglist.Add ("B");
  1555. bindinglist.Add ("C");
  1556. IList arraylist = new ArrayList (bindinglist);
  1557. ResetEventsInfo ();
  1558. iblist_source.DataSource = bindinglist;
  1559. ilist_source.DataSource = arraylist;
  1560. // Clear after setting DataSource generated some info
  1561. iblist_raised = ilist_raised = 0;
  1562. iblist_changed_args = ilist_changed_args = null;
  1563. iblist_source.Clear ();
  1564. ilist_source.Clear ();
  1565. Assert.AreEqual (1, iblist_raised, "A1");
  1566. Assert.AreEqual (1, ilist_raised, "A2");
  1567. Assert.AreEqual (ListChangedType.Reset, iblist_changed_args.ListChangedType, "A3");
  1568. Assert.AreEqual (ListChangedType.Reset, ilist_changed_args.ListChangedType, "A4");
  1569. Assert.AreEqual (-1, iblist_changed_args.NewIndex, "A5");
  1570. Assert.AreEqual (-1, ilist_changed_args.NewIndex, "A6");
  1571. // This is only for BindingList - Direct access to Clear
  1572. // First add some items
  1573. bindinglist.Add ("D");
  1574. bindinglist.Add ("E");
  1575. iblist_raised = ilist_raised = 0;
  1576. iblist_changed_args = ilist_changed_args = null;
  1577. bindinglist.Clear ();
  1578. Assert.AreEqual (1, iblist_raised, "B1");
  1579. Assert.AreEqual (ListChangedType.Reset, iblist_changed_args.ListChangedType, "B2");
  1580. Assert.AreEqual (-1, iblist_changed_args.NewIndex, "B3");
  1581. }
  1582. }
  1583. }
  1584. #endif