ListView.cs 89 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613
  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) 2004-2005 Novell, Inc. (http://www.novell.com)
  21. //
  22. // Authors:
  23. // Ravindra Kumar ([email protected])
  24. // Jordi Mas i Hernandez, [email protected]
  25. // Mike Kestner ([email protected])
  26. // Daniel Nauck (dna(at)mono-project(dot)de)
  27. //
  28. // TODO:
  29. // - Feedback for item activation, change in cursor types as mouse moves.
  30. // - LabelEdit
  31. // - Drag and drop
  32. // NOT COMPLETE
  33. using System.Collections;
  34. using System.ComponentModel;
  35. using System.ComponentModel.Design;
  36. using System.Drawing;
  37. using System.Runtime.InteropServices;
  38. using System.Globalization;
  39. #if NET_2_0
  40. using System.Collections.Generic;
  41. #endif
  42. namespace System.Windows.Forms
  43. {
  44. [DefaultEvent ("SelectedIndexChanged")]
  45. [DefaultProperty ("Items")]
  46. [Designer ("System.Windows.Forms.Design.ListViewDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
  47. public class ListView : Control
  48. {
  49. private ItemActivation activation = ItemActivation.Standard;
  50. private ListViewAlignment alignment = ListViewAlignment.Top;
  51. private bool allow_column_reorder = false;
  52. private bool auto_arrange = true;
  53. private bool check_boxes = false;
  54. private readonly CheckedIndexCollection checked_indices;
  55. private readonly CheckedListViewItemCollection checked_items;
  56. private readonly ColumnHeaderCollection columns;
  57. internal ListViewItem focused_item;
  58. private bool full_row_select = false;
  59. private bool grid_lines = false;
  60. private ColumnHeaderStyle header_style = ColumnHeaderStyle.Clickable;
  61. private bool hide_selection = true;
  62. private bool hover_selection = false;
  63. private IComparer item_sorter;
  64. private readonly ListViewItemCollection items;
  65. #if NET_2_0
  66. private readonly ListViewGroupCollection groups;
  67. private bool show_groups = true;
  68. #endif
  69. private bool label_edit = false;
  70. private bool label_wrap = true;
  71. private bool multiselect = true;
  72. private bool scrollable = true;
  73. private readonly SelectedIndexCollection selected_indices;
  74. private readonly SelectedListViewItemCollection selected_items;
  75. private SortOrder sort_order = SortOrder.None;
  76. private ImageList state_image_list;
  77. private bool updating = false;
  78. private View view = View.LargeIcon;
  79. private int layout_wd; // We might draw more than our client area
  80. private int layout_ht; // therefore we need to have these two.
  81. //private TextBox editor; // Used for editing an item text
  82. HeaderControl header_control;
  83. internal ItemControl item_control;
  84. internal ScrollBar h_scroll; // used for scrolling horizontally
  85. internal ScrollBar v_scroll; // used for scrolling vertically
  86. internal int h_marker; // Position markers for scrolling
  87. internal int v_marker;
  88. private int keysearch_tickcnt;
  89. private string keysearch_text;
  90. static private readonly int keysearch_keydelay = 1000;
  91. private int[] reordered_column_indices;
  92. // internal variables
  93. internal ImageList large_image_list;
  94. internal ImageList small_image_list;
  95. internal Size text_size = Size.Empty;
  96. #region Events
  97. static object AfterLabelEditEvent = new object ();
  98. static object BeforeLabelEditEvent = new object ();
  99. static object ColumnClickEvent = new object ();
  100. static object ItemActivateEvent = new object ();
  101. static object ItemCheckEvent = new object ();
  102. static object ItemDragEvent = new object ();
  103. static object SelectedIndexChangedEvent = new object ();
  104. public event LabelEditEventHandler AfterLabelEdit {
  105. add { Events.AddHandler (AfterLabelEditEvent, value); }
  106. remove { Events.RemoveHandler (AfterLabelEditEvent, value); }
  107. }
  108. [Browsable (false)]
  109. [EditorBrowsable (EditorBrowsableState.Never)]
  110. public new event EventHandler BackgroundImageChanged {
  111. add { base.BackgroundImageChanged += value; }
  112. remove { base.BackgroundImageChanged -= value; }
  113. }
  114. public event LabelEditEventHandler BeforeLabelEdit {
  115. add { Events.AddHandler (BeforeLabelEditEvent, value); }
  116. remove { Events.RemoveHandler (BeforeLabelEditEvent, value); }
  117. }
  118. public event ColumnClickEventHandler ColumnClick {
  119. add { Events.AddHandler (ColumnClickEvent, value); }
  120. remove { Events.RemoveHandler (ColumnClickEvent, value); }
  121. }
  122. public event EventHandler ItemActivate {
  123. add { Events.AddHandler (ItemActivateEvent, value); }
  124. remove { Events.RemoveHandler (ItemActivateEvent, value); }
  125. }
  126. public event ItemCheckEventHandler ItemCheck {
  127. add { Events.AddHandler (ItemCheckEvent, value); }
  128. remove { Events.RemoveHandler (ItemCheckEvent, value); }
  129. }
  130. public event ItemDragEventHandler ItemDrag {
  131. add { Events.AddHandler (ItemDragEvent, value); }
  132. remove { Events.RemoveHandler (ItemDragEvent, value); }
  133. }
  134. [Browsable (false)]
  135. [EditorBrowsable (EditorBrowsableState.Never)]
  136. public new event PaintEventHandler Paint {
  137. add { base.Paint += value; }
  138. remove { base.Paint -= value; }
  139. }
  140. public event EventHandler SelectedIndexChanged {
  141. add { Events.AddHandler (SelectedIndexChangedEvent, value); }
  142. remove { Events.RemoveHandler (SelectedIndexChangedEvent, value); }
  143. }
  144. [Browsable (false)]
  145. [EditorBrowsable (EditorBrowsableState.Never)]
  146. public new event EventHandler TextChanged {
  147. add { base.TextChanged += value; }
  148. remove { base.TextChanged -= value; }
  149. }
  150. #endregion // Events
  151. #region Public Constructors
  152. public ListView ()
  153. {
  154. background_color = ThemeEngine.Current.ColorWindow;
  155. items = new ListViewItemCollection (this);
  156. #if NET_2_0
  157. groups = new ListViewGroupCollection (this);
  158. #endif
  159. checked_indices = new CheckedIndexCollection (this);
  160. checked_items = new CheckedListViewItemCollection (this);
  161. columns = new ColumnHeaderCollection (this);
  162. foreground_color = SystemColors.WindowText;
  163. selected_indices = new SelectedIndexCollection (this);
  164. selected_items = new SelectedListViewItemCollection (this);
  165. border_style = BorderStyle.Fixed3D;
  166. header_control = new HeaderControl (this);
  167. header_control.Visible = false;
  168. Controls.AddImplicit (header_control);
  169. item_control = new ItemControl (this);
  170. Controls.AddImplicit (item_control);
  171. h_scroll = new ImplicitHScrollBar ();
  172. Controls.AddImplicit (this.h_scroll);
  173. v_scroll = new ImplicitVScrollBar ();
  174. Controls.AddImplicit (this.v_scroll);
  175. h_marker = v_marker = 0;
  176. keysearch_tickcnt = 0;
  177. // scroll bars are disabled initially
  178. h_scroll.Visible = false;
  179. h_scroll.ValueChanged += new EventHandler(HorizontalScroller);
  180. v_scroll.Visible = false;
  181. v_scroll.ValueChanged += new EventHandler(VerticalScroller);
  182. // event handlers
  183. base.KeyDown += new KeyEventHandler(ListView_KeyDown);
  184. SizeChanged += new EventHandler (ListView_SizeChanged);
  185. GotFocus += new EventHandler (FocusChanged);
  186. LostFocus += new EventHandler (FocusChanged);
  187. MouseWheel += new MouseEventHandler(ListView_MouseWheel);
  188. this.SetStyle (ControlStyles.UserPaint | ControlStyles.StandardClick
  189. #if NET_2_0
  190. | ControlStyles.UseTextForAccessibility
  191. #endif
  192. , false);
  193. }
  194. #endregion // Public Constructors
  195. #region Private Internal Properties
  196. internal Size CheckBoxSize {
  197. get {
  198. if (this.check_boxes) {
  199. if (this.state_image_list != null)
  200. return this.state_image_list.ImageSize;
  201. else
  202. return ThemeEngine.Current.ListViewCheckBoxSize;
  203. }
  204. return Size.Empty;
  205. }
  206. }
  207. #endregion // Private Internal Properties
  208. #region Protected Properties
  209. protected override CreateParams CreateParams {
  210. get { return base.CreateParams; }
  211. }
  212. protected override Size DefaultSize {
  213. get { return ThemeEngine.Current.ListViewDefaultSize; }
  214. }
  215. #endregion // Protected Properties
  216. #region Public Instance Properties
  217. [DefaultValue (ItemActivation.Standard)]
  218. public ItemActivation Activation {
  219. get { return activation; }
  220. set {
  221. if (value != ItemActivation.Standard && value != ItemActivation.OneClick &&
  222. value != ItemActivation.TwoClick) {
  223. throw new InvalidEnumArgumentException (string.Format
  224. ("Enum argument value '{0}' is not valid for Activation", value));
  225. }
  226. activation = value;
  227. }
  228. }
  229. [DefaultValue (ListViewAlignment.Top)]
  230. [Localizable (true)]
  231. public ListViewAlignment Alignment {
  232. get { return alignment; }
  233. set {
  234. if (value != ListViewAlignment.Default && value != ListViewAlignment.Left &&
  235. value != ListViewAlignment.SnapToGrid && value != ListViewAlignment.Top) {
  236. throw new InvalidEnumArgumentException (string.Format
  237. ("Enum argument value '{0}' is not valid for Alignment", value));
  238. }
  239. if (this.alignment != value) {
  240. alignment = value;
  241. // alignment does not matter in Details/List views
  242. if (this.view == View.LargeIcon ||
  243. this.View == View.SmallIcon)
  244. this.Redraw (true);
  245. }
  246. }
  247. }
  248. [DefaultValue (false)]
  249. public bool AllowColumnReorder {
  250. get { return allow_column_reorder; }
  251. set { allow_column_reorder = value; }
  252. }
  253. [DefaultValue (true)]
  254. public bool AutoArrange {
  255. get { return auto_arrange; }
  256. set {
  257. if (auto_arrange != value) {
  258. auto_arrange = value;
  259. // autoarrange does not matter in Details/List views
  260. if (this.view == View.LargeIcon || this.View == View.SmallIcon)
  261. this.Redraw (true);
  262. }
  263. }
  264. }
  265. public override Color BackColor {
  266. get {
  267. if (background_color.IsEmpty)
  268. return ThemeEngine.Current.ColorWindow;
  269. else
  270. return background_color;
  271. }
  272. set { background_color = value; }
  273. }
  274. [Browsable (false)]
  275. [EditorBrowsable (EditorBrowsableState.Never)]
  276. public override Image BackgroundImage {
  277. get { return base.BackgroundImage; }
  278. set { base.BackgroundImage = value; }
  279. }
  280. [DefaultValue (BorderStyle.Fixed3D)]
  281. [DispId (-504)]
  282. public BorderStyle BorderStyle {
  283. get { return InternalBorderStyle; }
  284. set { InternalBorderStyle = value; }
  285. }
  286. [DefaultValue (false)]
  287. public bool CheckBoxes {
  288. get { return check_boxes; }
  289. set {
  290. if (check_boxes != value) {
  291. #if NET_2_0
  292. if (value && View == View.Tile)
  293. throw new NotSupportedException ("CheckBoxes are not"
  294. + " supported in Tile view. Choose a different"
  295. + " view or set CheckBoxes to false.");
  296. #endif
  297. check_boxes = value;
  298. this.Redraw (true);
  299. }
  300. }
  301. }
  302. [Browsable (false)]
  303. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  304. public CheckedIndexCollection CheckedIndices {
  305. get { return checked_indices; }
  306. }
  307. [Browsable (false)]
  308. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  309. public CheckedListViewItemCollection CheckedItems {
  310. get { return checked_items; }
  311. }
  312. [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
  313. [Localizable (true)]
  314. [MergableProperty (false)]
  315. public ColumnHeaderCollection Columns {
  316. get { return columns; }
  317. }
  318. [Browsable (false)]
  319. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  320. public ListViewItem FocusedItem {
  321. get {
  322. return focused_item;
  323. }
  324. }
  325. public override Color ForeColor {
  326. get {
  327. if (foreground_color.IsEmpty)
  328. return ThemeEngine.Current.ColorWindowText;
  329. else
  330. return foreground_color;
  331. }
  332. set { foreground_color = value; }
  333. }
  334. [DefaultValue (false)]
  335. public bool FullRowSelect {
  336. get { return full_row_select; }
  337. set { full_row_select = value; }
  338. }
  339. [DefaultValue (false)]
  340. public bool GridLines {
  341. get { return grid_lines; }
  342. set {
  343. if (grid_lines != value) {
  344. grid_lines = value;
  345. this.Redraw (false);
  346. }
  347. }
  348. }
  349. [DefaultValue (ColumnHeaderStyle.Clickable)]
  350. public ColumnHeaderStyle HeaderStyle {
  351. get { return header_style; }
  352. set {
  353. if (header_style == value)
  354. return;
  355. switch (value) {
  356. case ColumnHeaderStyle.Clickable:
  357. case ColumnHeaderStyle.Nonclickable:
  358. case ColumnHeaderStyle.None:
  359. break;
  360. default:
  361. throw new InvalidEnumArgumentException (string.Format
  362. ("Enum argument value '{0}' is not valid for ColumnHeaderStyle", value));
  363. }
  364. header_style = value;
  365. if (view == View.Details)
  366. Redraw (true);
  367. }
  368. }
  369. [DefaultValue (true)]
  370. public bool HideSelection {
  371. get { return hide_selection; }
  372. set {
  373. if (hide_selection != value) {
  374. hide_selection = value;
  375. this.Redraw (false);
  376. }
  377. }
  378. }
  379. [DefaultValue (false)]
  380. public bool HoverSelection {
  381. get { return hover_selection; }
  382. set { hover_selection = value; }
  383. }
  384. [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
  385. [Localizable (true)]
  386. [MergableProperty (false)]
  387. public ListViewItemCollection Items {
  388. get { return items; }
  389. }
  390. [DefaultValue (false)]
  391. public bool LabelEdit {
  392. get { return label_edit; }
  393. set { label_edit = value; }
  394. }
  395. [DefaultValue (true)]
  396. [Localizable (true)]
  397. public bool LabelWrap {
  398. get { return label_wrap; }
  399. set {
  400. if (label_wrap != value) {
  401. label_wrap = value;
  402. this.Redraw (true);
  403. }
  404. }
  405. }
  406. [DefaultValue (null)]
  407. public ImageList LargeImageList {
  408. get { return large_image_list; }
  409. set {
  410. large_image_list = value;
  411. this.Redraw (true);
  412. }
  413. }
  414. [Browsable (false)]
  415. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  416. public IComparer ListViewItemSorter {
  417. get {
  418. if (View != View.SmallIcon && View != View.LargeIcon && item_sorter is ItemComparer)
  419. return null;
  420. return item_sorter;
  421. }
  422. set {
  423. if (item_sorter != value) {
  424. item_sorter = value;
  425. Sort ();
  426. }
  427. }
  428. }
  429. [DefaultValue (true)]
  430. public bool MultiSelect {
  431. get { return multiselect; }
  432. set { multiselect = value; }
  433. }
  434. [DefaultValue (true)]
  435. public bool Scrollable {
  436. get { return scrollable; }
  437. set {
  438. if (scrollable != value) {
  439. scrollable = value;
  440. this.Redraw (true);
  441. }
  442. }
  443. }
  444. [Browsable (false)]
  445. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  446. public SelectedIndexCollection SelectedIndices {
  447. get { return selected_indices; }
  448. }
  449. [Browsable (false)]
  450. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  451. public SelectedListViewItemCollection SelectedItems {
  452. get { return selected_items; }
  453. }
  454. #if NET_2_0
  455. [DefaultValue(true)]
  456. public bool ShowGroups {
  457. get { return show_groups; }
  458. set
  459. {
  460. if (show_groups != value)
  461. {
  462. show_groups = value;
  463. Redraw(true);
  464. }
  465. }
  466. }
  467. [LocalizableAttribute(true)]
  468. public ListViewGroupCollection Groups {
  469. get { return groups; }
  470. }
  471. #endif
  472. [DefaultValue (null)]
  473. public ImageList SmallImageList {
  474. get { return small_image_list; }
  475. set {
  476. small_image_list = value;
  477. this.Redraw (true);
  478. }
  479. }
  480. [DefaultValue (SortOrder.None)]
  481. public SortOrder Sorting {
  482. get { return sort_order; }
  483. set {
  484. if (!Enum.IsDefined (typeof (SortOrder), value)) {
  485. throw new InvalidEnumArgumentException ("value", (int) value,
  486. typeof (SortOrder));
  487. }
  488. if (sort_order == value)
  489. return;
  490. sort_order = value;
  491. if (value == SortOrder.None) {
  492. if (item_sorter != null) {
  493. // ListViewItemSorter should never be reset for SmallIcon
  494. // and LargeIcon view
  495. if (View != View.SmallIcon && View != View.LargeIcon)
  496. #if NET_2_0
  497. item_sorter = null;
  498. #else
  499. // in .NET 1.1, only internal IComparer would be
  500. // set to null
  501. if (item_sorter is ItemComparer)
  502. item_sorter = null;
  503. #endif
  504. }
  505. this.Redraw (false);
  506. } else {
  507. if (item_sorter == null)
  508. item_sorter = new ItemComparer (value);
  509. if (item_sorter is ItemComparer) {
  510. #if NET_2_0
  511. item_sorter = new ItemComparer (value);
  512. #else
  513. // in .NET 1.1, the sort order is not updated for
  514. // SmallIcon and LargeIcon views if no custom IComparer
  515. // is set
  516. if (View != View.SmallIcon && View != View.LargeIcon)
  517. item_sorter = new ItemComparer (value);
  518. #endif
  519. }
  520. Sort ();
  521. }
  522. }
  523. }
  524. [DefaultValue (null)]
  525. public ImageList StateImageList {
  526. get { return state_image_list; }
  527. set {
  528. state_image_list = value;
  529. this.Redraw (true);
  530. }
  531. }
  532. [Bindable (false)]
  533. [Browsable (false)]
  534. [EditorBrowsable (EditorBrowsableState.Never)]
  535. public override string Text {
  536. get { return base.Text; }
  537. set {
  538. if (value == base.Text)
  539. return;
  540. base.Text = value;
  541. this.Redraw (true);
  542. }
  543. }
  544. [Browsable (false)]
  545. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  546. public ListViewItem TopItem {
  547. get {
  548. // there is no item
  549. if (this.items.Count == 0)
  550. return null;
  551. // if contents are not scrolled
  552. // it is the first item
  553. else if (h_marker == 0 && v_marker == 0)
  554. return this.items [0];
  555. // do a hit test for the scrolled position
  556. else {
  557. foreach (ListViewItem item in this.items) {
  558. if (item.Bounds.X >= 0 && item.Bounds.Y >= 0)
  559. return item;
  560. }
  561. return null;
  562. }
  563. }
  564. }
  565. #if NET_2_0
  566. [MonoTODO("Implement")]
  567. public bool UseCompatibleStateImageBehavior {
  568. get {
  569. return false;
  570. }
  571. set {
  572. }
  573. }
  574. #endif
  575. [DefaultValue (View.LargeIcon)]
  576. public View View {
  577. get { return view; }
  578. set {
  579. if (!Enum.IsDefined (typeof (View), value))
  580. throw new InvalidEnumArgumentException ("value", (int) value,
  581. typeof (View));
  582. if (view != value) {
  583. #if NET_2_0
  584. if (CheckBoxes && value == View.Tile)
  585. throw new NotSupportedException ("CheckBoxes are not"
  586. + " supported in Tile view. Choose a different"
  587. + " view or set CheckBoxes to false.");
  588. #endif
  589. h_scroll.Value = v_scroll.Value = 0;
  590. view = value;
  591. Redraw (true);
  592. }
  593. }
  594. }
  595. #endregion // Public Instance Properties
  596. #region Internal Methods Properties
  597. internal int FirstVisibleIndex {
  598. get {
  599. // there is no item
  600. if (this.items.Count == 0)
  601. return 0;
  602. if (h_marker == 0 && v_marker == 0)
  603. return 0;
  604. foreach (ListViewItem item in this.items) {
  605. if (item.Bounds.Right >= 0 && item.Bounds.Bottom >= 0)
  606. return item.Index;
  607. }
  608. return 0;
  609. }
  610. }
  611. internal int LastVisibleIndex {
  612. get {
  613. for (int i = FirstVisibleIndex; i < Items.Count; i++) {
  614. if (View == View.List || Alignment == ListViewAlignment.Left) {
  615. if (Items[i].Bounds.X > ClientRectangle.Right)
  616. return i - 1;
  617. } else {
  618. if (Items[i].Bounds.Y > ClientRectangle.Bottom)
  619. return i - 1;
  620. }
  621. }
  622. return Items.Count - 1;
  623. }
  624. }
  625. internal void OnSelectedIndexChanged ()
  626. {
  627. if (IsHandleCreated)
  628. OnSelectedIndexChanged (EventArgs.Empty);
  629. }
  630. internal int TotalWidth {
  631. get { return Math.Max (this.Width, this.layout_wd); }
  632. }
  633. internal int TotalHeight {
  634. get { return Math.Max (this.Height, this.layout_ht); }
  635. }
  636. internal void Redraw (bool recalculate)
  637. {
  638. // Avoid calculations when control is being updated
  639. if (this.updating)
  640. return;
  641. if (recalculate)
  642. CalculateListView (this.alignment);
  643. Refresh ();
  644. }
  645. const int text_padding = 5;
  646. internal Size GetChildColumnSize (int index)
  647. {
  648. Size ret_size = Size.Empty;
  649. ColumnHeader col = this.columns [index];
  650. if (col.Width == -2) { // autosize = max(items, columnheader)
  651. Size size = Size.Ceiling (this.DeviceContext.MeasureString
  652. (col.Text, this.Font));
  653. size.Height += text_padding;
  654. size.Width += text_padding;
  655. ret_size = BiggestItem (index);
  656. if (size.Width > ret_size.Width)
  657. ret_size = size;
  658. }
  659. else { // -1 and all the values < -2 are put under one category
  660. ret_size = BiggestItem (index);
  661. // fall back to empty columns' width if no subitem is available for a column
  662. if (ret_size.IsEmpty) {
  663. ret_size.Width = ThemeEngine.Current.ListViewEmptyColumnWidth;
  664. if (col.Text.Length > 0)
  665. ret_size.Height = Size.Ceiling (this.DeviceContext.MeasureString
  666. (col.Text, this.Font)).Height;
  667. else
  668. ret_size.Height = this.Font.Height;
  669. }
  670. }
  671. // adjust the size for icon and checkbox for 0th column
  672. if (index == 0) {
  673. ret_size.Width += (this.CheckBoxSize.Width + 4);
  674. if (this.small_image_list != null)
  675. ret_size.Width += this.small_image_list.ImageSize.Width;
  676. }
  677. return ret_size;
  678. }
  679. // Returns the size of biggest item text in a column.
  680. private Size BiggestItem (int col)
  681. {
  682. Size temp = Size.Empty;
  683. Size ret_size = Size.Empty;
  684. // 0th column holds the item text, we check the size of
  685. // the various subitems falling in that column and get
  686. // the biggest one's size.
  687. foreach (ListViewItem item in items) {
  688. if (col >= item.SubItems.Count)
  689. continue;
  690. temp = Size.Ceiling (this.DeviceContext.MeasureString
  691. (item.SubItems [col].Text, this.Font));
  692. if (temp.Width > ret_size.Width)
  693. ret_size = temp;
  694. }
  695. // adjustment for space
  696. if (!ret_size.IsEmpty)
  697. ret_size.Width += 4;
  698. return ret_size;
  699. }
  700. const int max_wrap_padding = 38;
  701. // Sets the size of the biggest item text as per the view
  702. private void CalcTextSize ()
  703. {
  704. // clear the old value
  705. text_size = Size.Empty;
  706. if (items.Count == 0)
  707. return;
  708. text_size = BiggestItem (0);
  709. if (view == View.LargeIcon && this.label_wrap) {
  710. Size temp = Size.Empty;
  711. if (this.check_boxes)
  712. temp.Width += 2 * this.CheckBoxSize.Width;
  713. int icon_w = LargeImageList == null ? 12 : LargeImageList.ImageSize.Width;
  714. temp.Width += icon_w + max_wrap_padding;
  715. // wrapping is done for two lines only
  716. if (text_size.Width > temp.Width) {
  717. text_size.Width = temp.Width;
  718. text_size.Height *= 2;
  719. }
  720. }
  721. else if (view == View.List) {
  722. // in list view max text shown in determined by the
  723. // control width, even if scolling is enabled.
  724. int max_wd = this.Width - (this.CheckBoxSize.Width - 2);
  725. if (this.small_image_list != null)
  726. max_wd -= this.small_image_list.ImageSize.Width;
  727. if (text_size.Width > max_wd)
  728. text_size.Width = max_wd;
  729. }
  730. // we do the default settings, if we have got 0's
  731. if (text_size.Height <= 0)
  732. text_size.Height = this.Font.Height;
  733. if (text_size.Width <= 0)
  734. text_size.Width = this.Width;
  735. // little adjustment
  736. text_size.Width += 4;
  737. text_size.Height += 2;
  738. }
  739. private void Scroll (ScrollBar scrollbar, int delta)
  740. {
  741. if (delta == 0 || !scrollbar.Visible)
  742. return;
  743. int max;
  744. if (scrollbar == h_scroll)
  745. max = h_scroll.Maximum - item_control.Width;
  746. else
  747. max = v_scroll.Maximum - item_control.Height;
  748. int val = scrollbar.Value + delta;
  749. if (val > max)
  750. val = max;
  751. else if (val < scrollbar.Minimum)
  752. val = scrollbar.Minimum;
  753. scrollbar.Value = val;
  754. }
  755. private void CalculateScrollBars ()
  756. {
  757. Rectangle client_area = ClientRectangle;
  758. if (!this.scrollable || this.items.Count <= 0) {
  759. h_scroll.Visible = false;
  760. v_scroll.Visible = false;
  761. item_control.Location = new Point (0, header_control.Height);
  762. item_control.Height = ClientRectangle.Width - header_control.Height;
  763. item_control.Width = ClientRectangle.Width;
  764. header_control.Width = ClientRectangle.Width;
  765. return;
  766. }
  767. // Don't calculate if the view is not displayable
  768. if (client_area.Height < 0 || client_area.Width < 0)
  769. return;
  770. // making a scroll bar visible might make
  771. // other scroll bar visible
  772. if (layout_wd > client_area.Right) {
  773. h_scroll.Visible = true;
  774. if ((layout_ht + h_scroll.Height) > client_area.Bottom)
  775. v_scroll.Visible = true;
  776. else
  777. v_scroll.Visible = false;
  778. } else if (layout_ht > client_area.Bottom) {
  779. v_scroll.Visible = true;
  780. if ((layout_wd + v_scroll.Width) > client_area.Right)
  781. h_scroll.Visible = true;
  782. else
  783. h_scroll.Visible = false;
  784. } else {
  785. h_scroll.Visible = false;
  786. v_scroll.Visible = false;
  787. }
  788. item_control.Height = ClientRectangle.Height - header_control.Height;
  789. if (h_scroll.is_visible) {
  790. h_scroll.Location = new Point (client_area.X, client_area.Bottom - h_scroll.Height);
  791. h_scroll.Minimum = 0;
  792. // if v_scroll is visible, adjust the maximum of the
  793. // h_scroll to account for the width of v_scroll
  794. if (v_scroll.Visible) {
  795. h_scroll.Maximum = layout_wd + v_scroll.Width;
  796. h_scroll.Width = client_area.Width - v_scroll.Width;
  797. }
  798. else {
  799. h_scroll.Maximum = layout_wd;
  800. h_scroll.Width = client_area.Width;
  801. }
  802. h_scroll.LargeChange = client_area.Width;
  803. h_scroll.SmallChange = Font.Height;
  804. item_control.Height -= h_scroll.Height;
  805. }
  806. if (header_control.is_visible)
  807. header_control.Width = ClientRectangle.Width;
  808. item_control.Width = ClientRectangle.Width;
  809. if (v_scroll.is_visible) {
  810. v_scroll.Location = new Point (client_area.Right - v_scroll.Width, client_area.Y);
  811. v_scroll.Minimum = 0;
  812. // if h_scroll is visible, adjust the maximum of the
  813. // v_scroll to account for the height of h_scroll
  814. if (h_scroll.Visible) {
  815. v_scroll.Maximum = layout_ht + h_scroll.Height;
  816. v_scroll.Height = client_area.Height; // - h_scroll.Height already done
  817. } else {
  818. v_scroll.Maximum = layout_ht;
  819. v_scroll.Height = client_area.Height;
  820. }
  821. v_scroll.LargeChange = client_area.Height;
  822. v_scroll.SmallChange = Font.Height;
  823. if (header_control.Visible)
  824. header_control.Width -= v_scroll.Width;
  825. item_control.Width -= v_scroll.Width;
  826. }
  827. }
  828. ColumnHeader GetReorderedColumn (int index)
  829. {
  830. if (reordered_column_indices == null)
  831. return Columns [index];
  832. else
  833. return Columns [reordered_column_indices [index]];
  834. }
  835. void ReorderColumn (ColumnHeader col, int index)
  836. {
  837. if (reordered_column_indices == null) {
  838. reordered_column_indices = new int [Columns.Count];
  839. for (int i = 0; i < Columns.Count; i++)
  840. reordered_column_indices [i] = i;
  841. }
  842. if (reordered_column_indices [index] == col.Index)
  843. return;
  844. int[] curr = reordered_column_indices;
  845. int[] result = new int [Columns.Count];
  846. int curr_idx = 0;
  847. for (int i = 0; i < Columns.Count; i++) {
  848. if (curr_idx < Columns.Count && curr [curr_idx] == col.Index)
  849. curr_idx++;
  850. if (i == index)
  851. result [i] = col.Index;
  852. else
  853. result [i] = curr [curr_idx++];
  854. }
  855. reordered_column_indices = result;
  856. LayoutDetails ();
  857. header_control.Invalidate ();
  858. item_control.Invalidate ();
  859. }
  860. Size LargeIconItemSize {
  861. get {
  862. int image_w = LargeImageList == null ? 12 : LargeImageList.ImageSize.Width;
  863. int image_h = LargeImageList == null ? 2 : LargeImageList.ImageSize.Height;
  864. int w = CheckBoxSize.Width + 2 + Math.Max (text_size.Width, image_w);
  865. int h = text_size.Height + 2 + Math.Max (CheckBoxSize.Height, image_h);
  866. return new Size (w, h);
  867. }
  868. }
  869. Size SmallIconItemSize {
  870. get {
  871. int image_w = SmallImageList == null ? 0 : SmallImageList.ImageSize.Width;
  872. int image_h = SmallImageList == null ? 0 : SmallImageList.ImageSize.Height;
  873. int w = text_size.Width + 2 + CheckBoxSize.Width + image_w;
  874. int h = Math.Max (text_size.Height, Math.Max (CheckBoxSize.Height, image_h));
  875. return new Size (w, h);
  876. }
  877. }
  878. int rows;
  879. int cols;
  880. ListViewItem[,] item_matrix;
  881. void LayoutIcons (bool large_icons, bool left_aligned, int x_spacing, int y_spacing)
  882. {
  883. header_control.Visible = false;
  884. header_control.Size = Size.Empty;
  885. item_control.Visible = true;
  886. item_control.Location = Point.Empty;
  887. if (items.Count == 0)
  888. return;
  889. Size sz = large_icons ? LargeIconItemSize : SmallIconItemSize;
  890. Rectangle area = ClientRectangle;
  891. if (left_aligned) {
  892. rows = (int) Math.Floor ((double)(area.Height - h_scroll.Height + y_spacing) / (double)(sz.Height + y_spacing));
  893. if (rows <= 0)
  894. rows = 1;
  895. cols = (int) Math.Ceiling ((double)items.Count / (double)rows);
  896. } else {
  897. cols = (int) Math.Floor ((double)(area.Width - v_scroll.Width + x_spacing) / (double)(sz.Width + x_spacing));
  898. if (cols <= 0)
  899. cols = 1;
  900. rows = (int) Math.Ceiling ((double)items.Count / (double)cols);
  901. }
  902. layout_ht = rows * (sz.Height + y_spacing) - y_spacing;
  903. layout_wd = cols * (sz.Width + x_spacing) - x_spacing;
  904. item_matrix = new ListViewItem [rows, cols];
  905. int row = 0;
  906. int col = 0;
  907. foreach (ListViewItem item in items) {
  908. int x = col * (sz.Width + x_spacing);
  909. int y = row * (sz.Height + y_spacing);
  910. item.Location = new Point (x, y);
  911. item.Layout ();
  912. item.row = row;
  913. item.col = col;
  914. item_matrix [row, col] = item;
  915. if (left_aligned) {
  916. if (++row == rows) {
  917. row = 0;
  918. col++;
  919. }
  920. } else {
  921. if (++col == cols) {
  922. col = 0;
  923. row++;
  924. }
  925. }
  926. }
  927. item_control.Size = new Size (layout_wd, layout_ht);
  928. }
  929. void LayoutHeader ()
  930. {
  931. int x = 0;
  932. for (int i = 0; i < Columns.Count; i++) {
  933. ColumnHeader col = GetReorderedColumn (i);
  934. col.X = x;
  935. col.Y = 0;
  936. col.CalcColumnHeader ();
  937. x += col.Wd;
  938. }
  939. if (x < ClientRectangle.Width)
  940. x = ClientRectangle.Width;
  941. if (header_style == ColumnHeaderStyle.None) {
  942. header_control.Visible = false;
  943. header_control.Size = Size.Empty;
  944. } else {
  945. header_control.Width = x;
  946. header_control.Height = columns [0].Ht;
  947. header_control.Visible = true;
  948. }
  949. }
  950. void LayoutDetails ()
  951. {
  952. if (columns.Count == 0) {
  953. header_control.Visible = false;
  954. item_control.Visible = false;
  955. return;
  956. }
  957. LayoutHeader ();
  958. item_control.Visible = true;
  959. item_control.Location = new Point (0, header_control.Height);
  960. int y = 0;
  961. if (items.Count > 0) {
  962. foreach (ListViewItem item in items) {
  963. item.Layout ();
  964. item.Location = new Point (0, y);
  965. y += item.Bounds.Height + 2;
  966. }
  967. // some space for bottom gridline
  968. if (grid_lines)
  969. y += 2;
  970. }
  971. layout_wd = Math.Max (header_control.Width, item_control.Width);
  972. layout_ht = y + header_control.Height;
  973. }
  974. private void CalculateListView (ListViewAlignment align)
  975. {
  976. CalcTextSize ();
  977. switch (view) {
  978. case View.Details:
  979. LayoutDetails ();
  980. break;
  981. case View.SmallIcon:
  982. LayoutIcons (false, alignment == ListViewAlignment.Left, 4, 2);
  983. break;
  984. case View.LargeIcon:
  985. LayoutIcons (true, alignment == ListViewAlignment.Left,
  986. ThemeEngine.Current.ListViewHorizontalSpacing,
  987. ThemeEngine.Current.ListViewVerticalSpacing);
  988. break;
  989. case View.List:
  990. LayoutIcons (false, true, 4, 2);
  991. break;
  992. }
  993. CalculateScrollBars ();
  994. }
  995. private bool KeySearchString (KeyEventArgs ke)
  996. {
  997. int current_tickcnt = Environment.TickCount;
  998. if (keysearch_tickcnt > 0 && current_tickcnt - keysearch_tickcnt > keysearch_keydelay) {
  999. keysearch_text = string.Empty;
  1000. }
  1001. keysearch_text += (char) ke.KeyData;
  1002. keysearch_tickcnt = current_tickcnt;
  1003. int start = FocusedItem == null ? 0 : FocusedItem.Index;
  1004. int i = start;
  1005. while (true) {
  1006. if (CultureInfo.CurrentCulture.CompareInfo.IsPrefix (Items[i].Text, keysearch_text,
  1007. CompareOptions.IgnoreCase)) {
  1008. SetFocusedItem (Items [i]);
  1009. items [i].Selected = true;
  1010. EnsureVisible (i);
  1011. break;
  1012. }
  1013. i = (i + 1 < Items.Count) ? i+1 : 0;
  1014. if (i == start)
  1015. break;
  1016. }
  1017. return true;
  1018. }
  1019. int GetAdjustedIndex (Keys key)
  1020. {
  1021. int result = -1;
  1022. if (View == View.Details) {
  1023. if (key == Keys.Up)
  1024. result = FocusedItem.Index - 1;
  1025. else if (key == Keys.Down) {
  1026. result = FocusedItem.Index + 1;
  1027. if (result == items.Count)
  1028. result = -1;
  1029. }
  1030. return result;
  1031. }
  1032. int row = FocusedItem.row;
  1033. int col = FocusedItem.col;
  1034. switch (key) {
  1035. case Keys.Left:
  1036. if (col == 0)
  1037. return -1;
  1038. return item_matrix [row, col - 1].Index;
  1039. case Keys.Right:
  1040. if (col == (cols - 1))
  1041. return -1;
  1042. while (item_matrix [row, col + 1] == null) {
  1043. row--;
  1044. if (row < 0)
  1045. return -1;
  1046. }
  1047. return item_matrix [row, col + 1].Index;
  1048. case Keys.Up:
  1049. if (row == 0)
  1050. return -1;
  1051. return item_matrix [row - 1, col].Index;
  1052. case Keys.Down:
  1053. if (row == (rows - 1) || row == Items.Count - 1)
  1054. return -1;
  1055. while (item_matrix [row + 1, col] == null) {
  1056. col--;
  1057. if (col < 0)
  1058. return -1;
  1059. }
  1060. return item_matrix [row + 1, col].Index;
  1061. default:
  1062. return -1;
  1063. }
  1064. }
  1065. ListViewItem selection_start;
  1066. private bool SelectItems (ArrayList sel_items)
  1067. {
  1068. bool changed = false;
  1069. ArrayList curr_items = SelectedItems.List;
  1070. foreach (ListViewItem item in curr_items)
  1071. if (!sel_items.Contains (item)) {
  1072. item.Selected = false;
  1073. changed = true;
  1074. }
  1075. foreach (ListViewItem item in sel_items)
  1076. if (!item.Selected) {
  1077. item.Selected = true;
  1078. changed = true;
  1079. }
  1080. return changed;
  1081. }
  1082. private void UpdateMultiSelection (int index)
  1083. {
  1084. bool shift_pressed = (XplatUI.State.ModifierKeys & Keys.Shift) != 0;
  1085. bool ctrl_pressed = (XplatUI.State.ModifierKeys & Keys.Control) != 0;
  1086. ListViewItem item = items [index];
  1087. if (shift_pressed && selection_start != null) {
  1088. ArrayList list = new ArrayList ();
  1089. int start = Math.Min (selection_start.Index, index);
  1090. int end = Math.Max (selection_start.Index, index);
  1091. if (View == View.Details) {
  1092. for (int i = start; i <= end; i++)
  1093. list.Add (items [i]);
  1094. } else {
  1095. int left = Math.Min (items [start].col, items [end].col);
  1096. int right = Math.Max (items [start].col, items [end].col);
  1097. int top = Math.Min (items [start].row, items [end].row);
  1098. int bottom = Math.Max (items [start].row, items [end].row);
  1099. foreach (ListViewItem curr in items)
  1100. if (curr.row >= top && curr.row <= bottom &&
  1101. curr.col >= left && curr.col <= right)
  1102. list.Add (curr);
  1103. }
  1104. if (SelectItems (list))
  1105. OnSelectedIndexChanged (EventArgs.Empty);
  1106. } else if (ctrl_pressed) {
  1107. item.Selected = !item.Selected;
  1108. selection_start = item;
  1109. OnSelectedIndexChanged (EventArgs.Empty);
  1110. } else {
  1111. SelectedItems.Clear ();
  1112. item.Selected = true;
  1113. selection_start = item;
  1114. OnSelectedIndexChanged (EventArgs.Empty);
  1115. }
  1116. }
  1117. internal override bool InternalPreProcessMessage (ref Message msg)
  1118. {
  1119. if (msg.Msg == (int)Msg.WM_KEYDOWN) {
  1120. Keys key_data = (Keys)msg.WParam.ToInt32();
  1121. if (HandleNavKeys (key_data))
  1122. return true;
  1123. }
  1124. return base.InternalPreProcessMessage (ref msg);
  1125. }
  1126. bool HandleNavKeys (Keys key_data)
  1127. {
  1128. if (Items.Count == 0 || !item_control.Visible)
  1129. return false;
  1130. if (FocusedItem == null)
  1131. SetFocusedItem (Items [0]);
  1132. switch (key_data) {
  1133. case Keys.End:
  1134. SelectIndex (Items.Count - 1);
  1135. break;
  1136. case Keys.Home:
  1137. SelectIndex (0);
  1138. break;
  1139. case Keys.Left:
  1140. case Keys.Right:
  1141. case Keys.Up:
  1142. case Keys.Down:
  1143. SelectIndex (GetAdjustedIndex (key_data));
  1144. break;
  1145. default:
  1146. return false;
  1147. }
  1148. return true;
  1149. }
  1150. void SelectIndex (int index)
  1151. {
  1152. if (index == -1)
  1153. return;
  1154. if (MultiSelect)
  1155. UpdateMultiSelection (index);
  1156. else if (!items [index].Selected) {
  1157. items [index].Selected = true;
  1158. OnSelectedIndexChanged (EventArgs.Empty);
  1159. }
  1160. SetFocusedItem (items [index]);
  1161. EnsureVisible (index);
  1162. }
  1163. private void ListView_KeyDown (object sender, KeyEventArgs ke)
  1164. {
  1165. if (ke.Handled || Items.Count == 0 || !item_control.Visible)
  1166. return;
  1167. ke.Handled = KeySearchString (ke);
  1168. }
  1169. internal class ItemControl : Control {
  1170. ListView owner;
  1171. ListViewItem clicked_item;
  1172. ListViewItem last_clicked_item;
  1173. bool hover_processed = false;
  1174. bool checking = false;
  1175. ListViewLabelEditTextBox edit_text_box;
  1176. internal ListViewItem edit_item;
  1177. LabelEditEventArgs edit_args;
  1178. public ItemControl (ListView owner)
  1179. {
  1180. this.owner = owner;
  1181. DoubleClick += new EventHandler(ItemsDoubleClick);
  1182. MouseDown += new MouseEventHandler(ItemsMouseDown);
  1183. MouseMove += new MouseEventHandler(ItemsMouseMove);
  1184. MouseHover += new EventHandler(ItemsMouseHover);
  1185. MouseUp += new MouseEventHandler(ItemsMouseUp);
  1186. }
  1187. void ItemsDoubleClick (object sender, EventArgs e)
  1188. {
  1189. if (owner.activation == ItemActivation.Standard)
  1190. owner.OnItemActivate (EventArgs.Empty);
  1191. }
  1192. enum BoxSelect {
  1193. None,
  1194. Normal,
  1195. Shift,
  1196. Control
  1197. }
  1198. BoxSelect box_select_mode = BoxSelect.None;
  1199. ArrayList prev_selection;
  1200. Point box_select_start;
  1201. Rectangle box_select_rect;
  1202. internal Rectangle BoxSelectRectangle {
  1203. get { return box_select_rect; }
  1204. set {
  1205. if (box_select_rect == value)
  1206. return;
  1207. InvalidateBoxSelectRect ();
  1208. box_select_rect = value;
  1209. InvalidateBoxSelectRect ();
  1210. }
  1211. }
  1212. void InvalidateBoxSelectRect ()
  1213. {
  1214. if (BoxSelectRectangle.Size.IsEmpty)
  1215. return;
  1216. Rectangle edge = BoxSelectRectangle;
  1217. edge.X -= 1;
  1218. edge.Y -= 1;
  1219. edge.Width += 2;
  1220. edge.Height = 2;
  1221. Invalidate (edge);
  1222. edge.Y = BoxSelectRectangle.Bottom - 1;
  1223. Invalidate (edge);
  1224. edge.Y = BoxSelectRectangle.Y - 1;
  1225. edge.Width = 2;
  1226. edge.Height = BoxSelectRectangle.Height + 2;
  1227. Invalidate (edge);
  1228. edge.X = BoxSelectRectangle.Right - 1;
  1229. Invalidate (edge);
  1230. }
  1231. private Rectangle CalculateBoxSelectRectangle (Point pt)
  1232. {
  1233. int left = Math.Min (box_select_start.X, pt.X);
  1234. int right = Math.Max (box_select_start.X, pt.X);
  1235. int top = Math.Min (box_select_start.Y, pt.Y);
  1236. int bottom = Math.Max (box_select_start.Y, pt.Y);
  1237. return Rectangle.FromLTRB (left, top, right, bottom);
  1238. }
  1239. ArrayList BoxSelectedItems {
  1240. get {
  1241. ArrayList result = new ArrayList ();
  1242. foreach (ListViewItem item in owner.Items) {
  1243. Rectangle r = item.Bounds;
  1244. r.X += r.Width / 4;
  1245. r.Y += r.Height / 4;
  1246. r.Width /= 2;
  1247. r.Height /= 2;
  1248. if (BoxSelectRectangle.IntersectsWith (r))
  1249. result.Add (item);
  1250. }
  1251. return result;
  1252. }
  1253. }
  1254. private bool PerformBoxSelection (Point pt)
  1255. {
  1256. if (box_select_mode == BoxSelect.None)
  1257. return false;
  1258. BoxSelectRectangle = CalculateBoxSelectRectangle (pt);
  1259. ArrayList box_items = BoxSelectedItems;
  1260. ArrayList items;
  1261. switch (box_select_mode) {
  1262. case BoxSelect.Normal:
  1263. items = box_items;
  1264. break;
  1265. case BoxSelect.Control:
  1266. items = new ArrayList ();
  1267. foreach (ListViewItem item in prev_selection)
  1268. if (!box_items.Contains (item))
  1269. items.Add (item);
  1270. foreach (ListViewItem item in box_items)
  1271. if (!prev_selection.Contains (item))
  1272. items.Add (item);
  1273. break;
  1274. case BoxSelect.Shift:
  1275. items = box_items;
  1276. foreach (ListViewItem item in box_items)
  1277. prev_selection.Remove (item);
  1278. foreach (ListViewItem item in prev_selection)
  1279. items.Add (item);
  1280. break;
  1281. default:
  1282. throw new Exception ("Unexpected Selection mode: " + box_select_mode);
  1283. }
  1284. SuspendLayout ();
  1285. owner.SelectItems (items);
  1286. ResumeLayout ();
  1287. return true;
  1288. }
  1289. private void ToggleCheckState (ListViewItem item)
  1290. {
  1291. CheckState curr_state = item.Checked ? CheckState.Checked : CheckState.Unchecked;
  1292. item.Checked = !item.Checked;
  1293. CheckState new_state = item.Checked ? CheckState.Checked : CheckState.Unchecked;
  1294. ItemCheckEventArgs ice = new ItemCheckEventArgs (item.Index, curr_state, new_state);
  1295. owner.OnItemCheck (ice);
  1296. }
  1297. private void ItemsMouseDown (object sender, MouseEventArgs me)
  1298. {
  1299. if (owner.items.Count == 0)
  1300. return;
  1301. Point pt = new Point (me.X, me.Y);
  1302. foreach (ListViewItem item in owner.items) {
  1303. if (me.Clicks == 1 && item.CheckRectReal.Contains (pt)) {
  1304. checking = true;
  1305. if (me.Clicks > 1)
  1306. return;
  1307. ToggleCheckState (item);
  1308. return;
  1309. }
  1310. if (owner.View == View.Details && !owner.FullRowSelect) {
  1311. if (item.GetBounds (ItemBoundsPortion.Label).Contains (pt)) {
  1312. clicked_item = item;
  1313. break;
  1314. }
  1315. } else {
  1316. if (item.Bounds.Contains (pt)) {
  1317. clicked_item = item;
  1318. break;
  1319. }
  1320. }
  1321. }
  1322. if (clicked_item != null) {
  1323. owner.SetFocusedItem (clicked_item);
  1324. bool changed = !clicked_item.Selected;
  1325. if (owner.MultiSelect)
  1326. owner.UpdateMultiSelection (clicked_item.Index);
  1327. else
  1328. clicked_item.Selected = true;
  1329. if (changed)
  1330. owner.OnSelectedIndexChanged (EventArgs.Empty);
  1331. // Raise double click if the item was clicked. On MS the
  1332. // double click is only raised if you double click an item
  1333. if (me.Clicks > 1) {
  1334. owner.OnDoubleClick (EventArgs.Empty);
  1335. if (owner.CheckBoxes)
  1336. ToggleCheckState (clicked_item);
  1337. } else if (me.Clicks == 1) {
  1338. owner.OnClick (EventArgs.Empty);
  1339. if (owner.LabelEdit && !changed)
  1340. BeginEdit (clicked_item); // this is probably not the correct place to execute BeginEdit
  1341. }
  1342. } else {
  1343. if (owner.MultiSelect) {
  1344. Keys mods = XplatUI.State.ModifierKeys;
  1345. if ((mods & Keys.Shift) != 0)
  1346. box_select_mode = BoxSelect.Shift;
  1347. else if ((mods & Keys.Control) != 0)
  1348. box_select_mode = BoxSelect.Control;
  1349. else
  1350. box_select_mode = BoxSelect.Normal;
  1351. box_select_start = pt;
  1352. prev_selection = owner.SelectedItems.List;
  1353. } else if (owner.SelectedItems.Count > 0) {
  1354. owner.SelectedItems.Clear ();
  1355. owner.OnSelectedIndexChanged (EventArgs.Empty);
  1356. }
  1357. }
  1358. }
  1359. private void ItemsMouseMove (object sender, MouseEventArgs me)
  1360. {
  1361. if (PerformBoxSelection (new Point (me.X, me.Y)))
  1362. return;
  1363. if (owner.HoverSelection && hover_processed) {
  1364. Point pt = PointToClient (Control.MousePosition);
  1365. ListViewItem item = owner.GetItemAt (pt.X, pt.Y);
  1366. if (item == null || item.Selected)
  1367. return;
  1368. hover_processed = false;
  1369. XplatUI.ResetMouseHover (Handle);
  1370. }
  1371. }
  1372. private void ItemsMouseHover (object sender, EventArgs e)
  1373. {
  1374. if (Capture || !owner.HoverSelection)
  1375. return;
  1376. hover_processed = true;
  1377. Point pt = PointToClient (Control.MousePosition);
  1378. ListViewItem item = owner.GetItemAt (pt.X, pt.Y);
  1379. if (item == null)
  1380. return;
  1381. item.Selected = true;
  1382. owner.OnSelectedIndexChanged (new EventArgs ());
  1383. }
  1384. private void ItemsMouseUp (object sender, MouseEventArgs me)
  1385. {
  1386. Capture = false;
  1387. if (owner.Items.Count == 0)
  1388. return;
  1389. Point pt = new Point (me.X, me.Y);
  1390. Rectangle rect = Rectangle.Empty;
  1391. if (clicked_item != null) {
  1392. if (owner.view == View.Details && !owner.full_row_select)
  1393. rect = clicked_item.GetBounds (ItemBoundsPortion.Label);
  1394. else
  1395. rect = clicked_item.Bounds;
  1396. if (rect.Contains (pt)) {
  1397. switch (owner.activation) {
  1398. case ItemActivation.OneClick:
  1399. owner.OnItemActivate (EventArgs.Empty);
  1400. break;
  1401. case ItemActivation.TwoClick:
  1402. if (last_clicked_item == clicked_item) {
  1403. owner.OnItemActivate (EventArgs.Empty);
  1404. last_clicked_item = null;
  1405. } else
  1406. last_clicked_item = clicked_item;
  1407. break;
  1408. default:
  1409. // DoubleClick activation is handled in another handler
  1410. break;
  1411. }
  1412. }
  1413. } else if (!checking && owner.SelectedItems.Count > 0 && BoxSelectRectangle.Size.IsEmpty) {
  1414. // Need this to clean up background clicks
  1415. owner.SelectedItems.Clear ();
  1416. owner.OnSelectedIndexChanged (EventArgs.Empty);
  1417. }
  1418. clicked_item = null;
  1419. box_select_start = Point.Empty;
  1420. BoxSelectRectangle = Rectangle.Empty;
  1421. prev_selection = null;
  1422. box_select_mode = BoxSelect.None;
  1423. checking = false;
  1424. }
  1425. internal void LabelEditFinished (object sender, EventArgs e)
  1426. {
  1427. EndEdit (edit_item);
  1428. }
  1429. internal void BeginEdit (ListViewItem item)
  1430. {
  1431. if (edit_item != null)
  1432. EndEdit (edit_item);
  1433. if (edit_text_box == null) {
  1434. edit_text_box = new ListViewLabelEditTextBox ();
  1435. edit_text_box.BorderStyle = BorderStyle.FixedSingle;
  1436. edit_text_box.EditingFinished += new EventHandler (LabelEditFinished);
  1437. edit_text_box.Visible = false;
  1438. Controls.Add (edit_text_box);
  1439. }
  1440. item.EnsureVisible();
  1441. edit_text_box.Reset ();
  1442. switch (owner.view) {
  1443. case View.List:
  1444. case View.SmallIcon:
  1445. case View.Details:
  1446. edit_text_box.TextAlign = HorizontalAlignment.Left;
  1447. edit_text_box.Bounds = item.GetBounds (ItemBoundsPortion.Label);
  1448. SizeF sizef = DeviceContext.MeasureString (item.Text, item.Font);
  1449. edit_text_box.Width = (int)sizef.Width + 4;
  1450. edit_text_box.MaxWidth = owner.ClientRectangle.Width - edit_text_box.Bounds.X;
  1451. edit_text_box.WordWrap = false;
  1452. edit_text_box.Multiline = false;
  1453. break;
  1454. case View.LargeIcon:
  1455. edit_text_box.TextAlign = HorizontalAlignment.Center;
  1456. edit_text_box.Bounds = item.GetBounds (ItemBoundsPortion.Label);
  1457. sizef = DeviceContext.MeasureString (item.Text, item.Font);
  1458. edit_text_box.Width = (int)sizef.Width + 4;
  1459. edit_text_box.MaxWidth = item.GetBounds(ItemBoundsPortion.Entire).Width;
  1460. edit_text_box.MaxHeight = owner.ClientRectangle.Height - edit_text_box.Bounds.Y;
  1461. edit_text_box.WordWrap = true;
  1462. edit_text_box.Multiline = true;
  1463. break;
  1464. }
  1465. edit_text_box.Text = item.Text;
  1466. edit_text_box.Font = item.Font;
  1467. edit_text_box.Visible = true;
  1468. edit_text_box.Focus ();
  1469. edit_text_box.SelectAll ();
  1470. edit_args = new LabelEditEventArgs (owner.Items.IndexOf(edit_item));
  1471. owner.OnBeforeLabelEdit (edit_args);
  1472. if (edit_args.CancelEdit)
  1473. EndEdit (item);
  1474. edit_item = item;
  1475. }
  1476. internal void EndEdit (ListViewItem item)
  1477. {
  1478. if (edit_text_box != null && edit_text_box.Visible) {
  1479. edit_text_box.Visible = false;
  1480. }
  1481. if (edit_item != null && edit_item == item) {
  1482. owner.OnAfterLabelEdit (edit_args);
  1483. if (!edit_args.CancelEdit) {
  1484. if (edit_args.Label != null)
  1485. edit_item.Text = edit_args.Label;
  1486. else
  1487. edit_item.Text = edit_text_box.Text;
  1488. }
  1489. }
  1490. edit_item = null;
  1491. }
  1492. internal override void OnPaintInternal (PaintEventArgs pe)
  1493. {
  1494. ThemeEngine.Current.DrawListViewItems (pe.Graphics, pe.ClipRectangle, owner);
  1495. }
  1496. internal override void OnGotFocusInternal (EventArgs e)
  1497. {
  1498. owner.Focus ();
  1499. }
  1500. }
  1501. internal class ListViewLabelEditTextBox : TextBox
  1502. {
  1503. int max_width = -1;
  1504. int min_width = -1;
  1505. int max_height = -1;
  1506. int min_height = -1;
  1507. int old_number_lines = 1;
  1508. SizeF text_size_one_char;
  1509. public ListViewLabelEditTextBox ()
  1510. {
  1511. min_height = DefaultSize.Height;
  1512. text_size_one_char = DeviceContext.MeasureString ("B", Font);
  1513. }
  1514. public int MaxWidth {
  1515. set {
  1516. if (value < min_width)
  1517. max_width = min_width;
  1518. else
  1519. max_width = value;
  1520. }
  1521. }
  1522. public int MaxHeight {
  1523. set {
  1524. if (value < min_height)
  1525. max_height = min_height;
  1526. else
  1527. max_height = value;
  1528. }
  1529. }
  1530. public new int Width {
  1531. get {
  1532. return base.Width;
  1533. }
  1534. set {
  1535. min_width = value;
  1536. base.Width = value;
  1537. }
  1538. }
  1539. public override Font Font {
  1540. get {
  1541. return base.Font;
  1542. }
  1543. set {
  1544. base.Font = value;
  1545. text_size_one_char = DeviceContext.MeasureString ("B", Font);
  1546. }
  1547. }
  1548. protected override void OnTextChanged (EventArgs e)
  1549. {
  1550. SizeF text_size = DeviceContext.MeasureString (Text, Font);
  1551. int new_width = (int)text_size.Width + 8;
  1552. if (!Multiline)
  1553. ResizeTextBoxWidth (new_width);
  1554. else {
  1555. if (Width != max_width)
  1556. ResizeTextBoxWidth (new_width);
  1557. int number_lines = Lines.Length;
  1558. if (number_lines != old_number_lines) {
  1559. int new_height = number_lines * (int)text_size_one_char.Height + 4;
  1560. old_number_lines = number_lines;
  1561. ResizeTextBoxHeight (new_height);
  1562. }
  1563. }
  1564. base.OnTextChanged (e);
  1565. }
  1566. protected override bool IsInputKey (Keys key_data)
  1567. {
  1568. if ((key_data & Keys.Alt) == 0) {
  1569. switch (key_data & Keys.KeyCode) {
  1570. case Keys.Enter:
  1571. return true;
  1572. }
  1573. }
  1574. return base.IsInputKey (key_data);
  1575. }
  1576. protected override void OnKeyDown (KeyEventArgs e)
  1577. {
  1578. if (e.KeyCode == Keys.Return && Visible) {
  1579. this.Visible = false;
  1580. OnEditingFinished (e);
  1581. }
  1582. }
  1583. protected override void OnLostFocus (EventArgs e)
  1584. {
  1585. if (Visible) {
  1586. OnEditingFinished (e);
  1587. }
  1588. }
  1589. protected void OnEditingFinished (EventArgs e)
  1590. {
  1591. EventHandler eh = (EventHandler)(Events [EditingFinishedEvent]);
  1592. if (eh != null)
  1593. eh (this, e);
  1594. }
  1595. private void ResizeTextBoxWidth (int new_width)
  1596. {
  1597. if (new_width > max_width)
  1598. base.Width = max_width;
  1599. else
  1600. if (new_width >= min_width)
  1601. base.Width = new_width;
  1602. else
  1603. base.Width = min_width;
  1604. }
  1605. private void ResizeTextBoxHeight (int new_height)
  1606. {
  1607. if (new_height > max_height)
  1608. base.Height = max_height;
  1609. else
  1610. if (new_height >= min_height)
  1611. base.Height = new_height;
  1612. else
  1613. base.Height = min_height;
  1614. }
  1615. public void Reset ()
  1616. {
  1617. max_width = -1;
  1618. min_width = -1;
  1619. max_height = -1;
  1620. old_number_lines = 1;
  1621. Text = String.Empty;
  1622. Size = DefaultSize;
  1623. }
  1624. static object EditingFinishedEvent = new object ();
  1625. public event EventHandler EditingFinished {
  1626. add { Events.AddHandler (EditingFinishedEvent, value); }
  1627. remove { Events.RemoveHandler (EditingFinishedEvent, value); }
  1628. }
  1629. }
  1630. internal override void OnPaintInternal (PaintEventArgs pe)
  1631. {
  1632. if (updating)
  1633. return;
  1634. CalculateScrollBars ();
  1635. }
  1636. void FocusChanged (object o, EventArgs args)
  1637. {
  1638. if (Items.Count == 0)
  1639. return;
  1640. if (FocusedItem == null)
  1641. SetFocusedItem (Items [0]);
  1642. item_control.Invalidate (FocusedItem.Bounds);
  1643. }
  1644. private void ListView_MouseWheel (object sender, MouseEventArgs me)
  1645. {
  1646. if (Items.Count == 0)
  1647. return;
  1648. int lines = me.Delta / 120;
  1649. if (lines == 0)
  1650. return;
  1651. switch (View) {
  1652. case View.Details:
  1653. case View.SmallIcon:
  1654. Scroll (v_scroll, -Items [0].Bounds.Height * SystemInformation.MouseWheelScrollLines * lines);
  1655. break;
  1656. case View.LargeIcon:
  1657. Scroll (v_scroll, -(Items [0].Bounds.Height + ThemeEngine.Current.ListViewVerticalSpacing) * lines);
  1658. break;
  1659. case View.List:
  1660. Scroll (h_scroll, -Items [0].Bounds.Width * lines);
  1661. break;
  1662. }
  1663. }
  1664. private void ListView_SizeChanged (object sender, EventArgs e)
  1665. {
  1666. CalculateListView (alignment);
  1667. }
  1668. private void SetFocusedItem (ListViewItem item)
  1669. {
  1670. if (focused_item != null)
  1671. focused_item.Focused = false;
  1672. if (item != null)
  1673. item.Focused = true;
  1674. focused_item = item;
  1675. }
  1676. private void HorizontalScroller (object sender, EventArgs e)
  1677. {
  1678. item_control.EndEdit (item_control.edit_item);
  1679. // Avoid unnecessary flickering, when button is
  1680. // kept pressed at the end
  1681. if (h_marker != h_scroll.Value) {
  1682. int pixels = h_marker - h_scroll.Value;
  1683. h_marker = h_scroll.Value;
  1684. if (header_control.Visible)
  1685. XplatUI.ScrollWindow (header_control.Handle, pixels, 0, false);
  1686. XplatUI.ScrollWindow (item_control.Handle, pixels, 0, false);
  1687. }
  1688. }
  1689. private void VerticalScroller (object sender, EventArgs e)
  1690. {
  1691. item_control.EndEdit (item_control.edit_item);
  1692. // Avoid unnecessary flickering, when button is
  1693. // kept pressed at the end
  1694. if (v_marker != v_scroll.Value) {
  1695. int pixels = v_marker - v_scroll.Value;
  1696. Rectangle area = item_control.ClientRectangle;
  1697. v_marker = v_scroll.Value;
  1698. XplatUI.ScrollWindow (item_control.Handle, area, 0, pixels, false);
  1699. }
  1700. }
  1701. #endregion // Internal Methods Properties
  1702. #region Protected Methods
  1703. protected override void CreateHandle ()
  1704. {
  1705. base.CreateHandle ();
  1706. for (int i = 0; i < SelectedItems.Count; i++)
  1707. OnSelectedIndexChanged (EventArgs.Empty);
  1708. }
  1709. protected override void Dispose (bool disposing)
  1710. {
  1711. if (disposing) {
  1712. h_scroll.Dispose ();
  1713. v_scroll.Dispose ();
  1714. large_image_list = null;
  1715. small_image_list = null;
  1716. state_image_list = null;
  1717. }
  1718. base.Dispose (disposing);
  1719. }
  1720. protected override bool IsInputKey (Keys keyData)
  1721. {
  1722. switch (keyData) {
  1723. case Keys.Up:
  1724. case Keys.Down:
  1725. case Keys.PageUp:
  1726. case Keys.PageDown:
  1727. case Keys.Right:
  1728. case Keys.Left:
  1729. case Keys.End:
  1730. case Keys.Home:
  1731. return true;
  1732. default:
  1733. break;
  1734. }
  1735. return base.IsInputKey (keyData);
  1736. }
  1737. protected virtual void OnAfterLabelEdit (LabelEditEventArgs e)
  1738. {
  1739. LabelEditEventHandler eh = (LabelEditEventHandler)(Events [AfterLabelEditEvent]);
  1740. if (eh != null)
  1741. eh (this, e);
  1742. }
  1743. protected virtual void OnBeforeLabelEdit (LabelEditEventArgs e)
  1744. {
  1745. LabelEditEventHandler eh = (LabelEditEventHandler)(Events [BeforeLabelEditEvent]);
  1746. if (eh != null)
  1747. eh (this, e);
  1748. }
  1749. protected virtual void OnColumnClick (ColumnClickEventArgs e)
  1750. {
  1751. ColumnClickEventHandler eh = (ColumnClickEventHandler)(Events [ColumnClickEvent]);
  1752. if (eh != null)
  1753. eh (this, e);
  1754. }
  1755. protected override void OnEnabledChanged (EventArgs e)
  1756. {
  1757. base.OnEnabledChanged (e);
  1758. }
  1759. protected override void OnFontChanged (EventArgs e)
  1760. {
  1761. base.OnFontChanged (e);
  1762. Redraw (true);
  1763. }
  1764. protected override void OnHandleCreated (EventArgs e)
  1765. {
  1766. base.OnHandleCreated (e);
  1767. Sort ();
  1768. }
  1769. protected override void OnHandleDestroyed (EventArgs e)
  1770. {
  1771. base.OnHandleDestroyed (e);
  1772. }
  1773. protected virtual void OnItemActivate (EventArgs e)
  1774. {
  1775. EventHandler eh = (EventHandler)(Events [ItemActivateEvent]);
  1776. if (eh != null)
  1777. eh (this, e);
  1778. }
  1779. protected virtual void OnItemCheck (ItemCheckEventArgs ice)
  1780. {
  1781. EventHandler eh = (EventHandler)(Events [ItemCheckEvent]);
  1782. if (eh != null)
  1783. eh (this, ice);
  1784. }
  1785. protected virtual void OnItemDrag (ItemDragEventArgs e)
  1786. {
  1787. EventHandler eh = (EventHandler)(Events [ItemDragEvent]);
  1788. if (eh != null)
  1789. eh (this, e);
  1790. }
  1791. protected virtual void OnSelectedIndexChanged (EventArgs e)
  1792. {
  1793. EventHandler eh = (EventHandler)(Events [SelectedIndexChangedEvent]);
  1794. if (eh != null)
  1795. eh (this, e);
  1796. }
  1797. protected override void OnSystemColorsChanged (EventArgs e)
  1798. {
  1799. base.OnSystemColorsChanged (e);
  1800. }
  1801. protected void RealizeProperties ()
  1802. {
  1803. // FIXME: TODO
  1804. }
  1805. protected void UpdateExtendedStyles ()
  1806. {
  1807. // FIXME: TODO
  1808. }
  1809. protected override void WndProc (ref Message m)
  1810. {
  1811. base.WndProc (ref m);
  1812. }
  1813. #endregion // Protected Methods
  1814. #region Public Instance Methods
  1815. public void ArrangeIcons ()
  1816. {
  1817. ArrangeIcons (this.alignment);
  1818. }
  1819. public void ArrangeIcons (ListViewAlignment alignment)
  1820. {
  1821. // Icons are arranged only if view is set to LargeIcon or SmallIcon
  1822. if (view == View.LargeIcon || view == View.SmallIcon) {
  1823. this.CalculateListView (alignment);
  1824. // we have done the calculations already
  1825. this.Redraw (false);
  1826. }
  1827. }
  1828. public void BeginUpdate ()
  1829. {
  1830. // flag to avoid painting
  1831. updating = true;
  1832. }
  1833. public void Clear ()
  1834. {
  1835. columns.Clear ();
  1836. items.Clear (); // Redraw (true) called here
  1837. }
  1838. public void EndUpdate ()
  1839. {
  1840. // flag to avoid painting
  1841. updating = false;
  1842. // probably, now we need a redraw with recalculations
  1843. this.Redraw (true);
  1844. }
  1845. public void EnsureVisible (int index)
  1846. {
  1847. if (index < 0 || index >= items.Count || scrollable == false)
  1848. return;
  1849. Rectangle view_rect = item_control.ClientRectangle;
  1850. Rectangle bounds = items [index].Bounds;
  1851. if (view_rect.Contains (bounds))
  1852. return;
  1853. if (bounds.Left < 0)
  1854. h_scroll.Value += bounds.Left;
  1855. else if (bounds.Right > view_rect.Right)
  1856. h_scroll.Value += (bounds.Right - view_rect.Right);
  1857. if (bounds.Top < 0)
  1858. v_scroll.Value += bounds.Top;
  1859. else if (bounds.Bottom > view_rect.Bottom)
  1860. v_scroll.Value += (bounds.Bottom - view_rect.Bottom);
  1861. }
  1862. public ListViewItem GetItemAt (int x, int y)
  1863. {
  1864. foreach (ListViewItem item in items) {
  1865. if (item.Bounds.Contains (x, y))
  1866. return item;
  1867. }
  1868. return null;
  1869. }
  1870. public Rectangle GetItemRect (int index)
  1871. {
  1872. return GetItemRect (index, ItemBoundsPortion.Entire);
  1873. }
  1874. public Rectangle GetItemRect (int index, ItemBoundsPortion portion)
  1875. {
  1876. if (index < 0 || index >= items.Count)
  1877. throw new IndexOutOfRangeException ("index");
  1878. return items [index].GetBounds (portion);
  1879. }
  1880. public void Sort ()
  1881. {
  1882. Sort (true);
  1883. }
  1884. // we need this overload to reuse the logic for sorting, while allowing
  1885. // redrawing to be done by caller or have it done by this method when
  1886. // sorting is really performed
  1887. //
  1888. // ListViewItemCollection's Add and AddRange methods call this overload
  1889. // with redraw set to false, as they take care of redrawing themselves
  1890. // (they even want to redraw the listview if no sort is performed, as
  1891. // an item was added), while ListView.Sort () only wants to redraw if
  1892. // sorting was actually performed
  1893. private void Sort (bool redraw)
  1894. {
  1895. if (!IsHandleCreated || item_sorter == null) {
  1896. return;
  1897. }
  1898. items.Sort (item_sorter);
  1899. if (redraw)
  1900. this.Redraw (true);
  1901. }
  1902. public override string ToString ()
  1903. {
  1904. int count = this.Items.Count;
  1905. if (count == 0)
  1906. return string.Format ("System.Windows.Forms.ListView, Items.Count: 0");
  1907. else
  1908. return string.Format ("System.Windows.Forms.ListView, Items.Count: {0}, Items[0]: {1}", count, this.Items [0].ToString ());
  1909. }
  1910. #endregion // Public Instance Methods
  1911. #region Subclasses
  1912. class HeaderControl : Control {
  1913. ListView owner;
  1914. bool column_resize_active = false;
  1915. ColumnHeader resize_column;
  1916. ColumnHeader clicked_column;
  1917. ColumnHeader drag_column;
  1918. int drag_x;
  1919. int drag_to_index = -1;
  1920. public HeaderControl (ListView owner)
  1921. {
  1922. this.owner = owner;
  1923. MouseDown += new MouseEventHandler (HeaderMouseDown);
  1924. MouseMove += new MouseEventHandler (HeaderMouseMove);
  1925. MouseUp += new MouseEventHandler (HeaderMouseUp);
  1926. }
  1927. private ColumnHeader ColumnAtX (int x)
  1928. {
  1929. Point pt = new Point (x, 0);
  1930. ColumnHeader result = null;
  1931. foreach (ColumnHeader col in owner.Columns) {
  1932. if (col.Rect.Contains (pt)) {
  1933. result = col;
  1934. break;
  1935. }
  1936. }
  1937. return result;
  1938. }
  1939. private int GetReorderedIndex (ColumnHeader col)
  1940. {
  1941. if (owner.reordered_column_indices == null)
  1942. return col.Index;
  1943. else
  1944. for (int i = 0; i < owner.Columns.Count; i++)
  1945. if (owner.reordered_column_indices [i] == col.Index)
  1946. return i;
  1947. throw new Exception ("Column index missing from reordered array");
  1948. }
  1949. private void HeaderMouseDown (object sender, MouseEventArgs me)
  1950. {
  1951. if (resize_column != null) {
  1952. column_resize_active = true;
  1953. Capture = true;
  1954. return;
  1955. }
  1956. clicked_column = ColumnAtX (me.X + owner.h_marker);
  1957. if (clicked_column != null) {
  1958. Capture = true;
  1959. if (owner.AllowColumnReorder) {
  1960. drag_x = me.X;
  1961. drag_column = (ColumnHeader) (clicked_column as ICloneable).Clone ();
  1962. drag_column.column_rect = clicked_column.Rect;
  1963. drag_to_index = GetReorderedIndex (clicked_column);
  1964. }
  1965. clicked_column.pressed = true;
  1966. Rectangle bounds = clicked_column.Rect;
  1967. bounds.X -= owner.h_marker;
  1968. Invalidate (bounds);
  1969. return;
  1970. }
  1971. }
  1972. private void HeaderMouseMove (object sender, MouseEventArgs me)
  1973. {
  1974. Point pt = new Point (me.X + owner.h_marker, me.Y);
  1975. if (column_resize_active) {
  1976. resize_column.Width = pt.X - resize_column.X;
  1977. if (resize_column.Width < 0)
  1978. resize_column.Width = 0;
  1979. return;
  1980. }
  1981. resize_column = null;
  1982. if (clicked_column != null) {
  1983. if (owner.AllowColumnReorder) {
  1984. Rectangle r;
  1985. r = drag_column.column_rect;
  1986. r.X = clicked_column.Rect.X + me.X - drag_x;
  1987. drag_column.column_rect = r;
  1988. int x = me.X + owner.h_marker;
  1989. ColumnHeader over = ColumnAtX (x);
  1990. if (over == null)
  1991. drag_to_index = owner.Columns.Count;
  1992. else if (x < over.X + over.Width / 2)
  1993. drag_to_index = GetReorderedIndex (over);
  1994. else
  1995. drag_to_index = GetReorderedIndex (over) + 1;
  1996. Invalidate ();
  1997. } else {
  1998. ColumnHeader over = ColumnAtX (me.X + owner.h_marker);
  1999. bool pressed = clicked_column.pressed;
  2000. clicked_column.pressed = over == clicked_column;
  2001. if (clicked_column.pressed ^ pressed) {
  2002. Rectangle bounds = clicked_column.Rect;
  2003. bounds.X -= owner.h_marker;
  2004. Invalidate (bounds);
  2005. }
  2006. }
  2007. return;
  2008. }
  2009. for (int i = 0; i < owner.Columns.Count; i++) {
  2010. Rectangle zone = owner.Columns [i].Rect;
  2011. zone.X = zone.Right - 5;
  2012. zone.Width = 10;
  2013. if (zone.Contains (pt)) {
  2014. if (i < owner.Columns.Count - 1 && owner.Columns [i + 1].Width == 0)
  2015. i++;
  2016. resize_column = owner.Columns [i];
  2017. break;
  2018. }
  2019. }
  2020. if (resize_column == null)
  2021. Cursor = Cursors.Default;
  2022. else
  2023. Cursor = Cursors.VSplit;
  2024. }
  2025. void HeaderMouseUp (object sender, MouseEventArgs me)
  2026. {
  2027. Capture = false;
  2028. if (column_resize_active) {
  2029. column_resize_active = false;
  2030. resize_column = null;
  2031. Cursor = Cursors.Default;
  2032. return;
  2033. }
  2034. if (clicked_column != null && clicked_column.pressed) {
  2035. clicked_column.pressed = false;
  2036. Rectangle bounds = clicked_column.Rect;
  2037. bounds.X -= owner.h_marker;
  2038. Invalidate (bounds);
  2039. owner.OnColumnClick (new ColumnClickEventArgs (clicked_column.Index));
  2040. }
  2041. if (drag_column != null && owner.AllowColumnReorder) {
  2042. drag_column = null;
  2043. if (drag_to_index > GetReorderedIndex (clicked_column))
  2044. drag_to_index--;
  2045. if (owner.GetReorderedColumn (drag_to_index) != clicked_column)
  2046. owner.ReorderColumn (clicked_column, drag_to_index);
  2047. drag_to_index = -1;
  2048. Invalidate ();
  2049. }
  2050. clicked_column = null;
  2051. }
  2052. internal override void OnPaintInternal (PaintEventArgs pe)
  2053. {
  2054. if (owner.updating)
  2055. return;
  2056. Theme theme = ThemeEngine.Current;
  2057. theme.DrawListViewHeader (pe.Graphics, pe.ClipRectangle, this.owner);
  2058. if (drag_column == null)
  2059. return;
  2060. int target_x;
  2061. if (drag_to_index == owner.Columns.Count)
  2062. target_x = owner.GetReorderedColumn (drag_to_index - 1).Rect.Right - owner.h_marker;
  2063. else
  2064. target_x = owner.GetReorderedColumn (drag_to_index).Rect.X - owner.h_marker;
  2065. theme.DrawListViewHeaderDragDetails (pe.Graphics, owner, drag_column, target_x);
  2066. }
  2067. protected override void WndProc (ref Message m)
  2068. {
  2069. switch ((Msg)m.Msg) {
  2070. case Msg.WM_SETFOCUS:
  2071. owner.Focus ();
  2072. break;
  2073. default:
  2074. base.WndProc (ref m);
  2075. break;
  2076. }
  2077. }
  2078. }
  2079. private class ItemComparer : IComparer {
  2080. readonly SortOrder sort_order;
  2081. public ItemComparer (SortOrder sortOrder)
  2082. {
  2083. sort_order = sortOrder;
  2084. }
  2085. public int Compare (object x, object y)
  2086. {
  2087. ListViewItem item_x = x as ListViewItem;
  2088. ListViewItem item_y = y as ListViewItem;
  2089. if (sort_order == SortOrder.Ascending)
  2090. return String.Compare (item_x.Text, item_y.Text);
  2091. else
  2092. return String.Compare (item_y.Text, item_x.Text);
  2093. }
  2094. }
  2095. public class CheckedIndexCollection : IList, ICollection, IEnumerable
  2096. {
  2097. private readonly ListView owner;
  2098. #region Public Constructor
  2099. public CheckedIndexCollection (ListView owner)
  2100. {
  2101. this.owner = owner;
  2102. }
  2103. #endregion // Public Constructor
  2104. #region Public Properties
  2105. [Browsable (false)]
  2106. public int Count {
  2107. get { return owner.CheckedItems.Count; }
  2108. }
  2109. public bool IsReadOnly {
  2110. get { return true; }
  2111. }
  2112. public int this [int index] {
  2113. get {
  2114. int [] indices = GetIndices ();
  2115. if (index < 0 || index >= indices.Length)
  2116. throw new ArgumentOutOfRangeException ("index");
  2117. return indices [index];
  2118. }
  2119. }
  2120. bool ICollection.IsSynchronized {
  2121. get { return false; }
  2122. }
  2123. object ICollection.SyncRoot {
  2124. get { return this; }
  2125. }
  2126. bool IList.IsFixedSize {
  2127. get { return true; }
  2128. }
  2129. object IList.this [int index] {
  2130. get { return this [index]; }
  2131. set { throw new NotSupportedException ("SetItem operation is not supported."); }
  2132. }
  2133. #endregion // Public Properties
  2134. #region Public Methods
  2135. public bool Contains (int checkedIndex)
  2136. {
  2137. int [] indices = GetIndices ();
  2138. for (int i = 0; i < indices.Length; i++) {
  2139. if (indices [i] == checkedIndex)
  2140. return true;
  2141. }
  2142. return false;
  2143. }
  2144. public IEnumerator GetEnumerator ()
  2145. {
  2146. int [] indices = GetIndices ();
  2147. return indices.GetEnumerator ();
  2148. }
  2149. void ICollection.CopyTo (Array dest, int index)
  2150. {
  2151. int [] indices = GetIndices ();
  2152. Array.Copy (indices, 0, dest, index, indices.Length);
  2153. }
  2154. int IList.Add (object value)
  2155. {
  2156. throw new NotSupportedException ("Add operation is not supported.");
  2157. }
  2158. void IList.Clear ()
  2159. {
  2160. throw new NotSupportedException ("Clear operation is not supported.");
  2161. }
  2162. bool IList.Contains (object checkedIndex)
  2163. {
  2164. if (!(checkedIndex is int))
  2165. return false;
  2166. return Contains ((int) checkedIndex);
  2167. }
  2168. int IList.IndexOf (object checkedIndex)
  2169. {
  2170. if (!(checkedIndex is int))
  2171. return -1;
  2172. return IndexOf ((int) checkedIndex);
  2173. }
  2174. void IList.Insert (int index, object value)
  2175. {
  2176. throw new NotSupportedException ("Insert operation is not supported.");
  2177. }
  2178. void IList.Remove (object value)
  2179. {
  2180. throw new NotSupportedException ("Remove operation is not supported.");
  2181. }
  2182. void IList.RemoveAt (int index)
  2183. {
  2184. throw new NotSupportedException ("RemoveAt operation is not supported.");
  2185. }
  2186. public int IndexOf (int checkedIndex)
  2187. {
  2188. int [] indices = GetIndices ();
  2189. for (int i = 0; i < indices.Length; i++) {
  2190. if (indices [i] == checkedIndex)
  2191. return i;
  2192. }
  2193. return -1;
  2194. }
  2195. #endregion // Public Methods
  2196. private int [] GetIndices ()
  2197. {
  2198. ArrayList checked_items = owner.CheckedItems.List;
  2199. int [] indices = new int [checked_items.Count];
  2200. for (int i = 0; i < checked_items.Count; i++) {
  2201. ListViewItem item = (ListViewItem) checked_items [i];
  2202. indices [i] = item.Index;
  2203. }
  2204. return indices;
  2205. }
  2206. } // CheckedIndexCollection
  2207. public class CheckedListViewItemCollection : IList, ICollection, IEnumerable
  2208. {
  2209. private readonly ListView owner;
  2210. private ArrayList list;
  2211. #region Public Constructor
  2212. public CheckedListViewItemCollection (ListView owner)
  2213. {
  2214. this.owner = owner;
  2215. this.owner.Items.Changed += new CollectionChangedHandler (
  2216. ItemsCollection_Changed);
  2217. }
  2218. #endregion // Public Constructor
  2219. #region Public Properties
  2220. [Browsable (false)]
  2221. public int Count {
  2222. get {
  2223. if (!owner.CheckBoxes)
  2224. return 0;
  2225. return List.Count;
  2226. }
  2227. }
  2228. public bool IsReadOnly {
  2229. get { return true; }
  2230. }
  2231. public ListViewItem this [int index] {
  2232. get {
  2233. ArrayList checked_items = List;
  2234. if (index < 0 || index >= checked_items.Count)
  2235. throw new ArgumentOutOfRangeException ("index");
  2236. return (ListViewItem) checked_items [index];
  2237. }
  2238. }
  2239. bool ICollection.IsSynchronized {
  2240. get { return false; }
  2241. }
  2242. object ICollection.SyncRoot {
  2243. get { return this; }
  2244. }
  2245. bool IList.IsFixedSize {
  2246. get { return true; }
  2247. }
  2248. object IList.this [int index] {
  2249. get { return this [index]; }
  2250. set { throw new NotSupportedException ("SetItem operation is not supported."); }
  2251. }
  2252. #endregion // Public Properties
  2253. #region Public Methods
  2254. public bool Contains (ListViewItem item)
  2255. {
  2256. if (!owner.CheckBoxes)
  2257. return false;
  2258. return List.Contains (item);
  2259. }
  2260. public void CopyTo (Array dest, int index)
  2261. {
  2262. if (!owner.CheckBoxes)
  2263. return;
  2264. List.CopyTo (dest, index);
  2265. }
  2266. public IEnumerator GetEnumerator ()
  2267. {
  2268. if (!owner.CheckBoxes)
  2269. return (new ListViewItem [0]).GetEnumerator ();
  2270. return List.GetEnumerator ();
  2271. }
  2272. int IList.Add (object value)
  2273. {
  2274. throw new NotSupportedException ("Add operation is not supported.");
  2275. }
  2276. void IList.Clear ()
  2277. {
  2278. throw new NotSupportedException ("Clear operation is not supported.");
  2279. }
  2280. bool IList.Contains (object item)
  2281. {
  2282. if (!(item is ListViewItem))
  2283. return false;
  2284. return Contains ((ListViewItem) item);
  2285. }
  2286. int IList.IndexOf (object item)
  2287. {
  2288. if (!(item is ListViewItem))
  2289. return -1;
  2290. return IndexOf ((ListViewItem) item);
  2291. }
  2292. void IList.Insert (int index, object value)
  2293. {
  2294. throw new NotSupportedException ("Insert operation is not supported.");
  2295. }
  2296. void IList.Remove (object value)
  2297. {
  2298. throw new NotSupportedException ("Remove operation is not supported.");
  2299. }
  2300. void IList.RemoveAt (int index)
  2301. {
  2302. throw new NotSupportedException ("RemoveAt operation is not supported.");
  2303. }
  2304. public int IndexOf (ListViewItem item)
  2305. {
  2306. if (!owner.CheckBoxes)
  2307. return -1;
  2308. return List.IndexOf (item);
  2309. }
  2310. #endregion // Public Methods
  2311. internal ArrayList List {
  2312. get {
  2313. if (list == null) {
  2314. list = new ArrayList ();
  2315. foreach (ListViewItem item in owner.Items) {
  2316. if (item.Checked)
  2317. list.Add (item);
  2318. }
  2319. }
  2320. return list;
  2321. }
  2322. }
  2323. internal void Reset ()
  2324. {
  2325. // force re-population of list
  2326. list = null;
  2327. }
  2328. private void ItemsCollection_Changed ()
  2329. {
  2330. Reset ();
  2331. }
  2332. } // CheckedListViewItemCollection
  2333. public class ColumnHeaderCollection : IList, ICollection, IEnumerable
  2334. {
  2335. internal ArrayList list;
  2336. private ListView owner;
  2337. #region Public Constructor
  2338. public ColumnHeaderCollection (ListView owner)
  2339. {
  2340. list = new ArrayList ();
  2341. this.owner = owner;
  2342. }
  2343. #endregion // Public Constructor
  2344. #region Public Properties
  2345. [Browsable (false)]
  2346. public int Count {
  2347. get { return list.Count; }
  2348. }
  2349. public bool IsReadOnly {
  2350. get { return false; }
  2351. }
  2352. public virtual ColumnHeader this [int index] {
  2353. get {
  2354. if (index < 0 || index >= list.Count)
  2355. throw new ArgumentOutOfRangeException ("index");
  2356. return (ColumnHeader) list [index];
  2357. }
  2358. }
  2359. bool ICollection.IsSynchronized {
  2360. get { return true; }
  2361. }
  2362. object ICollection.SyncRoot {
  2363. get { return this; }
  2364. }
  2365. bool IList.IsFixedSize {
  2366. get { return list.IsFixedSize; }
  2367. }
  2368. object IList.this [int index] {
  2369. get { return this [index]; }
  2370. set { throw new NotSupportedException ("SetItem operation is not supported."); }
  2371. }
  2372. #endregion // Public Properties
  2373. #region Public Methods
  2374. public virtual int Add (ColumnHeader value)
  2375. {
  2376. int idx;
  2377. value.owner = this.owner;
  2378. idx = list.Add (value);
  2379. if (owner.IsHandleCreated) {
  2380. owner.Redraw (true);
  2381. }
  2382. return idx;
  2383. }
  2384. public virtual ColumnHeader Add (string str, int width, HorizontalAlignment textAlign)
  2385. {
  2386. ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
  2387. this.Add (colHeader);
  2388. return colHeader;
  2389. }
  2390. public virtual void AddRange (ColumnHeader [] values)
  2391. {
  2392. foreach (ColumnHeader colHeader in values) {
  2393. colHeader.owner = this.owner;
  2394. Add (colHeader);
  2395. }
  2396. owner.Redraw (true);
  2397. }
  2398. public virtual void Clear ()
  2399. {
  2400. list.Clear ();
  2401. owner.Redraw (true);
  2402. }
  2403. public bool Contains (ColumnHeader value)
  2404. {
  2405. return list.Contains (value);
  2406. }
  2407. public IEnumerator GetEnumerator ()
  2408. {
  2409. return list.GetEnumerator ();
  2410. }
  2411. void ICollection.CopyTo (Array dest, int index)
  2412. {
  2413. list.CopyTo (dest, index);
  2414. }
  2415. int IList.Add (object value)
  2416. {
  2417. if (! (value is ColumnHeader)) {
  2418. throw new ArgumentException ("Not of type ColumnHeader", "value");
  2419. }
  2420. return this.Add ((ColumnHeader) value);
  2421. }
  2422. bool IList.Contains (object value)
  2423. {
  2424. if (! (value is ColumnHeader)) {
  2425. throw new ArgumentException ("Not of type ColumnHeader", "value");
  2426. }
  2427. return this.Contains ((ColumnHeader) value);
  2428. }
  2429. int IList.IndexOf (object value)
  2430. {
  2431. if (! (value is ColumnHeader)) {
  2432. throw new ArgumentException ("Not of type ColumnHeader", "value");
  2433. }
  2434. return this.IndexOf ((ColumnHeader) value);
  2435. }
  2436. void IList.Insert (int index, object value)
  2437. {
  2438. if (! (value is ColumnHeader)) {
  2439. throw new ArgumentException ("Not of type ColumnHeader", "value");
  2440. }
  2441. this.Insert (index, (ColumnHeader) value);
  2442. }
  2443. void IList.Remove (object value)
  2444. {
  2445. if (! (value is ColumnHeader)) {
  2446. throw new ArgumentException ("Not of type ColumnHeader", "value");
  2447. }
  2448. this.Remove ((ColumnHeader) value);
  2449. }
  2450. public int IndexOf (ColumnHeader value)
  2451. {
  2452. return list.IndexOf (value);
  2453. }
  2454. public void Insert (int index, ColumnHeader value)
  2455. {
  2456. // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
  2457. // but it's really only greater.
  2458. if (index < 0 || index > list.Count)
  2459. throw new ArgumentOutOfRangeException ("index");
  2460. value.owner = this.owner;
  2461. list.Insert (index, value);
  2462. owner.Redraw (true);
  2463. }
  2464. public void Insert (int index, string str, int width, HorizontalAlignment textAlign)
  2465. {
  2466. ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
  2467. this.Insert (index, colHeader);
  2468. }
  2469. public virtual void Remove (ColumnHeader column)
  2470. {
  2471. // TODO: Update Column internal index ?
  2472. list.Remove (column);
  2473. owner.Redraw (true);
  2474. }
  2475. public virtual void RemoveAt (int index)
  2476. {
  2477. if (index < 0 || index >= list.Count)
  2478. throw new ArgumentOutOfRangeException ("index");
  2479. // TODO: Update Column internal index ?
  2480. list.RemoveAt (index);
  2481. owner.Redraw (true);
  2482. }
  2483. #endregion // Public Methods
  2484. } // ColumnHeaderCollection
  2485. public class ListViewItemCollection : IList, ICollection, IEnumerable
  2486. {
  2487. private readonly ArrayList list;
  2488. private readonly ListView owner;
  2489. #region Public Constructor
  2490. public ListViewItemCollection (ListView owner)
  2491. {
  2492. list = new ArrayList ();
  2493. this.owner = owner;
  2494. }
  2495. #endregion // Public Constructor
  2496. #region Public Properties
  2497. [Browsable (false)]
  2498. public int Count {
  2499. get { return list.Count; }
  2500. }
  2501. public bool IsReadOnly {
  2502. get { return false; }
  2503. }
  2504. public virtual ListViewItem this [int displayIndex] {
  2505. get {
  2506. if (displayIndex < 0 || displayIndex >= list.Count)
  2507. throw new ArgumentOutOfRangeException ("displayIndex");
  2508. return (ListViewItem) list [displayIndex];
  2509. }
  2510. set {
  2511. if (displayIndex < 0 || displayIndex >= list.Count)
  2512. throw new ArgumentOutOfRangeException ("displayIndex");
  2513. if (list.Contains (value))
  2514. throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
  2515. if (value.ListView != null && value.ListView != owner)
  2516. throw new ArgumentException ("Cannot add or insert the item '" + value.Text + "' in more than one place. You must first remove it from its current location or clone it.", "value");
  2517. value.Owner = owner;
  2518. list [displayIndex] = value;
  2519. OnChange ();
  2520. owner.Redraw (true);
  2521. }
  2522. }
  2523. #if NET_2_0
  2524. public virtual ListViewItem this [string key] {
  2525. get {
  2526. int idx = IndexOfKey (key);
  2527. if (idx == -1)
  2528. return null;
  2529. return (ListViewItem) list [idx];
  2530. }
  2531. }
  2532. #endif
  2533. bool ICollection.IsSynchronized {
  2534. get { return true; }
  2535. }
  2536. object ICollection.SyncRoot {
  2537. get { return this; }
  2538. }
  2539. bool IList.IsFixedSize {
  2540. get { return list.IsFixedSize; }
  2541. }
  2542. object IList.this [int index] {
  2543. get { return this [index]; }
  2544. set {
  2545. if (value is ListViewItem)
  2546. this [index] = (ListViewItem) value;
  2547. else
  2548. this [index] = new ListViewItem (value.ToString ());
  2549. OnChange ();
  2550. }
  2551. }
  2552. #endregion // Public Properties
  2553. #region Public Methods
  2554. public virtual ListViewItem Add (ListViewItem value)
  2555. {
  2556. if (list.Contains (value))
  2557. throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
  2558. if (value.ListView != null && value.ListView != owner)
  2559. throw new ArgumentException ("Cannot add or insert the item '" + value.Text + "' in more than one place. You must first remove it from its current location or clone it.", "value");
  2560. value.Owner = owner;
  2561. list.Add (value);
  2562. if (this.owner != null)
  2563. {
  2564. owner.Sort (false);
  2565. OnChange ();
  2566. owner.Redraw (true);
  2567. }
  2568. return value;
  2569. }
  2570. public virtual ListViewItem Add (string text)
  2571. {
  2572. ListViewItem item = new ListViewItem (text);
  2573. return this.Add (item);
  2574. }
  2575. public virtual ListViewItem Add (string text, int imageIndex)
  2576. {
  2577. ListViewItem item = new ListViewItem (text, imageIndex);
  2578. return this.Add (item);
  2579. }
  2580. #if NET_2_0
  2581. public virtual ListViewItem Add (string text, string imageKey)
  2582. {
  2583. ListViewItem item = new ListViewItem (text, imageKey);
  2584. return this.Add (item);
  2585. }
  2586. public virtual ListViewItem Add (string key, string text, int imageIndex)
  2587. {
  2588. ListViewItem item = new ListViewItem (text, imageIndex);
  2589. item.Name = key;
  2590. return this.Add (item);
  2591. }
  2592. public virtual ListViewItem Add (string key, string text, string imageKey)
  2593. {
  2594. ListViewItem item = new ListViewItem (text, imageKey);
  2595. item.Name = key;
  2596. return this.Add (item);
  2597. }
  2598. #endif
  2599. public void AddRange (ListViewItem [] values)
  2600. {
  2601. if (values == null)
  2602. throw new ArgumentNullException ("Argument cannot be null!", "values");
  2603. foreach (ListViewItem item in values) {
  2604. this.Add (item);
  2605. }
  2606. }
  2607. #if NET_2_0
  2608. public void AddRange (ListViewItemCollection items)
  2609. {
  2610. if (items == null)
  2611. throw new ArgumentNullException ("Argument cannot be null!", "items");
  2612. ListViewItem[] itemArray = new ListViewItem[items.Count];
  2613. items.CopyTo (itemArray,0);
  2614. this.AddRange (itemArray);
  2615. }
  2616. #endif
  2617. public virtual void Clear ()
  2618. {
  2619. owner.SetFocusedItem (null);
  2620. owner.h_scroll.Value = owner.v_scroll.Value = 0;
  2621. list.Clear ();
  2622. OnChange ();
  2623. owner.Redraw (true);
  2624. }
  2625. public bool Contains (ListViewItem item)
  2626. {
  2627. return list.Contains (item);
  2628. }
  2629. #if NET_2_0
  2630. public virtual bool ContainsKey (string key)
  2631. {
  2632. return IndexOfKey (key) != -1;
  2633. }
  2634. #endif
  2635. public void CopyTo (Array dest, int index)
  2636. {
  2637. list.CopyTo (dest, index);
  2638. }
  2639. #if NET_2_0
  2640. public ListViewItem [] Find (string key, bool searchAllSubitems)
  2641. {
  2642. if (key == null)
  2643. return new ListViewItem [0];
  2644. List<ListViewItem> temp_list = new List<ListViewItem> ();
  2645. for (int i = 0; i < list.Count; i++) {
  2646. ListViewItem lvi = (ListViewItem) list [i];
  2647. if (String.Compare (key, lvi.Name, true) == 0)
  2648. temp_list.Add (lvi);
  2649. }
  2650. ListViewItem [] retval = new ListViewItem [temp_list.Count];
  2651. temp_list.CopyTo (retval);
  2652. return retval;
  2653. }
  2654. #endif
  2655. public IEnumerator GetEnumerator ()
  2656. {
  2657. return list.GetEnumerator ();
  2658. }
  2659. int IList.Add (object item)
  2660. {
  2661. int result;
  2662. ListViewItem li;
  2663. if (item is ListViewItem) {
  2664. li = (ListViewItem) item;
  2665. if (list.Contains (li))
  2666. throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
  2667. if (li.ListView != null && li.ListView != owner)
  2668. throw new ArgumentException ("Cannot add or insert the item '" + li.Text + "' in more than one place. You must first remove it from its current location or clone it.", "item");
  2669. }
  2670. else
  2671. li = new ListViewItem (item.ToString ());
  2672. li.Owner = owner;
  2673. result = list.Add (li);
  2674. OnChange ();
  2675. owner.Redraw (true);
  2676. return result;
  2677. }
  2678. bool IList.Contains (object item)
  2679. {
  2680. return list.Contains (item);
  2681. }
  2682. int IList.IndexOf (object item)
  2683. {
  2684. return list.IndexOf (item);
  2685. }
  2686. void IList.Insert (int index, object item)
  2687. {
  2688. if (item is ListViewItem)
  2689. this.Insert (index, (ListViewItem) item);
  2690. else
  2691. this.Insert (index, item.ToString ());
  2692. }
  2693. void IList.Remove (object item)
  2694. {
  2695. Remove ((ListViewItem) item);
  2696. }
  2697. public int IndexOf (ListViewItem item)
  2698. {
  2699. return list.IndexOf (item);
  2700. }
  2701. #if NET_2_0
  2702. public int IndexOfKey (string key)
  2703. {
  2704. if (key == null || key.Length == 0)
  2705. return -1;
  2706. for (int i = 0; i < list.Count; i++) {
  2707. ListViewItem lvi = (ListViewItem) list [i];
  2708. if (String.Compare (key, lvi.Name, true) == 0)
  2709. return i;
  2710. }
  2711. return -1;
  2712. }
  2713. #endif
  2714. public ListViewItem Insert (int index, ListViewItem item)
  2715. {
  2716. if (index < 0 || index > list.Count)
  2717. throw new ArgumentOutOfRangeException ("index");
  2718. if (list.Contains (item))
  2719. throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
  2720. if (item.ListView != null && item.ListView != owner)
  2721. throw new ArgumentException ("Cannot add or insert the item '" + item.Text + "' in more than one place. You must first remove it from its current location or clone it.", "item");
  2722. item.Owner = owner;
  2723. list.Insert (index, item);
  2724. OnChange ();
  2725. owner.Redraw (true);
  2726. return item;
  2727. }
  2728. public ListViewItem Insert (int index, string text)
  2729. {
  2730. return this.Insert (index, new ListViewItem (text));
  2731. }
  2732. public ListViewItem Insert (int index, string text, int imageIndex)
  2733. {
  2734. return this.Insert (index, new ListViewItem (text, imageIndex));
  2735. }
  2736. #if NET_2_0
  2737. public ListViewItem Insert (int index, string key, string text, int imageIndex)
  2738. {
  2739. ListViewItem lvi = new ListViewItem (text, imageIndex);
  2740. lvi.Name = key;
  2741. return Insert (index, lvi);
  2742. }
  2743. #endif
  2744. public virtual void Remove (ListViewItem item)
  2745. {
  2746. if (!list.Contains (item))
  2747. return;
  2748. bool selection_changed = owner.SelectedItems.Contains (item);
  2749. list.Remove (item);
  2750. OnChange ();
  2751. owner.Redraw (true);
  2752. if (selection_changed)
  2753. owner.OnSelectedIndexChanged (EventArgs.Empty);
  2754. }
  2755. public virtual void RemoveAt (int index)
  2756. {
  2757. if (index < 0 || index >= Count)
  2758. throw new ArgumentOutOfRangeException ("index");
  2759. bool selection_changed = owner.SelectedIndices.Contains (index);
  2760. list.RemoveAt (index);
  2761. OnChange ();
  2762. owner.Redraw (false);
  2763. if (selection_changed)
  2764. owner.OnSelectedIndexChanged (EventArgs.Empty);
  2765. }
  2766. #if NET_2_0
  2767. public void RemoveByKey (string key)
  2768. {
  2769. int idx = IndexOfKey (key);
  2770. if (idx != -1)
  2771. RemoveAt (idx);
  2772. }
  2773. #endif
  2774. #endregion // Public Methods
  2775. internal event CollectionChangedHandler Changed;
  2776. internal void Sort (IComparer comparer)
  2777. {
  2778. list.Sort (comparer);
  2779. OnChange ();
  2780. }
  2781. internal void OnChange ()
  2782. {
  2783. if (Changed != null)
  2784. Changed ();
  2785. }
  2786. } // ListViewItemCollection
  2787. public class SelectedIndexCollection : IList, ICollection, IEnumerable
  2788. {
  2789. private readonly ListView owner;
  2790. #region Public Constructor
  2791. public SelectedIndexCollection (ListView owner)
  2792. {
  2793. this.owner = owner;
  2794. }
  2795. #endregion // Public Constructor
  2796. #region Public Properties
  2797. [Browsable (false)]
  2798. public int Count {
  2799. get {
  2800. return owner.SelectedItems.Count;
  2801. }
  2802. }
  2803. public bool IsReadOnly {
  2804. get {
  2805. #if NET_2_0
  2806. return false;
  2807. #else
  2808. return true;
  2809. #endif
  2810. }
  2811. }
  2812. public int this [int index] {
  2813. get {
  2814. int [] indices = GetIndices ();
  2815. if (index < 0 || index >= indices.Length)
  2816. throw new ArgumentOutOfRangeException ("index");
  2817. return indices [index];
  2818. }
  2819. }
  2820. bool ICollection.IsSynchronized {
  2821. get { return false; }
  2822. }
  2823. object ICollection.SyncRoot {
  2824. get { return this; }
  2825. }
  2826. bool IList.IsFixedSize {
  2827. get {
  2828. #if NET_2_0
  2829. return false;
  2830. #else
  2831. return true;
  2832. #endif
  2833. }
  2834. }
  2835. object IList.this [int index] {
  2836. get { return this [index]; }
  2837. set { throw new NotSupportedException ("SetItem operation is not supported."); }
  2838. }
  2839. #endregion // Public Properties
  2840. #region Public Methods
  2841. public bool Contains (int selectedIndex)
  2842. {
  2843. int [] indices = GetIndices ();
  2844. for (int i = 0; i < indices.Length; i++) {
  2845. if (indices [i] == selectedIndex)
  2846. return true;
  2847. }
  2848. return false;
  2849. }
  2850. public void CopyTo (Array dest, int index)
  2851. {
  2852. int [] indices = GetIndices ();
  2853. Array.Copy (indices, 0, dest, index, indices.Length);
  2854. }
  2855. public IEnumerator GetEnumerator ()
  2856. {
  2857. int [] indices = GetIndices ();
  2858. return indices.GetEnumerator ();
  2859. }
  2860. int IList.Add (object value)
  2861. {
  2862. throw new NotSupportedException ("Add operation is not supported.");
  2863. }
  2864. void IList.Clear ()
  2865. {
  2866. throw new NotSupportedException ("Clear operation is not supported.");
  2867. }
  2868. bool IList.Contains (object selectedIndex)
  2869. {
  2870. if (!(selectedIndex is int))
  2871. return false;
  2872. return Contains ((int) selectedIndex);
  2873. }
  2874. int IList.IndexOf (object selectedIndex)
  2875. {
  2876. if (!(selectedIndex is int))
  2877. return -1;
  2878. return IndexOf ((int) selectedIndex);
  2879. }
  2880. void IList.Insert (int index, object value)
  2881. {
  2882. throw new NotSupportedException ("Insert operation is not supported.");
  2883. }
  2884. void IList.Remove (object value)
  2885. {
  2886. throw new NotSupportedException ("Remove operation is not supported.");
  2887. }
  2888. void IList.RemoveAt (int index)
  2889. {
  2890. throw new NotSupportedException ("RemoveAt operation is not supported.");
  2891. }
  2892. public int IndexOf (int selectedIndex)
  2893. {
  2894. int [] indices = GetIndices ();
  2895. for (int i = 0; i < indices.Length; i++) {
  2896. if (indices [i] == selectedIndex)
  2897. return i;
  2898. }
  2899. return -1;
  2900. }
  2901. #endregion // Public Methods
  2902. private int [] GetIndices ()
  2903. {
  2904. ArrayList selected_items = owner.SelectedItems.List;
  2905. int [] indices = new int [selected_items.Count];
  2906. for (int i = 0; i < selected_items.Count; i++) {
  2907. ListViewItem item = (ListViewItem) selected_items [i];
  2908. indices [i] = item.Index;
  2909. }
  2910. return indices;
  2911. }
  2912. } // SelectedIndexCollection
  2913. public class SelectedListViewItemCollection : IList, ICollection, IEnumerable
  2914. {
  2915. private readonly ListView owner;
  2916. private ArrayList list;
  2917. #region Public Constructor
  2918. public SelectedListViewItemCollection (ListView owner)
  2919. {
  2920. this.owner = owner;
  2921. this.owner.Items.Changed += new CollectionChangedHandler (
  2922. ItemsCollection_Changed);
  2923. }
  2924. #endregion // Public Constructor
  2925. #region Public Properties
  2926. [Browsable (false)]
  2927. public int Count {
  2928. get {
  2929. if (!owner.IsHandleCreated)
  2930. return 0;
  2931. return List.Count;
  2932. }
  2933. }
  2934. public bool IsReadOnly {
  2935. get { return true; }
  2936. }
  2937. public ListViewItem this [int index] {
  2938. get {
  2939. ArrayList selected_items = List;
  2940. if (!owner.IsHandleCreated || index < 0 || index >= selected_items.Count)
  2941. throw new ArgumentOutOfRangeException ("index");
  2942. return (ListViewItem) selected_items [index];
  2943. }
  2944. }
  2945. bool ICollection.IsSynchronized {
  2946. get { return false; }
  2947. }
  2948. object ICollection.SyncRoot {
  2949. get { return this; }
  2950. }
  2951. bool IList.IsFixedSize {
  2952. get { return true; }
  2953. }
  2954. object IList.this [int index] {
  2955. get { return this [index]; }
  2956. set { throw new NotSupportedException ("SetItem operation is not supported."); }
  2957. }
  2958. #endregion // Public Properties
  2959. #region Public Methods
  2960. public void Clear ()
  2961. {
  2962. if (!owner.IsHandleCreated)
  2963. return;
  2964. foreach (ListViewItem item in List)
  2965. item.Selected = false;
  2966. }
  2967. public bool Contains (ListViewItem item)
  2968. {
  2969. if (!owner.IsHandleCreated)
  2970. return false;
  2971. return List.Contains (item);
  2972. }
  2973. public void CopyTo (Array dest, int index)
  2974. {
  2975. if (!owner.IsHandleCreated)
  2976. return;
  2977. List.CopyTo (dest, index);
  2978. }
  2979. public IEnumerator GetEnumerator ()
  2980. {
  2981. if (!owner.IsHandleCreated)
  2982. return (new ListViewItem [0]).GetEnumerator ();
  2983. return List.GetEnumerator ();
  2984. }
  2985. int IList.Add (object value)
  2986. {
  2987. throw new NotSupportedException ("Add operation is not supported.");
  2988. }
  2989. bool IList.Contains (object item)
  2990. {
  2991. if (!(item is ListViewItem))
  2992. return false;
  2993. return Contains ((ListViewItem) item);
  2994. }
  2995. int IList.IndexOf (object item)
  2996. {
  2997. if (!(item is ListViewItem))
  2998. return -1;
  2999. return IndexOf ((ListViewItem) item);
  3000. }
  3001. void IList.Insert (int index, object value)
  3002. {
  3003. throw new NotSupportedException ("Insert operation is not supported.");
  3004. }
  3005. void IList.Remove (object value)
  3006. {
  3007. throw new NotSupportedException ("Remove operation is not supported.");
  3008. }
  3009. void IList.RemoveAt (int index)
  3010. {
  3011. throw new NotSupportedException ("RemoveAt operation is not supported.");
  3012. }
  3013. public int IndexOf (ListViewItem item)
  3014. {
  3015. if (!owner.IsHandleCreated)
  3016. return -1;
  3017. return List.IndexOf (item);
  3018. }
  3019. #endregion // Public Methods
  3020. internal ArrayList List {
  3021. get {
  3022. if (list == null) {
  3023. list = new ArrayList ();
  3024. foreach (ListViewItem item in owner.Items) {
  3025. if (item.Selected)
  3026. list.Add (item);
  3027. }
  3028. }
  3029. return list;
  3030. }
  3031. }
  3032. internal void Reset ()
  3033. {
  3034. // force re-population of list
  3035. list = null;
  3036. }
  3037. private void ItemsCollection_Changed ()
  3038. {
  3039. Reset ();
  3040. }
  3041. } // SelectedListViewItemCollection
  3042. internal delegate void CollectionChangedHandler ();
  3043. #endregion // Subclasses
  3044. }
  3045. }