PageRenderTime 63ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 2ms

/ObjectListView/ObjectListView.cs

https://bitbucket.org/BlueRaja/starbank
C# | 9075 lines | 4805 code | 980 blank | 3290 comment | 1146 complexity | e2e03e0bad28347f094bdfcc5b9c1412 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * ObjectListView - A listview to show various aspects of a collection of objects
  3. *
  4. * Author: Phillip Piper
  5. * Date: 9/10/2006 11:15 AM
  6. *
  7. * Change log
  8. * 2011-05-31 JPP - SelectObject() and SelectObjects() no longer deselect all other rows.
  9. Set the SelectedObject or SelectedObjects property to do that.
  10. * - Added CheckedObjectsEnumerable
  11. * - Made setting CheckedObjects more efficient on large collections
  12. * - Deprecated GetSelectedObject() and GetSelectedObjects()
  13. * 2011-04-25 JPP - Added SubItemChecking event
  14. * - Fixed bug in handling of NewValue on CellEditFinishing event
  15. * 2011-04-12 JPP - Added UseFilterIndicator
  16. * - Added some more localizable messages
  17. * 2011-04-10 JPP - FormatCellEventArgs now has a CellValue property, which is the model value displayed
  18. * by the cell. For example, for the Birthday column, the CellValue might be
  19. * DateTime(1980, 12, 31), whereas the cell's text might be 'Dec 31, 1980'.
  20. * 2011-04-04 JPP - Tweaked UseTranslucentSelection and UseTranslucentHotItem to look (a little) more
  21. * like Vista/Win7.
  22. * - Alternate colours are now only applied in Details view (as they always should have been)
  23. * - Alternate colours are now correctly recalculated after removing objects
  24. * 2011-03-29 JPP - Added SelectColumnsOnRightClickBehaviour to allow the selecting of columns mechanism
  25. * to be changed. Can now be InlineMenu (the default), SubMenu, or ModelDialog.
  26. * - ColumnSelectionForm was moved from the demo into the ObjectListView project itself.
  27. * - Ctrl-C copying is now able to use the DragSource to create the data transfer object.
  28. * 2011-03-19 JPP - All model object comparisons now use Equals rather than == (thanks to vulkanino)
  29. * - [Small Break] GetNextItem() and GetPreviousItem() now accept and return OLVListView
  30. * rather than ListViewItems.
  31. * 2011-03-07 JPP - [Big] Added Excel-style filtering. Right click on a header to show a Filtering menu.
  32. * - Added CellEditKeyEngine to allow key handling when cell editing to be completely customised.
  33. * Add CellEditTabChangesRows and CellEditEnterChangesRows to show some of these abilities.
  34. * 2011-03-06 JPP - Added OLVColumn.AutoCompleteEditorMode in preference to AutoCompleteEditor
  35. * (which is now just a wrapper). Thanks to Clive Haskins
  36. * - Added lots of docs to new classes
  37. * 2011-02-25 JPP - Preserve word wrap settings on TreeListView
  38. * - Resize last group to keep it on screen (thanks to ?)
  39. * 2010-11-16 JPP - Fixed (once and for all) DisplayIndex problem with Generator
  40. * - Changed the serializer used in SaveState()/RestoreState() so that it resolves on
  41. * class name alone.
  42. * - Fixed bug in GroupWithItemCountSingularFormatOrDefault
  43. * - Fixed strange flickering in grouped, owner drawn OLV's using RefreshObject()
  44. * v2.4.1
  45. * 2010-08-25 JPP - Fixed bug where setting OLVColumn.CheckBoxes to false gave it a renderer
  46. * specialized for checkboxes. Oddly, this made Generator created owner drawn
  47. * lists appear to be completely empty.
  48. * - In IDE, all ObjectListView properties are now in a single "ObjectListView" category,
  49. * rather than splitting them between "Appearance" and "Behavior" categories.
  50. * - Added GroupingParameters.GroupComparer to allow groups to be sorted in a customizable fashion.
  51. * - Sorting of items within a group can be disabled by setting
  52. * GroupingParameters.PrimarySortOrder to None.
  53. * 2010-08-24 JPP - Added OLVColumn.IsHeaderVertical to make a column draw its header vertical.
  54. * - Added OLVColumn.HeaderTextAlign to control the alignment of a column's header text.
  55. * - Added HeaderMaximumHeight to limit how tall the header section can become
  56. * 2010-08-18 JPP - Fixed long standing bug where having 0 columns caused a InvalidCast exception.
  57. * - Added IncludeAllColumnsInDataObject property
  58. * - Improved BuildList(bool) so that it preserves scroll position even when
  59. * the listview is grouped.
  60. * 2010-08-08 JPP - Added OLVColumn.HeaderImageKey to allow column headers to have an image.
  61. * - CellEdit validation and finish events now have NewValue property.
  62. * 2010-08-03 JPP - Subitem checkboxes improvments: obey IsEditable, can be hot, can be disabled.
  63. * - No more flickering of selection when tabbing between cells
  64. * - Added EditingCellBorderDecoration to make it clearer which cell is being edited.
  65. * 2010-08-01 JPP - Added ObjectListView.SmoothingMode to control the smoothing of all graphics
  66. * operations
  67. * - Columns now cache their group item format strings so that they still work as
  68. * grouping columns after they have been removed from the listview. This cached
  69. * value is only used when the column is not part of the listview.
  70. * 2010-07-25 JPP - Correctly trigger a Click event when the mouse is clicked.
  71. * 2010-07-16 JPP - Invalidate the control before and after cell editing to make sure it looks right
  72. * 2010-06-23 JPP - Right mouse clicks on checkboxes no longer confuse them
  73. * 2010-06-21 JPP - Avoid bug in underlying ListView control where virtual lists in SmallIcon view
  74. * generate GETTOOLINFO msgs with invalid item indicies.
  75. * - Fixed bug where FastObjectListView would throw an exception when showing hyperlinks
  76. * in any view except Details.
  77. * 2010-06-15 JPP - Fixed bug in ChangeToFilteredColumns() that resulted in column display order
  78. * being lost when a column was hidden.
  79. * - Renamed IsVista property to IsVistaOrLater which more accurately describes its function.
  80. * v2.4
  81. * 2010-04-14 JPP - Prevent object disposed errors when mouse event handlers cause the
  82. * ObjectListView to be destroyed (e.g. closing a form during a
  83. * double click event).
  84. * - Avoid checkbox munging bug in standard ListView when shift clicking on non-primary
  85. * columns when FullRowSelect is true.
  86. * 2010-04-12 JPP - Fixed bug in group sorting (thanks Mike).
  87. * 2010-04-07 JPP - Prevent hyperlink processing from triggering spurious MouseUp events.
  88. * This showed itself by launching the same url multiple times.
  89. * 2010-04-06 JPP - Space filling columns correctly resize upon initial display
  90. * - ShowHeaderInAllViews is better but still not working reliably.
  91. * See comments on property for more details.
  92. * 2010-03-23 JPP - Added ObjectListView.HeaderFormatStyle and OLVColumn.HeaderFormatStyle.
  93. * This makes HeaderFont and HeaderForeColor properties unnecessary --
  94. * they will be marked obsolete in the next version and removed after that.
  95. * 2010-03-16 JPP - Changed object checking so that objects can be pre-checked before they
  96. * are added to the list. Normal ObjectListViews managed "checkedness" in
  97. * the ListViewItem, so this won't work for them, unless check state getters
  98. * and putters have been installed. It will work on on virtual lists (thus fast lists and
  99. * tree views) since they manage their own check state.
  100. * 2010-03-06 JPP - Hide "Items" and "Groups" from the IDE properties grid since they shouldn't be set like that.
  101. * They can still be accessed through "Custom Commands" and there's nothing we can do
  102. * about that.
  103. * 2010-03-05 JPP - Added filtering
  104. * 2010-01-18 JPP - Overlays can be turned off. They also only work on 32-bit displays
  105. * v2.3
  106. * 2009-10-30 JPP - Plugged possible resource leak by using using() with CreateGraphics()
  107. * 2009-10-28 JPP - Fix bug when right clicking in the empty area of the header
  108. * 2009-10-20 JPP - Redraw the control after setting EmptyListMsg property
  109. * v2.3
  110. * 2009-09-30 JPP - Added Dispose() method to properly release resources
  111. * 2009-09-16 JPP - Added OwnerDrawnHeader, which you can set to true if you want to owner draw
  112. * the header yourself.
  113. * 2009-09-15 JPP - Added UseExplorerTheme, which allow complete visual compliance with Vista explorer.
  114. * But see property documentation for its many limitations.
  115. * - Added ShowHeaderInAllViews. To make this work, Columns are no longer
  116. * changed when switching to/from Tile view.
  117. * 2009-09-11 JPP - Added OLVColumn.AutoCompleteEditor to allow the autocomplete of cell editors
  118. * to be disabled.
  119. * 2009-09-01 JPP - Added ObjectListView.TextRenderingHint property which controls the
  120. * text rendering hint of all drawn text.
  121. * 2009-08-28 JPP - [BIG] Added group formatting to supercharge what is possible with groups
  122. * - [BIG] Virtual groups now work
  123. * - Extended MakeGroupies() to handle more aspects of group creation
  124. * 2009-08-19 JPP - Added ability to show basic column commands when header is right clicked
  125. * - Added SelectedRowDecoration, UseTranslucentSelection and UseTranslucentHotItem.
  126. * - Added PrimarySortColumn and PrimarySortOrder
  127. * 2009-08-15 JPP - Correct problems with standard hit test and subitems
  128. * 2009-08-14 JPP - [BIG] Support Decorations
  129. * - [BIG] Added header formatting capabilities: font, color, word wrap
  130. * - Gave ObjectListView its own designer to hide unwanted properties
  131. * - Separated design time stuff into separate file
  132. * - Added FormatRow and FormatCell events
  133. * 2009-08-09 JPP - Get around bug in HitTest when not FullRowSelect
  134. * - Added OLVListItem.GetSubItemBounds() method which works correctly
  135. * for all columns including column 0
  136. * 2009-08-07 JPP - Added Hot* properties that track where the mouse is
  137. * - Added HotItemChanged event
  138. * - Overrode TextAlign on columns so that column 0 can have something other
  139. * than just left alignment. This is only honored when owner drawn.
  140. * v2.2.1
  141. * 2009-08-03 JPP - Subitem edit rectangles always allowed for an image in the cell, even if there was none.
  142. * Now they only allow for an image when there actually is one.
  143. * - Added Bounds property to OLVListItem which handles items being part of collapsed groups.
  144. * 2009-07-29 JPP - Added GetSubItem() methods to ObjectListView and OLVListItem
  145. * 2009-07-26 JPP - Avoided bug in .NET framework involving column 0 of owner drawn listviews not being
  146. * redrawn when the listview was scrolled horizontally (this was a LOT of work to track
  147. * down and fix!)
  148. * - The cell edit rectangle is now correctly calculated when the listview is scrolled
  149. * horizontally.
  150. * 2009-07-14 JPP - If the user clicks/double clicks on a tree list cell, an edit operation will no longer begin
  151. * if the click was to the left of the expander. This is implemented in such a way that
  152. * other renderers can have similar "dead" zones.
  153. * 2009-07-11 JPP - CalculateCellBounds() messed with the FullRowSelect property, which confused the
  154. * tooltip handling on the underlying control. It no longer does this.
  155. * - The cell edit rectangle is now correctly calculated for owner-drawn, non-Details views.
  156. * 2009-07-08 JPP - Added Cell events (CellClicked, CellOver, CellRightClicked)
  157. * - Made BuildList(), AddObject() and RemoveObject() thread-safe
  158. * 2009-07-04 JPP - Space bar now properly toggles checkedness of selected rows
  159. * 2009-07-02 JPP - Fixed bug with tooltips when the underlying Windows control was destroyed.
  160. * - CellToolTipShowing events are now triggered in all views.
  161. * v2.2
  162. * 2009-06-02 JPP - BeforeSortingEventArgs now has a Handled property to let event handlers do
  163. * the item sorting themselves.
  164. * - AlwaysGroupByColumn works again, as does SortGroupItemsByPrimaryColumn and all their
  165. * various permutations.
  166. * - SecondarySortOrder and SecondarySortColumn are now "null" by default
  167. * 2009-05-15 JPP - Fixed bug so that KeyPress events are again triggered
  168. * 2009-05-10 JPP - Removed all unsafe code
  169. * 2009-05-07 JPP - Don't use glass panel for overlays when in design mode. It's too confusing.
  170. * 2009-05-05 JPP - Added Scroll event (thanks to Christophe Hosten for the complete patch to implement this)
  171. * - Added Unfocused foreground and background colors (also thanks to Christophe Hosten)
  172. * 2009-04-29 JPP - Added SelectedColumn property, which puts a slight tint on that column. Combine
  173. * this with TintSortColumn property and the sort column is automatically tinted.
  174. * - Use an overlay to implement "empty list" msg. Default empty list msg is now prettier.
  175. * 2009-04-28 JPP - Fixed bug where DoubleClick events were not triggered when CheckBoxes was true
  176. * 2009-04-23 JPP - Fixed various bugs under Vista.
  177. * - Made groups collapsible - Vista only. Thanks to Crustyapplesniffer.
  178. * - Forward events from DropSink to the control itself. This allows handlers to be defined
  179. * within the IDE for drop events
  180. * 2009-04-16 JPP - Made several properties localizable.
  181. * 2009-04-11 JPP - Correctly renderer checkboxes when RowHeight is non-standard
  182. * 2009-04-11 JPP - Implemented overlay architecture, based on CustomDraw scheme.
  183. * This unified drag drop feedback, empty list msgs and overlay images.
  184. * - Added OverlayImage and friends, which allows an image to be drawn
  185. * transparently over the listview
  186. * 2009-04-10 JPP - Fixed long-standing annoying flicker on owner drawn virtual lists!
  187. * This means, amongst other things, that grid lines no longer get confused,
  188. * and drag-select no longer flickers.
  189. * 2009-04-07 JPP - Calculate edit rectangles more accurately
  190. * 2009-04-06 JPP - Double-clicking no longer toggles the checkbox
  191. * - Double-clicking on a checkbox no longer confuses the checkbox
  192. * 2009-03-16 JPP - Optimized the build of autocomplete lists
  193. * v2.1
  194. * 2009-02-24 JPP - Fix bug where double-clicking VERY quickly on two different cells
  195. * could give two editors
  196. * - Maintain focused item when rebuilding list (SF #2547060)
  197. * 2009-02-22 JPP - Reworked checkboxes so that events are triggered for virtual lists
  198. * 2009-02-15 JPP - Added ObjectListView.ConfigureAutoComplete utility method
  199. * 2009-02-02 JPP - Fixed bug with AlwaysGroupByColumn where column header clicks would not resort groups.
  200. * 2009-02-01 JPP - OLVColumn.CheckBoxes and TriStateCheckBoxes now work.
  201. * 2009-01-28 JPP - Complete overhaul of renderers!
  202. * - Use IRenderer
  203. * - Added ObjectListView.ItemRenderer to draw whole items
  204. * 2009-01-23 JPP - Simple Checkboxes now work properly
  205. * - Added TriStateCheckBoxes property to control whether the user can
  206. * set the row checkbox to have the Indeterminate value
  207. * - CheckState property is now just a wrapper around the StateImageIndex property
  208. * 2009-01-20 JPP - Changed to always draw columns when owner drawn, rather than falling back on DrawDefault.
  209. * This simplified several owner drawn problems
  210. * - Added DefaultRenderer property to help with the above
  211. * - HotItem background color is applied to all cells even when FullRowSelect is false
  212. * - Allow grouping by CheckedAspectName columns
  213. * - Commented out experimental animations. Still needs work.
  214. * 2009-01-17 JPP - Added HotItemStyle and UseHotItem to highlight the row under the cursor
  215. * - Added UseCustomSelectionColors property
  216. * - Owner draw mode now honors ForeColor and BackColor settings on the list
  217. * 2009-01-16 JPP - Changed to use EditorRegistry rather than hard coding cell editors
  218. * 2009-01-10 JPP - Changed to use Equals() method rather than == to compare model objects.
  219. * v2.0.1
  220. * 2009-01-08 JPP - Fixed long-standing "multiple columns generated" problem.
  221. * Thanks to pinkjones for his help with solving this one!
  222. * - Added EnsureGroupVisible()
  223. * 2009-01-07 JPP - Made all public and protected methods virtual
  224. * - FinishCellEditing, PossibleFinishCellEditing and CancelCellEditing are now public
  225. * 2008-12-20 JPP - Fixed bug with group comparisons when a group key was null (SF#2445761)
  226. * 2008-12-19 JPP - Fixed bug with space filling columns and layout events
  227. * - Fixed RowHeight so that it only changes the row height, not the width of the images.
  228. * v2.0
  229. * 2008-12-10 JPP - Handle Backspace key. Resets the seach-by-typing state without delay
  230. * - Made some changes to the column collection editor to try and avoid
  231. * the multiple column generation problem.
  232. * - Updated some documentation
  233. * 2008-12-07 JPP - Search-by-typing now works when showing groups
  234. * - Added BeforeSearching and AfterSearching events which are triggered when the user types
  235. * into the list.
  236. * - Added secondary sort information to Before/AfterSorting events
  237. * - Reorganized group sorting code. Now triggers Sorting events.
  238. * - Added GetItemIndexInDisplayOrder()
  239. * - Tweaked in the interaction of the column editor with the IDE so that we (normally)
  240. * don't rely on a hack to find the owning ObjectListView
  241. * - Changed all 'DefaultValue(typeof(Color), "Empty")' to 'DefaultValue(typeof(Color), "")'
  242. * since the first does not given Color.Empty as I thought, but the second does.
  243. * 2008-11-28 JPP - Fixed long standing bug with horizontal scrollbar when shrinking the window.
  244. * (thanks to Bartosz Borowik)
  245. * 2008-11-25 JPP - Added support for dynamic tooltips
  246. * - Split out comparers and header controls stuff into their own files
  247. * 2008-11-21 JPP - Fixed bug where enabling grouping when there was not a sort column would not
  248. * produce a grouped list. Grouping column now defaults to column 0.
  249. * - Preserve selection on virtual lists when sorting
  250. * 2008-11-20 JPP - Added ability to search by sort column to ObjectListView. Unified this with
  251. * ability that was already in VirtualObjectListView
  252. * 2008-11-19 JPP - Fixed bug in ChangeToFilteredColumns() where DisplayOrder was not always restored correctly.
  253. * 2008-10-29 JPP - Event argument blocks moved to directly within the namespace, rather than being
  254. * nested inside ObjectListView class.
  255. * - Removed OLVColumn.CellEditor since it was never used.
  256. * - Marked OLVColumn.AspectGetterAutoGenerated as obsolete (it has not been used for
  257. * several versions now).
  258. * 2008-10-28 JPP - SelectedObjects is now an IList, rather than an ArrayList. This allows
  259. * it to accept generic list (eg List<File>).
  260. * 2008-10-09 JPP - Support indeterminate checkbox values.
  261. * [BREAKING CHANGE] CheckStateGetter/CheckStatePutter now use CheckState types only.
  262. * BooleanCheckStateGetter and BooleanCheckStatePutter added to ease transition.
  263. * 2008-10-08 JPP - Added setFocus parameter to SelectObject(), which allows focus to be set
  264. * at the same time as selecting.
  265. * 2008-09-27 JPP - BIG CHANGE: Fissioned this file into separate files for each component
  266. * 2008-09-24 JPP - Corrected bug with owner drawn lists where a column 0 with a renderer
  267. * would draw at column 0 even if column 0 was dragged to another position.
  268. * - Correctly handle space filling columns when columns are added/removed
  269. * 2008-09-16 JPP - Consistently use try..finally for BeginUpdate()/EndUpdate() pairs
  270. * 2008-08-24 JPP - If LastSortOrder is None when adding objects, don't force a resort.
  271. * 2008-08-22 JPP - Catch and ignore some problems with setting TopIndex on FastObjectListViews.
  272. * 2008-08-05 JPP - In the right-click column select menu, columns are now sorted by display order, rather than alphabetically
  273. * v1.13
  274. * 2008-07-23 JPP - Consistently use copy-on-write semantics with Add/RemoveObject methods
  275. * 2008-07-10 JPP - Enable validation on cell editors through a CellEditValidating event.
  276. * (thanks to Artiom Chilaru for the initial suggestion and implementation).
  277. * 2008-07-09 JPP - Added HeaderControl.Handle to allow OLV to be used within UserControls.
  278. * (thanks to Michael Coffey for tracking this down).
  279. * 2008-06-23 JPP - Split the more generally useful CopyObjectsToClipboard() method
  280. * out of CopySelectionToClipboard()
  281. * 2008-06-22 JPP - Added AlwaysGroupByColumn and AlwaysGroupBySortOrder, which
  282. * force the list view to always be grouped by a particular column.
  283. * 2008-05-31 JPP - Allow check boxes on FastObjectListViews
  284. * - Added CheckedObject and CheckedObjects properties
  285. * 2008-05-11 JPP - Allow selection foreground and background colors to be changed.
  286. * Windows doesn't allow this, so we can only make it happen when owner
  287. * drawing. Set the HighlightForegroundColor and HighlightBackgroundColor
  288. * properties and then call EnableCustomSelectionColors().
  289. * v1.12
  290. * 2008-05-08 JPP - Fixed bug where the column select menu would not appear if the
  291. * ObjectListView has a context menu installed.
  292. * 2008-05-05 JPP - Non detail views can now be owner drawn. The renderer installed for
  293. * primary column is given the chance to render the whole item.
  294. * See BusinessCardRenderer in the demo for an example.
  295. * - BREAKING CHANGE: RenderDelegate now returns a bool to indicate if default
  296. * rendering should be done. Previously returned void. Only important if your
  297. * code used RendererDelegate directly. Renderers derived from BaseRenderer
  298. * are unchanged.
  299. * 2008-05-03 JPP - Changed cell editing to use values directly when the values are Strings.
  300. * Previously, values were always handed to the AspectToStringConverter.
  301. * - When editing a cell, tabbing no longer tries to edit the next subitem
  302. * when not in details view!
  303. * 2008-05-02 JPP - MappedImageRenderer can now handle a Aspects that return a collection
  304. * of values. Each value will be drawn as its own image.
  305. * - Made AddObjects() and RemoveObjects() work for all flavours (or at least not crash)
  306. * - Fixed bug with clearing virtual lists that has been scrolled vertically
  307. * - Made TopItemIndex work with virtual lists.
  308. * 2008-05-01 JPP - Added AddObjects() and RemoveObjects() to allow faster mods to the list
  309. * - Reorganised public properties. Now alphabetical.
  310. * - Made the class ObjectListViewState internal, as it always should have been.
  311. * v1.11
  312. * 2008-04-29 JPP - Preserve scroll position when building the list or changing columns.
  313. * - Added TopItemIndex property. Due to problems with the underlying control, this
  314. * property is not always reliable. See property docs for info.
  315. * 2008-04-27 JPP - Added SelectedIndex property.
  316. * - Use a different, more general strategy to handle Invoke(). Removed all delegates
  317. * that were only declared to support Invoke().
  318. * - Check all native structures for 64-bit correctness.
  319. * 2008-04-25 JPP - Released on SourceForge.
  320. * 2008-04-13 JPP - Added ColumnRightClick event.
  321. * - Made the assembly CLS-compliant. To do this, our cell editors were made internal, and
  322. * the constraint on FlagRenderer template parameter was removed (the type must still
  323. * be an IConvertible, but if it isn't, the error will be caught at runtime, not compile time).
  324. * 2008-04-12 JPP - Changed HandleHeaderRightClick() to have a columnIndex parameter, which tells
  325. * exactly which column was right-clicked.
  326. * 2008-03-31 JPP - Added SaveState() and RestoreState()
  327. * - When cell editing, scrolling with a mouse wheel now ends the edit operation.
  328. * v1.10
  329. * 2008-03-25 JPP - Added space filling columns. See OLVColumn.FreeSpaceProportion property for details.
  330. * A space filling columns fills all (or a portion) of the width unoccupied by other columns.
  331. * 2008-03-23 JPP - Finished tinkering with support for Mono. Compile with conditional compilation symbol 'MONO'
  332. * to enable. On Windows, current problems with Mono:
  333. * - grid lines on virtual lists crashes
  334. * - when grouped, items sometimes are not drawn when any item is scrolled out of view
  335. * - i can't seem to get owner drawing to work
  336. * - when editing cell values, the editing controls always appear behind the listview,
  337. * where they function fine -- the user just can't see them :-)
  338. * 2008-03-16 JPP - Added some methods suggested by Chris Marlowe (thanks for the suggestions Chris)
  339. * - ClearObjects()
  340. * - GetCheckedObject(), GetCheckedObjects()
  341. * - GetItemAt() variation that gets both the item and the column under a point
  342. * 2008-02-28 JPP - Fixed bug with subitem colors when using OwnerDrawn lists and a RowFormatter.
  343. * v1.9.1
  344. * 2008-01-29 JPP - Fixed bug that caused owner-drawn virtual lists to use 100% CPU
  345. * - Added FlagRenderer to help draw bitwise-OR'ed flag values
  346. * 2008-01-23 JPP - Fixed bug (introduced in v1.9) that made alternate row colour with groups not quite right
  347. * - Ensure that DesignerSerializationVisibility.Hidden is set on all non-browsable properties
  348. * - Make sure that sort indicators are shown after changing which columns are visible
  349. * 2008-01-21 JPP - Added FastObjectListView
  350. * v1.9
  351. * 2008-01-18 JPP - Added IncrementalUpdate()
  352. * 2008-01-16 JPP - Right clicking on column header will allow the user to choose which columns are visible.
  353. * Set SelectColumnsOnRightClick to false to prevent this behaviour.
  354. * - Added ImagesRenderer to draw more than one images in a column
  355. * - Changed the positioning of the empty list m to use all the client area. Thanks to Matze.
  356. * 2007-12-13 JPP - Added CopySelectionToClipboard(). Ctrl-C invokes this method. Supports text
  357. * and HTML formats.
  358. * 2007-12-12 JPP - Added support for checkboxes via CheckStateGetter and CheckStatePutter properties.
  359. * - Made ObjectListView and OLVColumn into partial classes so that others can extend them.
  360. * 2007-12-09 JPP - Added ability to have hidden columns, i.e. columns that the ObjectListView knows
  361. * about but that are not visible to the user. Controlled by OLVColumn.IsVisible.
  362. * Added ColumnSelectionForm to the project to show how it could be used in an application.
  363. *
  364. * v1.8
  365. * 2007-11-26 JPP - Cell editing fully functional
  366. * 2007-11-21 JPP - Added SelectionChanged event. This event is triggered once when the
  367. * selection changes, no matter how many items are selected or deselected (in
  368. * contrast to SelectedIndexChanged which is called once for every row that
  369. * is selected or deselected). Thanks to lupokehl42 (Daniel) for his suggestions and
  370. * improvements on this idea.
  371. * 2007-11-19 JPP - First take at cell editing
  372. * 2007-11-17 JPP - Changed so that items within a group are not sorted if lastSortOrder == None
  373. * - Only call MakeSortIndicatorImages() if we haven't already made the sort indicators
  374. * (Corrected misspelling in the name of the method too)
  375. * 2007-11-06 JPP - Added ability to have secondary sort criteria when sorting
  376. * (SecondarySortColumn and SecondarySortOrder properties)
  377. * - Added SortGroupItemsByPrimaryColumn to allow group items to be sorted by the
  378. * primary column. Previous default was to sort by the grouping column.
  379. * v1.7
  380. * No big changes to this version but made to work with ListViewPrinter and released with it.
  381. *
  382. * 2007-11-05 JPP - Changed BaseRenderer to use DrawString() rather than TextRenderer, since TextRenderer
  383. * does not work when printing.
  384. * v1.6
  385. * 2007-11-03 JPP - Fixed some bugs in the rebuilding of DataListView.
  386. * 2007-10-31 JPP - Changed to use builtin sort indicators on XP and later. This also avoids alignment
  387. * problems on Vista. (thanks to gravybod for the suggestion and example implementation)
  388. * 2007-10-21 JPP - Added MinimumWidth and MaximumWidth properties to OLVColumn.
  389. * - Added ability for BuildList() to preserve selection. Calling BuildList() directly
  390. * tries to preserve selection; calling SetObjects() does not.
  391. * - Added SelectAll() and DeselectAll() methods. Useful for working with large lists.
  392. * 2007-10-08 JPP - Added GetNextItem() and GetPreviousItem(), which walk sequentially through the
  393. * listview items, even when the view is grouped.
  394. * - Added SelectedItem property
  395. * 2007-09-28 JPP - Optimized aspect-to-string conversion. BuildList() 15% faster.
  396. * - Added empty implementation of RefreshObjects() to VirtualObjectListView since
  397. * RefreshObjects() cannot work on virtual lists.
  398. * 2007-09-13 JPP - Corrected bug with custom sorter in VirtualObjectListView (thanks for mpgjunky)
  399. * 2007-09-07 JPP - Corrected image scaling bug in DrawAlignedImage() (thanks to krita970)
  400. * 2007-08-29 JPP - Allow item count labels on groups to be set per column (thanks to cmarlow for idea)
  401. * 2007-08-14 JPP - Major rework of DataListView based on Ian Griffiths's great work
  402. * 2007-08-11 JPP - When empty, the control can now draw a "List Empty" m
  403. * - Added GetColumn() and GetItem() methods
  404. * v1.5
  405. * 2007-08-03 JPP - Support animated GIFs in ImageRenderer
  406. * - Allow height of rows to be specified - EXPERIMENTAL!
  407. * 2007-07-26 JPP - Optimised redrawing of owner-drawn lists by remembering the update rect
  408. * - Allow sort indicators to be turned off
  409. * 2007-06-30 JPP - Added RowFormatter delegate
  410. * - Allow a different label when there is only one item in a group (thanks to cmarlow)
  411. * v1.4
  412. * 2007-04-12 JPP - Allow owner drawn on steriods!
  413. * - Column headers now display sort indicators
  414. * - ImageGetter delegates can now return ints, strings or Images
  415. * (Images are only visible if the list is owner drawn)
  416. * - Added OLVColumn.MakeGroupies to help with group partitioning
  417. * - All normal listview views are now supported
  418. * - Allow dotted aspect names, e.g. Owner.Workgroup.Name (thanks to OlafD)
  419. * - Added SelectedObject and SelectedObjects properties
  420. * v1.3
  421. * 2007-03-01 JPP - Added DataListView
  422. * - Added VirtualObjectListView
  423. * - Added Freeze/Unfreeze capabilities
  424. * - Allowed sort handler to be installed
  425. * - Simplified sort comparisons: handles 95% of cases with only 6 lines of code!
  426. * - Fixed bug with alternative line colors on unsorted lists (thanks to cmarlow)
  427. * 2007-01-13 JPP - Fixed bug with lastSortOrder (thanks to Kwan Fu Sit)
  428. * - Non-OLVColumns are no longer allowed
  429. * 2007-01-04 JPP - Clear sorter before rebuilding list. 10x faster! (thanks to aaberg)
  430. * - Include GetField in GetAspectByName() so field values can be Invoked too.
  431. * - Fixed subtle bug in RefreshItem() that erased background colors.
  432. * 2006-11-01 JPP - Added alternate line colouring
  433. * 2006-10-20 JPP - Refactored all sorting comparisons and made it extendable. See ComparerManager.
  434. * - Improved IDE integration
  435. * - Made control DoubleBuffered
  436. * - Added object selection methods
  437. * 2006-10-13 JPP Implemented grouping and column sorting
  438. * 2006-10-09 JPP Initial version
  439. *
  440. * TO DO:
  441. * - Support undocumented group features: subseted groups, group footer items
  442. * - Complete custom designer
  443. *
  444. * Copyright (C) 2006-2011 Phillip Piper
  445. *
  446. * This program is free software: you can redistribute it and/or modify
  447. * it under the terms of the GNU General Public License as published by
  448. * the Free Software Foundation, either version 3 of the License, or
  449. * (at your option) any later version.
  450. *
  451. * This program is distributed in the hope that it will be useful,
  452. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  453. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  454. * GNU General Public License for more details.
  455. *
  456. * You should have received a copy of the GNU General Public License
  457. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  458. *
  459. * If you wish to use this code in a closed source application, please contact phillip_piper@bigfoot.com.
  460. */
  461. using System;
  462. using System.Collections;
  463. using System.Collections.Generic;
  464. using System.ComponentModel;
  465. using System.Drawing;
  466. using System.IO;
  467. using System.Reflection;
  468. using System.Runtime.InteropServices;
  469. using System.Runtime.Serialization.Formatters.Binary;
  470. using System.Windows.Forms;
  471. using System.Windows.Forms.VisualStyles;
  472. using System.Runtime.Serialization.Formatters;
  473. namespace BrightIdeasSoftware
  474. {
  475. /// <summary>
  476. /// An ObjectListView is a much easier to use, and much more powerful, version of the ListView.
  477. /// </summary>
  478. /// <remarks>
  479. /// <para>
  480. /// An ObjectListView automatically populates a ListView control with information taken
  481. /// from a given collection of objects. It can do this because each column is configured
  482. /// to know which bit of the model object (the "aspect") it should be displaying. Columns similarly
  483. /// understand how to sort the list based on their aspect, and how to construct groups
  484. /// using their aspect.
  485. /// </para>
  486. /// <para>
  487. /// Aspects are extracted by giving the name of a method to be called or a
  488. /// property to be fetched. These names can be simple names or they can be dotted
  489. /// to chain property access e.g. "Owner.Address.Postcode".
  490. /// Aspects can also be extracted by installing a delegate.
  491. /// </para>
  492. /// <para>
  493. /// An ObjectListView can show a "this list is empty" message when there is nothing to show in the list,
  494. /// so that the user knows the control is supposed to be empty.
  495. /// </para>
  496. /// <para>
  497. /// Right clicking on a column header should present a menu which can contain:
  498. /// commands (sort, group, ungroup); filtering; and column selection. Whether these
  499. /// parts of the menu appear is controlled by ShowCommandMenuOnRightClick,
  500. /// ShowFilterMenuOnRightClick and SelectColumnsOnRightClick respectively.
  501. /// </para>
  502. /// <para>
  503. /// The groups created by an ObjectListView can be configured to include other formatting
  504. /// information, including a group icon, subtitle and task button. Using some undocumented
  505. /// interfaces, these groups can even on virtual lists.
  506. /// </para>
  507. /// <para>
  508. /// ObjectListView supports dragging rows to other places, including other application.
  509. /// Special support is provide for drops from other ObjectListViews in the same application.
  510. /// In many cases, an ObjectListView becomes a full drag source by setting <see cref="IsSimpleDragSource"/> to
  511. /// true. Similarly, to accept drops, it is usually enough to set <see cref="IsSimpleDropSink"/> to true,
  512. /// and then handle the <see cref="CanDrop"/> and <see cref="Dropped"/> events (or the <see cref="ModelCanDrop"/> and
  513. /// <see cref="ModelDropped"/> events, if you only want to handle drops from other ObjectListViews in your application).
  514. /// </para>
  515. /// <para>
  516. /// For these classes to build correctly, the project must have references to these assemblies:
  517. /// </para>
  518. /// <list type="bullet">
  519. /// <item><description>System</description></item>
  520. /// <item><description>System.Data</description></item>
  521. /// <item><description>System.Design</description></item>
  522. /// <item><description>System.Drawing</description></item>
  523. /// <item><description>System.Windows.Forms (obviously)</description></item>
  524. /// </list>
  525. /// </remarks>
  526. //[Designer("BrightIdeasSoftware.Design.ObjectListViewDesigner")] // Uncomment this if you are feeling brave :)
  527. public partial class ObjectListView : ListView, ISupportInitialize {
  528. #region Life and death
  529. /// <summary>
  530. /// Create an ObjectListView
  531. /// </summary>
  532. public ObjectListView() {
  533. this.ColumnClick += new ColumnClickEventHandler(this.HandleColumnClick);
  534. this.Layout += new LayoutEventHandler(this.HandleLayout);
  535. this.ColumnWidthChanging += new ColumnWidthChangingEventHandler(this.HandleColumnWidthChanging);
  536. this.ColumnWidthChanged += new ColumnWidthChangedEventHandler(this.HandleColumnWidthChanged);
  537. base.View = View.Details;
  538. this.DoubleBuffered = true; // kill nasty flickers. hiss... me hates 'em
  539. this.ShowSortIndicators = true;
  540. // Setup the overlays that will be controlled by the IDE settings
  541. this.InitializeStandardOverlays();
  542. this.InitializeEmptyListMsgOverlay();
  543. }
  544. /// <summary>
  545. /// Dispose of any resources this instance has been using
  546. /// </summary>
  547. /// <param name="disposing"></param>
  548. protected override void Dispose(bool disposing) {
  549. base.Dispose(disposing);
  550. if (disposing) {
  551. foreach (GlassPanelForm glassPanel in this.glassPanels) {
  552. glassPanel.Unbind();
  553. glassPanel.Dispose();
  554. }
  555. this.glassPanels.Clear();
  556. }
  557. }
  558. #endregion
  559. #region Static properties
  560. /// <summary>
  561. /// Gets whether the program running on Vista or later?
  562. /// </summary>
  563. static public bool IsVistaOrLater {
  564. get {
  565. if (!ObjectListView.isVistaOrLater.HasValue)
  566. ObjectListView.isVistaOrLater = Environment.OSVersion.Version.Major >= 6;
  567. return ObjectListView.isVistaOrLater.Value;
  568. }
  569. }
  570. static private bool? isVistaOrLater;
  571. /// <summary>
  572. /// Gets whether the program running on Win7 or later?
  573. /// </summary>
  574. static public bool IsWin7OrLater {
  575. get {
  576. if (!ObjectListView.isWin7OrLater.HasValue) {
  577. // For some reason, Win7 is v6.1, not v7.0
  578. Version version = Environment.OSVersion.Version;
  579. ObjectListView.isWin7OrLater = version.Major > 6 || (version.Major == 6 && version.Minor > 0);
  580. }
  581. return ObjectListView.isWin7OrLater.Value;
  582. }
  583. }
  584. static private bool? isWin7OrLater;
  585. /// <summary>
  586. /// Gets or sets how what smoothing mode will be applied to graphic operations.
  587. /// </summary>
  588. static public System.Drawing.Drawing2D.SmoothingMode SmoothingMode {
  589. get { return ObjectListView.smoothingMode; }
  590. set { ObjectListView.smoothingMode = value; }
  591. }
  592. static private System.Drawing.Drawing2D.SmoothingMode smoothingMode =
  593. System.Drawing.Drawing2D.SmoothingMode.HighQuality;
  594. /// <summary>
  595. /// Gets or sets how should text be renderered.
  596. /// </summary>
  597. static public System.Drawing.Text.TextRenderingHint TextRenderingHint {
  598. get { return ObjectListView.textRendereringHint; }
  599. set { ObjectListView.textRendereringHint = value; }
  600. }
  601. static private System.Drawing.Text.TextRenderingHint textRendereringHint =
  602. System.Drawing.Text.TextRenderingHint.SystemDefault;
  603. /// <summary>
  604. /// Convert the given enumerable into an ArrayList as efficiently as possible
  605. /// </summary>
  606. /// <param name="collection">The source collection</param>
  607. /// <param name="alwaysCreate">If true, this method will always create a new
  608. /// collection.</param>
  609. /// <returns>An ArrayList with the same contents as the given collection.</returns>
  610. /// <remarks>
  611. /// <para>When we move to .NET 3.5, we can use LINQ and not need this method.</para>
  612. /// </remarks>
  613. public static ArrayList EnumerableToArray(IEnumerable collection, bool alwaysCreate) {
  614. if (collection == null)
  615. return new ArrayList();
  616. if (!alwaysCreate) {
  617. ArrayList array = collection as ArrayList;
  618. if (array != null)
  619. return array;
  620. IList iList = collection as IList;
  621. if (iList != null)
  622. return ArrayList.Adapter(iList);
  623. }
  624. ICollection iCollection = collection as ICollection;
  625. if (iCollection != null)
  626. return new ArrayList(iCollection);
  627. ArrayList newObjects = new ArrayList();
  628. foreach (object x in collection)
  629. newObjects.Add(x);
  630. return newObjects;
  631. }
  632. ///// <summary>
  633. ///// Decide if the given enumerable is empty
  634. ///// </summary>
  635. ///// <param name="collection">The source collection</param>
  636. ///// <returns>True if the given enumerable is empty</returns>
  637. ///// <remarks>
  638. ///// <para>When we move to .NET 3.5, we can use LINQ and not need this method.</para>
  639. ///// </remarks>
  640. //public static bool IsEnumerableEmpty(IEnumerable collection) {
  641. // if (collection == null)
  642. // return true;
  643. // IEnumerator enumerator = collection.GetEnumerator();
  644. // return !enumerator.MoveNext();
  645. //}
  646. #endregion
  647. #region Public properties
  648. /// <summary>
  649. /// Get or set all the columns that this control knows about.
  650. /// Only those columns where IsVisible is true will be seen by the user.
  651. /// </summary>
  652. /// <remarks>
  653. /// <para>
  654. /// If you want to add new columns programmatically, add them to
  655. /// AllColumns and then call RebuildColumns(). Normally, you do not have to
  656. /// deal with this property directly. Just use the IDE.
  657. /// </para>
  658. /// <para>If you do add or remove columns from the AllColumns collection,
  659. /// you have to call RebuildColumns() to make those changes take effect.</para>
  660. /// </remarks>
  661. [Browsable(false),
  662. DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
  663. public virtual List<OLVColumn> AllColumns {
  664. get { return this.allColumns; }
  665. set { this.allColumns = value ?? new List<OLVColumn>(); }
  666. }
  667. private List<OLVColumn> allColumns = new List<OLVColumn>();
  668. /// <summary>
  669. /// Gets or sets the background color of every second row
  670. /// </summary>
  671. [Category("ObjectListView"),
  672. Description("If using alternate colors, what color should the background of alterate rows be?"),
  673. DefaultValue(typeof(Color), "")]
  674. public Color AlternateRowBackColor {
  675. get { return alternateRowBackColor; }
  676. set { alternateRowBackColor = value; }
  677. }
  678. private Color alternateRowBackColor = Color.Empty;
  679. /// <summary>
  680. /// Gets the alternate row background color that has been set, or the default color
  681. /// </summary>
  682. [Browsable(false)]
  683. public virtual Color AlternateRowBackColorOrDefault {
  684. get {
  685. return this.alternateRowBackColor == Color.Empty ? Color.LemonChiffon : this.alternateRowBackColor;
  686. }
  687. }
  688. /// <summary>
  689. /// This property forces the ObjectListView to always group items by the given column.
  690. /// </summary>
  691. [Browsable(false),
  692. DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  693. public virtual OLVColumn AlwaysGroupByColumn {
  694. get { return alwaysGroupByColumn; }
  695. set { alwaysGroupByColumn = value; }
  696. }
  697. private OLVColumn alwaysGroupByColumn;
  698. /// <summary>
  699. /// If AlwaysGroupByColumn is not null, this property will be used to decide how
  700. /// those groups are sorted. If this property has the value SortOrder.None, then
  701. /// the sort order will toggle according to the users last header click.
  702. /// </summary>
  703. [Browsable(false),
  704. DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  705. public virtual SortOrder AlwaysGroupBySortOrder {
  706. get { return alwaysGroupBySortOrder; }
  707. set { alwaysGroupBySortOrder = value; }
  708. }
  709. private SortOrder alwaysGroupBySortOrder = SortOrder.None;
  710. /// <summary>
  711. /// Give access to the image list that is actually being used by the control
  712. /// </summary>
  713. /// <remarks>
  714. /// Normally, it is preferable to use SmallImageList. Only use this property
  715. /// if you know exactly what you are doing.
  716. /// </remarks>
  717. [Browsable(false),
  718. DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  719. public virtual ImageList BaseSmallImageList {
  720. get { return base.SmallImageList; }
  721. set { base.SmallImageList = value; }
  722. }
  723. /// <summary>
  724. /// How does the user indicate that they want to edit a cell?
  725. /// None means that the listview cannot be edited.
  726. /// </summary>
  727. /// <remarks>Columns can also be marked as editable.</remarks>
  728. [Category("ObjectListView"),
  729. Description("How does the user indicate that they want to edit a cell?"),
  730. DefaultValue(CellEditActivateMode.None)]
  731. public virtual CellEditActivateMode CellEditActivation {
  732. get { return cellEditActivation; }
  733. set {
  734. cellEditActivation = value;
  735. if (this.Created)
  736. this.Invalidate();
  737. }
  738. }
  739. private CellEditActivateMode cellEditActivation = CellEditActivateMode.None;
  740. /// <summary>
  741. /// Gets or sets the engine that will handle key presses during a cell edit operation.
  742. /// Settings this to null will reset it to default value.
  743. /// </summary>
  744. [Browsable(false),
  745. DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  746. public CellEditKeyEngine CellEditKeyEngine {
  747. get {
  748. if (this.cellEditKeyEngine == null)
  749. this.cellEditKeyEngine = new CellEditKeyEngine();
  750. return this.cellEditKeyEngine;
  751. }

Large files files are truncated, but you can click here to view the full file