10742 lines
480 KiB
C#
10742 lines
480 KiB
C#
/*
|
||
* ObjectListView - A listview to show various aspects of a collection of objects
|
||
*
|
||
* Author: Phillip Piper
|
||
* Date: 9/10/2006 11:15 AM
|
||
*
|
||
* Change log
|
||
* v2.9.1
|
||
* 2015-12-30 JPP - Added CellRendererGetter to allow each cell to have a different renderer.
|
||
* - Obsolete properties are no longer code-gen'ed.
|
||
*
|
||
* v2.9.0
|
||
* 2015-08-22 JPP - Allow selected row back/fore colours to be specified for each row
|
||
* - Renamed properties related to selection colours:
|
||
* - HighlightBackgroundColor -> SelectedBackColor
|
||
* - HighlightForegroundColor -> SelectedForeColor
|
||
* - UnfocusedHighlightBackgroundColor -> UnfocusedSelectedBackColor
|
||
* - UnfocusedHighlightForegroundColor -> UnfocusedSelectedForeColor
|
||
* - UseCustomSelectionColors is no longer used
|
||
* 2015-08-03 JPP - Added ObjectListView.CellEditFinished event
|
||
* - Added EditorRegistry.Unregister()
|
||
* 2015-07-08 JPP - All ObjectListViews are now OwnerDrawn by default. This allows all the great features
|
||
* of ObjectListView to work correctly at the slight cost of more processing at render time.
|
||
* It also avoids the annoying "hot item background ignored in column 0" behaviour that native
|
||
* ListView has. Programmers can still turn it back off if they wish.
|
||
* 2015-06-27 JPP - Yet another attempt to disable ListView's "shift click toggles checkboxes" behaviour.
|
||
* The last strategy (fake right click) worked, but had nasty side effects. This one works
|
||
* by intercepting a HITTEST message so that it fails. It no longer creates fake right mouse events.
|
||
* - Trigger SelectionChanged when filter is changed
|
||
* 2015-06-23 JPP - [BIG] Added support for Buttons
|
||
* 2015-06-22 JPP - Added OLVColumn.SearchValueGetter to allow the text used when text filtering to be customised
|
||
* - The default DefaultRenderer is now a HighlightTextRenderer, since that seems more generally useful
|
||
* 2015-06-17 JPP - Added FocusedObject property
|
||
* - Hot item is now always applied to the row even if FullRowSelect is false
|
||
* 2015-06-11 JPP - Added DefaultHotItemStyle property
|
||
* 2015-06-07 JPP - Added HeaderMinimumHeight property
|
||
* - Added ObjectListView.CellEditUsesWholeCell and OLVColumn.CellEditUsesWholeCell properties.
|
||
* 2015-05-15 JPP - Allow ImageGetter to return an Image (which I can't believe didn't work from the beginning!)
|
||
* 2015-04-27 JPP - Fix bug where setting View to LargeIcon in the designer was not persisted
|
||
* 2015-04-07 JPP - Ensure changes to row.Font in FormatRow are not wiped out by FormatCell (SF #141)
|
||
*
|
||
* v2.8.1
|
||
* 2014-10-15 JPP - Added CellEditActivateMode.SingleClickAlways mode
|
||
* - Fire Filter event event if ModelFilter and ListFilter are null (SF #126)
|
||
* - Fixed issue where single-click editing didn't work (SF #128)
|
||
* v2.8.0
|
||
* 2014-10-11 JPP - Fixed some XP-only flicker issues
|
||
* 2014-09-26 JPP - Fixed intricate bug involving checkboxes on non-owner-drawn virtual lists.
|
||
* - Fixed long standing (but previously unreported) error on non-details virtual lists where
|
||
* users could not click on checkboxes.
|
||
* 2014-09-07 JPP - (Major) Added ability to have checkboxes in headers
|
||
* - CellOver events are raised when the mouse moves over the header. Set TriggerCellOverEventsWhenOverHeader
|
||
* to false to disable this behaviour.
|
||
* - Freeze/Unfreeze now use BeginUpdate/EndUpdate to disable Window level drawing
|
||
* - Changed default value of ObjectListView.HeaderUsesThemes from true to false. Too many people were
|
||
* being confused, trying to make something interesting appear in the header and nothing showing up
|
||
* 2014-08-04 JPP - Final attempt to fix the multiple hyperlink events being raised. This involves turning
|
||
* a NM_CLICK notification into a NM_RCLICK.
|
||
* 2014-05-21 JPP - (Major) Added ability to disable rows. DisabledObjects, DisableObjects(), DisabledItemStyle.
|
||
* 2014-04-25 JPP - Fixed issue where virtual lists containing a single row didn't update hyperlinks on MouseOver
|
||
* - Added sanity check before BuildGroups()
|
||
* 2014-03-22 JPP - Fixed some subtle bugs resulting from misuse of TryGetValue()
|
||
* 2014-03-09 JPP - Added CollapsedGroups property
|
||
* - Several minor Resharper complaints quiesced.
|
||
* v2.7
|
||
* 2014-02-14 JPP - Fixed issue with ShowHeaderInAllViews (another one!) where setting it to false caused the list to lose
|
||
* its other extended styles, leading to nasty flickering and worse.
|
||
* 2014-02-06 JPP - Fix issue on virtual lists where the filter was not correctly reapplied after columns were added or removed.
|
||
* - Made disposing of cell editors optional (defaults to true). This allows controls to be cached and reused.
|
||
* - Bracketed column resizing with BeginUpdate/EndUpdate to smooth redraws (thanks to Davide)
|
||
* 2014-02-01 JPP - Added static property ObjectListView.GroupTitleDefault to allow the default group title to be localised.
|
||
* 2013-09-24 JPP - Fixed issue in RefreshObjects() when model objects overrode the Equals()/GetHashCode() methods.
|
||
* - Made sure get state checker were used when they should have been
|
||
* 2013-04-21 JPP - Clicking on a non-groupable column header when showing groups will now sort
|
||
* the group contents by that column.
|
||
* v2.6
|
||
* 2012-08-16 JPP - Added ObjectListView.EditModel() -- a convenience method to start an edit operation on a model
|
||
* 2012-08-10 JPP - Don't trigger selection changed events during sorting/grouping or add/removing columns
|
||
* 2012-08-06 JPP - Don't start a cell edit operation when the user clicks on the background of a checkbox cell.
|
||
* - Honor values from the BeforeSorting event when calling a CustomSorter
|
||
* 2012-08-02 JPP - Added CellVerticalAlignment and CellPadding properties.
|
||
* 2012-07-04 JPP - Fixed issue with cell editing where the cell editing didn't finish until the first idle event.
|
||
* This meant that if you clicked and held on the scroll thumb to finish a cell edit, the editor
|
||
* wouldn't be removed until the mouse was released.
|
||
* 2012-07-03 JPP - Fixed issue with SingleClick cell edit mode where the cell editing would not begin until the
|
||
* mouse moved after the click.
|
||
* 2012-06-25 JPP - Fixed bug where removing a column from a LargeIcon or SmallIcon view would crash the control.
|
||
* 2012-06-15 JPP - Added Reset() method, which definitively removes all rows *and* columns from an ObjectListView.
|
||
* 2012-06-11 JPP - Added FilteredObjects property which returns the collection of objects that survives any installed filters.
|
||
* 2012-06-04 JPP - [Big] Added UseNotifyPropertyChanged to allow OLV to listen for INotifyPropertyChanged events on models.
|
||
* 2012-05-30 JPP - Added static property ObjectListView.IgnoreMissingAspects. If this is set to true, all
|
||
* ObjectListViews will silently ignore missing aspect errors. Read the remarks to see why this would be useful.
|
||
* 2012-05-23 JPP - Setting UseFilterIndicator to true now sets HeaderUsesTheme to false.
|
||
* Also, changed default value of UseFilterIndicator to false. Previously, HeaderUsesTheme and UseFilterIndicator
|
||
* defaulted to true, which was pointless since when the HeaderUsesTheme is true, UseFilterIndicator does nothing.
|
||
* v2.5.1
|
||
* 2012-05-06 JPP - Fix bug where collapsing the first group would cause decorations to stop being drawn (SR #3502608)
|
||
* 2012-04-23 JPP - Trigger GroupExpandingCollapsing event to allow the expand/collapse to be cancelled
|
||
* - Fixed SetGroupSpacing() so it corrects updates the space between all groups.
|
||
* - ResizeLastGroup() now does nothing since it was broken and I can't remember what it was
|
||
* even supposed to do :)
|
||
* 2012-04-18 JPP - Upgraded hit testing to include hits on groups.
|
||
* - HotItemChanged is now correctly recalculated on each mouse move. Includes "hot" group information.
|
||
* 2012-04-14 JPP - Added GroupStateChanged event. Useful for knowing when a group is collapsed/expanded.
|
||
* - Added AdditionalFilter property. This filter is combined with the Excel-like filtering that
|
||
* the end user might enact at runtime.
|
||
* 2012-04-10 JPP - Added PersistentCheckBoxes property to allow primary checkboxes to remember their values
|
||
* across list rebuilds.
|
||
* 2012-04-05 JPP - Reverted some code to .NET 2.0 standard.
|
||
* - Tweaked some code
|
||
* 2012-02-05 JPP - Fixed bug when selecting a separator on a drop down menu
|
||
* 2011-06-24 JPP - Added CanUseApplicationIdle property to cover cases where Application.Idle events
|
||
* are not triggered. For example, when used within VS (and probably Office) extensions
|
||
* Application.Idle is never triggered. Set CanUseApplicationIdle to false to handle
|
||
* these cases.
|
||
* - Handle cases where a second tool tip is installed onto the ObjectListView.
|
||
* - Correctly recolour rows after an Insert or Move
|
||
* - Removed m.LParam cast which could cause overflow issues on Win7/64 bit.
|
||
* v2.5.0
|
||
* 2011-05-31 JPP - SelectObject() and SelectObjects() no longer deselect all other rows.
|
||
Set the SelectedObject or SelectedObjects property to do that.
|
||
* - Added CheckedObjectsEnumerable
|
||
* - Made setting CheckedObjects more efficient on large collections
|
||
* - Deprecated GetSelectedObject() and GetSelectedObjects()
|
||
* 2011-04-25 JPP - Added SubItemChecking event
|
||
* - Fixed bug in handling of NewValue on CellEditFinishing event
|
||
* 2011-04-12 JPP - Added UseFilterIndicator
|
||
* - Added some more localizable messages
|
||
* 2011-04-10 JPP - FormatCellEventArgs now has a CellValue property, which is the model value displayed
|
||
* by the cell. For example, for the Birthday column, the CellValue might be
|
||
* DateTime(1980, 12, 31), whereas the cell's text might be 'Dec 31, 1980'.
|
||
* 2011-04-04 JPP - Tweaked UseTranslucentSelection and UseTranslucentHotItem to look (a little) more
|
||
* like Vista/Win7.
|
||
* - Alternate colours are now only applied in Details view (as they always should have been)
|
||
* - Alternate colours are now correctly recalculated after removing objects
|
||
* 2011-03-29 JPP - Added SelectColumnsOnRightClickBehaviour to allow the selecting of columns mechanism
|
||
* to be changed. Can now be InlineMenu (the default), SubMenu, or ModelDialog.
|
||
* - ColumnSelectionForm was moved from the demo into the ObjectListView project itself.
|
||
* - Ctrl-C copying is now able to use the DragSource to create the data transfer object.
|
||
* 2011-03-19 JPP - All model object comparisons now use Equals rather than == (thanks to vulkanino)
|
||
* - [Small Break] GetNextItem() and GetPreviousItem() now accept and return OLVListView
|
||
* rather than ListViewItems.
|
||
* 2011-03-07 JPP - [Big] Added Excel-style filtering. Right click on a header to show a Filtering menu.
|
||
* - Added CellEditKeyEngine to allow key handling when cell editing to be completely customised.
|
||
* Add CellEditTabChangesRows and CellEditEnterChangesRows to show some of these abilities.
|
||
* 2011-03-06 JPP - Added OLVColumn.AutoCompleteEditorMode in preference to AutoCompleteEditor
|
||
* (which is now just a wrapper). Thanks to Clive Haskins
|
||
* - Added lots of docs to new classes
|
||
* 2011-02-25 JPP - Preserve word wrap settings on TreeListView
|
||
* - Resize last group to keep it on screen (thanks to ?)
|
||
* 2010-11-16 JPP - Fixed (once and for all) DisplayIndex problem with Generator
|
||
* - Changed the serializer used in SaveState()/RestoreState() so that it resolves on
|
||
* class name alone.
|
||
* - Fixed bug in GroupWithItemCountSingularFormatOrDefault
|
||
* - Fixed strange flickering in grouped, owner drawn OLV's using RefreshObject()
|
||
* v2.4.1
|
||
* 2010-08-25 JPP - Fixed bug where setting OLVColumn.CheckBoxes to false gave it a renderer
|
||
* specialized for checkboxes. Oddly, this made Generator created owner drawn
|
||
* lists appear to be completely empty.
|
||
* - In IDE, all ObjectListView properties are now in a single "ObjectListView" category,
|
||
* rather than splitting them between "Appearance" and "Behavior" categories.
|
||
* - Added GroupingParameters.GroupComparer to allow groups to be sorted in a customizable fashion.
|
||
* - Sorting of items within a group can be disabled by setting
|
||
* GroupingParameters.PrimarySortOrder to None.
|
||
* 2010-08-24 JPP - Added OLVColumn.IsHeaderVertical to make a column draw its header vertical.
|
||
* - Added OLVColumn.HeaderTextAlign to control the alignment of a column's header text.
|
||
* - Added HeaderMaximumHeight to limit how tall the header section can become
|
||
* 2010-08-18 JPP - Fixed long standing bug where having 0 columns caused a InvalidCast exception.
|
||
* - Added IncludeAllColumnsInDataObject property
|
||
* - Improved BuildList(bool) so that it preserves scroll position even when
|
||
* the listview is grouped.
|
||
* 2010-08-08 JPP - Added OLVColumn.HeaderImageKey to allow column headers to have an image.
|
||
* - CellEdit validation and finish events now have NewValue property.
|
||
* 2010-08-03 JPP - Subitem checkboxes improvements: obey IsEditable, can be hot, can be disabled.
|
||
* - No more flickering of selection when tabbing between cells
|
||
* - Added EditingCellBorderDecoration to make it clearer which cell is being edited.
|
||
* 2010-08-01 JPP - Added ObjectListView.SmoothingMode to control the smoothing of all graphics
|
||
* operations
|
||
* - Columns now cache their group item format strings so that they still work as
|
||
* grouping columns after they have been removed from the listview. This cached
|
||
* value is only used when the column is not part of the listview.
|
||
* 2010-07-25 JPP - Correctly trigger a Click event when the mouse is clicked.
|
||
* 2010-07-16 JPP - Invalidate the control before and after cell editing to make sure it looks right
|
||
* 2010-06-23 JPP - Right mouse clicks on checkboxes no longer confuse them
|
||
* 2010-06-21 JPP - Avoid bug in underlying ListView control where virtual lists in SmallIcon view
|
||
* generate GETTOOLINFO msgs with invalid item indices.
|
||
* - Fixed bug where FastObjectListView would throw an exception when showing hyperlinks
|
||
* in any view except Details.
|
||
* 2010-06-15 JPP - Fixed bug in ChangeToFilteredColumns() that resulted in column display order
|
||
* being lost when a column was hidden.
|
||
* - Renamed IsVista property to IsVistaOrLater which more accurately describes its function.
|
||
* v2.4
|
||
* 2010-04-14 JPP - Prevent object disposed errors when mouse event handlers cause the
|
||
* ObjectListView to be destroyed (e.g. closing a form during a
|
||
* double click event).
|
||
* - Avoid checkbox munging bug in standard ListView when shift clicking on non-primary
|
||
* columns when FullRowSelect is true.
|
||
* 2010-04-12 JPP - Fixed bug in group sorting (thanks Mike).
|
||
* 2010-04-07 JPP - Prevent hyperlink processing from triggering spurious MouseUp events.
|
||
* This showed itself by launching the same url multiple times.
|
||
* 2010-04-06 JPP - Space filling columns correctly resize upon initial display
|
||
* - ShowHeaderInAllViews is better but still not working reliably.
|
||
* See comments on property for more details.
|
||
* 2010-03-23 JPP - Added ObjectListView.HeaderFormatStyle and OLVColumn.HeaderFormatStyle.
|
||
* This makes HeaderFont and HeaderForeColor properties unnecessary --
|
||
* they will be marked obsolete in the next version and removed after that.
|
||
* 2010-03-16 JPP - Changed object checking so that objects can be pre-checked before they
|
||
* are added to the list. Normal ObjectListViews managed "checkedness" in
|
||
* the ListViewItem, so this won't work for them, unless check state getters
|
||
* and putters have been installed. It will work on on virtual lists (thus fast lists and
|
||
* tree views) since they manage their own check state.
|
||
* 2010-03-06 JPP - Hide "Items" and "Groups" from the IDE properties grid since they shouldn't be set like that.
|
||
* They can still be accessed through "Custom Commands" and there's nothing we can do
|
||
* about that.
|
||
* 2010-03-05 JPP - Added filtering
|
||
* 2010-01-18 JPP - Overlays can be turned off. They also only work on 32-bit displays
|
||
* v2.3
|
||
* 2009-10-30 JPP - Plugged possible resource leak by using using() with CreateGraphics()
|
||
* 2009-10-28 JPP - Fix bug when right clicking in the empty area of the header
|
||
* 2009-10-20 JPP - Redraw the control after setting EmptyListMsg property
|
||
* v2.3
|
||
* 2009-09-30 JPP - Added Dispose() method to properly release resources
|
||
* 2009-09-16 JPP - Added OwnerDrawnHeader, which you can set to true if you want to owner draw
|
||
* the header yourself.
|
||
* 2009-09-15 JPP - Added UseExplorerTheme, which allow complete visual compliance with Vista explorer.
|
||
* But see property documentation for its many limitations.
|
||
* - Added ShowHeaderInAllViews. To make this work, Columns are no longer
|
||
* changed when switching to/from Tile view.
|
||
* 2009-09-11 JPP - Added OLVColumn.AutoCompleteEditor to allow the autocomplete of cell editors
|
||
* to be disabled.
|
||
* 2009-09-01 JPP - Added ObjectListView.TextRenderingHint property which controls the
|
||
* text rendering hint of all drawn text.
|
||
* 2009-08-28 JPP - [BIG] Added group formatting to supercharge what is possible with groups
|
||
* - [BIG] Virtual groups now work
|
||
* - Extended MakeGroupies() to handle more aspects of group creation
|
||
* 2009-08-19 JPP - Added ability to show basic column commands when header is right clicked
|
||
* - Added SelectedRowDecoration, UseTranslucentSelection and UseTranslucentHotItem.
|
||
* - Added PrimarySortColumn and PrimarySortOrder
|
||
* 2009-08-15 JPP - Correct problems with standard hit test and subitems
|
||
* 2009-08-14 JPP - [BIG] Support Decorations
|
||
* - [BIG] Added header formatting capabilities: font, color, word wrap
|
||
* - Gave ObjectListView its own designer to hide unwanted properties
|
||
* - Separated design time stuff into separate file
|
||
* - Added FormatRow and FormatCell events
|
||
* 2009-08-09 JPP - Get around bug in HitTest when not FullRowSelect
|
||
* - Added OLVListItem.GetSubItemBounds() method which works correctly
|
||
* for all columns including column 0
|
||
* 2009-08-07 JPP - Added Hot* properties that track where the mouse is
|
||
* - Added HotItemChanged event
|
||
* - Overrode TextAlign on columns so that column 0 can have something other
|
||
* than just left alignment. This is only honored when owner drawn.
|
||
* v2.2.1
|
||
* 2009-08-03 JPP - Subitem edit rectangles always allowed for an image in the cell, even if there was none.
|
||
* Now they only allow for an image when there actually is one.
|
||
* - Added Bounds property to OLVListItem which handles items being part of collapsed groups.
|
||
* 2009-07-29 JPP - Added GetSubItem() methods to ObjectListView and OLVListItem
|
||
* 2009-07-26 JPP - Avoided bug in .NET framework involving column 0 of owner drawn listviews not being
|
||
* redrawn when the listview was scrolled horizontally (this was a LOT of work to track
|
||
* down and fix!)
|
||
* - The cell edit rectangle is now correctly calculated when the listview is scrolled
|
||
* horizontally.
|
||
* 2009-07-14 JPP - If the user clicks/double clicks on a tree list cell, an edit operation will no longer begin
|
||
* if the click was to the left of the expander. This is implemented in such a way that
|
||
* other renderers can have similar "dead" zones.
|
||
* 2009-07-11 JPP - CalculateCellBounds() messed with the FullRowSelect property, which confused the
|
||
* tooltip handling on the underlying control. It no longer does this.
|
||
* - The cell edit rectangle is now correctly calculated for owner-drawn, non-Details views.
|
||
* 2009-07-08 JPP - Added Cell events (CellClicked, CellOver, CellRightClicked)
|
||
* - Made BuildList(), AddObject() and RemoveObject() thread-safe
|
||
* 2009-07-04 JPP - Space bar now properly toggles checkedness of selected rows
|
||
* 2009-07-02 JPP - Fixed bug with tooltips when the underlying Windows control was destroyed.
|
||
* - CellToolTipShowing events are now triggered in all views.
|
||
* v2.2
|
||
* 2009-06-02 JPP - BeforeSortingEventArgs now has a Handled property to let event handlers do
|
||
* the item sorting themselves.
|
||
* - AlwaysGroupByColumn works again, as does SortGroupItemsByPrimaryColumn and all their
|
||
* various permutations.
|
||
* - SecondarySortOrder and SecondarySortColumn are now "null" by default
|
||
* 2009-05-15 JPP - Fixed bug so that KeyPress events are again triggered
|
||
* 2009-05-10 JPP - Removed all unsafe code
|
||
* 2009-05-07 JPP - Don't use glass panel for overlays when in design mode. It's too confusing.
|
||
* 2009-05-05 JPP - Added Scroll event (thanks to Christophe Hosten for the complete patch to implement this)
|
||
* - Added Unfocused foreground and background colors (also thanks to Christophe Hosten)
|
||
* 2009-04-29 JPP - Added SelectedColumn property, which puts a slight tint on that column. Combine
|
||
* this with TintSortColumn property and the sort column is automatically tinted.
|
||
* - Use an overlay to implement "empty list" msg. Default empty list msg is now prettier.
|
||
* 2009-04-28 JPP - Fixed bug where DoubleClick events were not triggered when CheckBoxes was true
|
||
* 2009-04-23 JPP - Fixed various bugs under Vista.
|
||
* - Made groups collapsible - Vista only. Thanks to Crustyapplesniffer.
|
||
* - Forward events from DropSink to the control itself. This allows handlers to be defined
|
||
* within the IDE for drop events
|
||
* 2009-04-16 JPP - Made several properties localizable.
|
||
* 2009-04-11 JPP - Correctly renderer checkboxes when RowHeight is non-standard
|
||
* 2009-04-11 JPP - Implemented overlay architecture, based on CustomDraw scheme.
|
||
* This unified drag drop feedback, empty list msgs and overlay images.
|
||
* - Added OverlayImage and friends, which allows an image to be drawn
|
||
* transparently over the listview
|
||
* 2009-04-10 JPP - Fixed long-standing annoying flicker on owner drawn virtual lists!
|
||
* This means, amongst other things, that grid lines no longer get confused,
|
||
* and drag-select no longer flickers.
|
||
* 2009-04-07 JPP - Calculate edit rectangles more accurately
|
||
* 2009-04-06 JPP - Double-clicking no longer toggles the checkbox
|
||
* - Double-clicking on a checkbox no longer confuses the checkbox
|
||
* 2009-03-16 JPP - Optimized the build of autocomplete lists
|
||
* v2.1
|
||
* 2009-02-24 JPP - Fix bug where double-clicking VERY quickly on two different cells
|
||
* could give two editors
|
||
* - Maintain focused item when rebuilding list (SF #2547060)
|
||
* 2009-02-22 JPP - Reworked checkboxes so that events are triggered for virtual lists
|
||
* 2009-02-15 JPP - Added ObjectListView.ConfigureAutoComplete utility method
|
||
* 2009-02-02 JPP - Fixed bug with AlwaysGroupByColumn where column header clicks would not resort groups.
|
||
* 2009-02-01 JPP - OLVColumn.CheckBoxes and TriStateCheckBoxes now work.
|
||
* 2009-01-28 JPP - Complete overhaul of renderers!
|
||
* - Use IRenderer
|
||
* - Added ObjectListView.ItemRenderer to draw whole items
|
||
* 2009-01-23 JPP - Simple Checkboxes now work properly
|
||
* - Added TriStateCheckBoxes property to control whether the user can
|
||
* set the row checkbox to have the Indeterminate value
|
||
* - CheckState property is now just a wrapper around the StateImageIndex property
|
||
* 2009-01-20 JPP - Changed to always draw columns when owner drawn, rather than falling back on DrawDefault.
|
||
* This simplified several owner drawn problems
|
||
* - Added DefaultRenderer property to help with the above
|
||
* - HotItem background color is applied to all cells even when FullRowSelect is false
|
||
* - Allow grouping by CheckedAspectName columns
|
||
* - Commented out experimental animations. Still needs work.
|
||
* 2009-01-17 JPP - Added HotItemStyle and UseHotItem to highlight the row under the cursor
|
||
* - Added UseCustomSelectionColors property
|
||
* - Owner draw mode now honors ForeColor and BackColor settings on the list
|
||
* 2009-01-16 JPP - Changed to use EditorRegistry rather than hard coding cell editors
|
||
* 2009-01-10 JPP - Changed to use Equals() method rather than == to compare model objects.
|
||
* v2.0.1
|
||
* 2009-01-08 JPP - Fixed long-standing "multiple columns generated" problem.
|
||
* Thanks to pinkjones for his help with solving this one!
|
||
* - Added EnsureGroupVisible()
|
||
* 2009-01-07 JPP - Made all public and protected methods virtual
|
||
* - FinishCellEditing, PossibleFinishCellEditing and CancelCellEditing are now public
|
||
* 2008-12-20 JPP - Fixed bug with group comparisons when a group key was null (SF#2445761)
|
||
* 2008-12-19 JPP - Fixed bug with space filling columns and layout events
|
||
* - Fixed RowHeight so that it only changes the row height, not the width of the images.
|
||
* v2.0
|
||
* 2008-12-10 JPP - Handle Backspace key. Resets the search-by-typing state without delay
|
||
* - Made some changes to the column collection editor to try and avoid
|
||
* the multiple column generation problem.
|
||
* - Updated some documentation
|
||
* 2008-12-07 JPP - Search-by-typing now works when showing groups
|
||
* - Added BeforeSearching and AfterSearching events which are triggered when the user types
|
||
* into the list.
|
||
* - Added secondary sort information to Before/AfterSorting events
|
||
* - Reorganized group sorting code. Now triggers Sorting events.
|
||
* - Added GetItemIndexInDisplayOrder()
|
||
* - Tweaked in the interaction of the column editor with the IDE so that we (normally)
|
||
* don't rely on a hack to find the owning ObjectListView
|
||
* - Changed all 'DefaultValue(typeof(Color), "Empty")' to 'DefaultValue(typeof(Color), "")'
|
||
* since the first does not given Color.Empty as I thought, but the second does.
|
||
* 2008-11-28 JPP - Fixed long standing bug with horizontal scrollbar when shrinking the window.
|
||
* (thanks to Bartosz Borowik)
|
||
* 2008-11-25 JPP - Added support for dynamic tooltips
|
||
* - Split out comparers and header controls stuff into their own files
|
||
* 2008-11-21 JPP - Fixed bug where enabling grouping when there was not a sort column would not
|
||
* produce a grouped list. Grouping column now defaults to column 0.
|
||
* - Preserve selection on virtual lists when sorting
|
||
* 2008-11-20 JPP - Added ability to search by sort column to ObjectListView. Unified this with
|
||
* ability that was already in VirtualObjectListView
|
||
* 2008-11-19 JPP - Fixed bug in ChangeToFilteredColumns() where DisplayOrder was not always restored correctly.
|
||
* 2008-10-29 JPP - Event argument blocks moved to directly within the namespace, rather than being
|
||
* nested inside ObjectListView class.
|
||
* - Removed OLVColumn.CellEditor since it was never used.
|
||
* - Marked OLVColumn.AspectGetterAutoGenerated as obsolete (it has not been used for
|
||
* several versions now).
|
||
* 2008-10-28 JPP - SelectedObjects is now an IList, rather than an ArrayList. This allows
|
||
* it to accept generic list (eg List<File>).
|
||
* 2008-10-09 JPP - Support indeterminate checkbox values.
|
||
* [BREAKING CHANGE] CheckStateGetter/CheckStatePutter now use CheckState types only.
|
||
* BooleanCheckStateGetter and BooleanCheckStatePutter added to ease transition.
|
||
* 2008-10-08 JPP - Added setFocus parameter to SelectObject(), which allows focus to be set
|
||
* at the same time as selecting.
|
||
* 2008-09-27 JPP - BIG CHANGE: Fissioned this file into separate files for each component
|
||
* 2008-09-24 JPP - Corrected bug with owner drawn lists where a column 0 with a renderer
|
||
* would draw at column 0 even if column 0 was dragged to another position.
|
||
* - Correctly handle space filling columns when columns are added/removed
|
||
* 2008-09-16 JPP - Consistently use try..finally for BeginUpdate()/EndUpdate() pairs
|
||
* 2008-08-24 JPP - If LastSortOrder is None when adding objects, don't force a resort.
|
||
* 2008-08-22 JPP - Catch and ignore some problems with setting TopIndex on FastObjectListViews.
|
||
* 2008-08-05 JPP - In the right-click column select menu, columns are now sorted by display order, rather than alphabetically
|
||
* v1.13
|
||
* 2008-07-23 JPP - Consistently use copy-on-write semantics with Add/RemoveObject methods
|
||
* 2008-07-10 JPP - Enable validation on cell editors through a CellEditValidating event.
|
||
* (thanks to Artiom Chilaru for the initial suggestion and implementation).
|
||
* 2008-07-09 JPP - Added HeaderControl.Handle to allow OLV to be used within UserControls.
|
||
* (thanks to Michael Coffey for tracking this down).
|
||
* 2008-06-23 JPP - Split the more generally useful CopyObjectsToClipboard() method
|
||
* out of CopySelectionToClipboard()
|
||
* 2008-06-22 JPP - Added AlwaysGroupByColumn and AlwaysGroupBySortOrder, which
|
||
* force the list view to always be grouped by a particular column.
|
||
* 2008-05-31 JPP - Allow check boxes on FastObjectListViews
|
||
* - Added CheckedObject and CheckedObjects properties
|
||
* 2008-05-11 JPP - Allow selection foreground and background colors to be changed.
|
||
* Windows doesn't allow this, so we can only make it happen when owner
|
||
* drawing. Set the HighlightForegroundColor and HighlightBackgroundColor
|
||
* properties and then call EnableCustomSelectionColors().
|
||
* v1.12
|
||
* 2008-05-08 JPP - Fixed bug where the column select menu would not appear if the
|
||
* ObjectListView has a context menu installed.
|
||
* 2008-05-05 JPP - Non detail views can now be owner drawn. The renderer installed for
|
||
* primary column is given the chance to render the whole item.
|
||
* See BusinessCardRenderer in the demo for an example.
|
||
* - BREAKING CHANGE: RenderDelegate now returns a bool to indicate if default
|
||
* rendering should be done. Previously returned void. Only important if your
|
||
* code used RendererDelegate directly. Renderers derived from BaseRenderer
|
||
* are unchanged.
|
||
* 2008-05-03 JPP - Changed cell editing to use values directly when the values are Strings.
|
||
* Previously, values were always handed to the AspectToStringConverter.
|
||
* - When editing a cell, tabbing no longer tries to edit the next subitem
|
||
* when not in details view!
|
||
* 2008-05-02 JPP - MappedImageRenderer can now handle a Aspects that return a collection
|
||
* of values. Each value will be drawn as its own image.
|
||
* - Made AddObjects() and RemoveObjects() work for all flavours (or at least not crash)
|
||
* - Fixed bug with clearing virtual lists that has been scrolled vertically
|
||
* - Made TopItemIndex work with virtual lists.
|
||
* 2008-05-01 JPP - Added AddObjects() and RemoveObjects() to allow faster mods to the list
|
||
* - Reorganised public properties. Now alphabetical.
|
||
* - Made the class ObjectListViewState internal, as it always should have been.
|
||
* v1.11
|
||
* 2008-04-29 JPP - Preserve scroll position when building the list or changing columns.
|
||
* - Added TopItemIndex property. Due to problems with the underlying control, this
|
||
* property is not always reliable. See property docs for info.
|
||
* 2008-04-27 JPP - Added SelectedIndex property.
|
||
* - Use a different, more general strategy to handle Invoke(). Removed all delegates
|
||
* that were only declared to support Invoke().
|
||
* - Check all native structures for 64-bit correctness.
|
||
* 2008-04-25 JPP - Released on SourceForge.
|
||
* 2008-04-13 JPP - Added ColumnRightClick event.
|
||
* - Made the assembly CLS-compliant. To do this, our cell editors were made internal, and
|
||
* the constraint on FlagRenderer template parameter was removed (the type must still
|
||
* be an IConvertible, but if it isn't, the error will be caught at runtime, not compile time).
|
||
* 2008-04-12 JPP - Changed HandleHeaderRightClick() to have a columnIndex parameter, which tells
|
||
* exactly which column was right-clicked.
|
||
* 2008-03-31 JPP - Added SaveState() and RestoreState()
|
||
* - When cell editing, scrolling with a mouse wheel now ends the edit operation.
|
||
* v1.10
|
||
* 2008-03-25 JPP - Added space filling columns. See OLVColumn.FreeSpaceProportion property for details.
|
||
* A space filling columns fills all (or a portion) of the width unoccupied by other columns.
|
||
* 2008-03-23 JPP - Finished tinkering with support for Mono. Compile with conditional compilation symbol 'MONO'
|
||
* to enable. On Windows, current problems with Mono:
|
||
* - grid lines on virtual lists crashes
|
||
* - when grouped, items sometimes are not drawn when any item is scrolled out of view
|
||
* - i can't seem to get owner drawing to work
|
||
* - when editing cell values, the editing controls always appear behind the listview,
|
||
* where they function fine -- the user just can't see them :-)
|
||
* 2008-03-16 JPP - Added some methods suggested by Chris Marlowe (thanks for the suggestions Chris)
|
||
* - ClearObjects()
|
||
* - GetCheckedObject(), GetCheckedObjects()
|
||
* - GetItemAt() variation that gets both the item and the column under a point
|
||
* 2008-02-28 JPP - Fixed bug with subitem colors when using OwnerDrawn lists and a RowFormatter.
|
||
* v1.9.1
|
||
* 2008-01-29 JPP - Fixed bug that caused owner-drawn virtual lists to use 100% CPU
|
||
* - Added FlagRenderer to help draw bitwise-OR'ed flag values
|
||
* 2008-01-23 JPP - Fixed bug (introduced in v1.9) that made alternate row colour with groups not quite right
|
||
* - Ensure that DesignerSerializationVisibility.Hidden is set on all non-browsable properties
|
||
* - Make sure that sort indicators are shown after changing which columns are visible
|
||
* 2008-01-21 JPP - Added FastObjectListView
|
||
* v1.9
|
||
* 2008-01-18 JPP - Added IncrementalUpdate()
|
||
* 2008-01-16 JPP - Right clicking on column header will allow the user to choose which columns are visible.
|
||
* Set SelectColumnsOnRightClick to false to prevent this behaviour.
|
||
* - Added ImagesRenderer to draw more than one images in a column
|
||
* - Changed the positioning of the empty list m to use all the client area. Thanks to Matze.
|
||
* 2007-12-13 JPP - Added CopySelectionToClipboard(). Ctrl-C invokes this method. Supports text
|
||
* and HTML formats.
|
||
* 2007-12-12 JPP - Added support for checkboxes via CheckStateGetter and CheckStatePutter properties.
|
||
* - Made ObjectListView and OLVColumn into partial classes so that others can extend them.
|
||
* 2007-12-09 JPP - Added ability to have hidden columns, i.e. columns that the ObjectListView knows
|
||
* about but that are not visible to the user. Controlled by OLVColumn.IsVisible.
|
||
* Added ColumnSelectionForm to the project to show how it could be used in an application.
|
||
*
|
||
* v1.8
|
||
* 2007-11-26 JPP - Cell editing fully functional
|
||
* 2007-11-21 JPP - Added SelectionChanged event. This event is triggered once when the
|
||
* selection changes, no matter how many items are selected or deselected (in
|
||
* contrast to SelectedIndexChanged which is called once for every row that
|
||
* is selected or deselected). Thanks to lupokehl42 (Daniel) for his suggestions and
|
||
* improvements on this idea.
|
||
* 2007-11-19 JPP - First take at cell editing
|
||
* 2007-11-17 JPP - Changed so that items within a group are not sorted if lastSortOrder == None
|
||
* - Only call MakeSortIndicatorImages() if we haven't already made the sort indicators
|
||
* (Corrected misspelling in the name of the method too)
|
||
* 2007-11-06 JPP - Added ability to have secondary sort criteria when sorting
|
||
* (SecondarySortColumn and SecondarySortOrder properties)
|
||
* - Added SortGroupItemsByPrimaryColumn to allow group items to be sorted by the
|
||
* primary column. Previous default was to sort by the grouping column.
|
||
* v1.7
|
||
* No big changes to this version but made to work with ListViewPrinter and released with it.
|
||
*
|
||
* 2007-11-05 JPP - Changed BaseRenderer to use DrawString() rather than TextRenderer, since TextRenderer
|
||
* does not work when printing.
|
||
* v1.6
|
||
* 2007-11-03 JPP - Fixed some bugs in the rebuilding of DataListView.
|
||
* 2007-10-31 JPP - Changed to use builtin sort indicators on XP and later. This also avoids alignment
|
||
* problems on Vista. (thanks to gravybod for the suggestion and example implementation)
|
||
* 2007-10-21 JPP - Added MinimumWidth and MaximumWidth properties to OLVColumn.
|
||
* - Added ability for BuildList() to preserve selection. Calling BuildList() directly
|
||
* tries to preserve selection; calling SetObjects() does not.
|
||
* - Added SelectAll() and DeselectAll() methods. Useful for working with large lists.
|
||
* 2007-10-08 JPP - Added GetNextItem() and GetPreviousItem(), which walk sequentially through the
|
||
* listview items, even when the view is grouped.
|
||
* - Added SelectedItem property
|
||
* 2007-09-28 JPP - Optimized aspect-to-string conversion. BuildList() 15% faster.
|
||
* - Added empty implementation of RefreshObjects() to VirtualObjectListView since
|
||
* RefreshObjects() cannot work on virtual lists.
|
||
* 2007-09-13 JPP - Corrected bug with custom sorter in VirtualObjectListView (thanks for mpgjunky)
|
||
* 2007-09-07 JPP - Corrected image scaling bug in DrawAlignedImage() (thanks to krita970)
|
||
* 2007-08-29 JPP - Allow item count labels on groups to be set per column (thanks to cmarlow for idea)
|
||
* 2007-08-14 JPP - Major rework of DataListView based on Ian Griffiths's great work
|
||
* 2007-08-11 JPP - When empty, the control can now draw a "List Empty" m
|
||
* - Added GetColumn() and GetItem() methods
|
||
* v1.5
|
||
* 2007-08-03 JPP - Support animated GIFs in ImageRenderer
|
||
* - Allow height of rows to be specified - EXPERIMENTAL!
|
||
* 2007-07-26 JPP - Optimised redrawing of owner-drawn lists by remembering the update rect
|
||
* - Allow sort indicators to be turned off
|
||
* 2007-06-30 JPP - Added RowFormatter delegate
|
||
* - Allow a different label when there is only one item in a group (thanks to cmarlow)
|
||
* v1.4
|
||
* 2007-04-12 JPP - Allow owner drawn on steriods!
|
||
* - Column headers now display sort indicators
|
||
* - ImageGetter delegates can now return ints, strings or Images
|
||
* (Images are only visible if the list is owner drawn)
|
||
* - Added OLVColumn.MakeGroupies to help with group partitioning
|
||
* - All normal listview views are now supported
|
||
* - Allow dotted aspect names, e.g. Owner.Workgroup.Name (thanks to OlafD)
|
||
* - Added SelectedObject and SelectedObjects properties
|
||
* v1.3
|
||
* 2007-03-01 JPP - Added DataListView
|
||
* - Added VirtualObjectListView
|
||
* - Added Freeze/Unfreeze capabilities
|
||
* - Allowed sort handler to be installed
|
||
* - Simplified sort comparisons: handles 95% of cases with only 6 lines of code!
|
||
* - Fixed bug with alternative line colors on unsorted lists (thanks to cmarlow)
|
||
* 2007-01-13 JPP - Fixed bug with lastSortOrder (thanks to Kwan Fu Sit)
|
||
* - Non-OLVColumns are no longer allowed
|
||
* 2007-01-04 JPP - Clear sorter before rebuilding list. 10x faster! (thanks to aaberg)
|
||
* - Include GetField in GetAspectByName() so field values can be Invoked too.
|
||
* - Fixed subtle bug in RefreshItem() that erased background colors.
|
||
* 2006-11-01 JPP - Added alternate line colouring
|
||
* 2006-10-20 JPP - Refactored all sorting comparisons and made it extendable. See ComparerManager.
|
||
* - Improved IDE integration
|
||
* - Made control DoubleBuffered
|
||
* - Added object selection methods
|
||
* 2006-10-13 JPP Implemented grouping and column sorting
|
||
* 2006-10-09 JPP Initial version
|
||
*
|
||
* TO DO:
|
||
* - Support undocumented group features: subseted groups, group footer items
|
||
*
|
||
* Copyright (C) 2006-2016 Phillip Piper
|
||
*
|
||
* This program is free software: you can redistribute it and/or modify
|
||
* it under the terms of the GNU General Public License as published by
|
||
* the Free Software Foundation, either version 3 of the License, or
|
||
* (at your option) any later version.
|
||
*
|
||
* This program is distributed in the hope that it will be useful,
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
* GNU General Public License for more details.
|
||
*
|
||
* You should have received a copy of the GNU General Public License
|
||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
*
|
||
* If you wish to use this code in a closed source application, please contact phillip.piper@gmail.com.
|
||
*/
|
||
|
||
using System;
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using System.ComponentModel;
|
||
using System.Diagnostics;
|
||
using System.Drawing;
|
||
using System.Globalization;
|
||
using System.IO;
|
||
using System.Reflection;
|
||
using System.Runtime.InteropServices;
|
||
using System.Runtime.Serialization.Formatters.Binary;
|
||
using System.Windows.Forms;
|
||
using System.Windows.Forms.VisualStyles;
|
||
using System.Runtime.Serialization.Formatters;
|
||
using System.Threading;
|
||
|
||
namespace BrightIdeasSoftware
|
||
{
|
||
/// <summary>
|
||
/// An ObjectListView is a much easier to use, and much more powerful, version of the ListView.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// An ObjectListView automatically populates a ListView control with information taken
|
||
/// from a given collection of objects. It can do this because each column is configured
|
||
/// to know which bit of the model object (the "aspect") it should be displaying. Columns similarly
|
||
/// understand how to sort the list based on their aspect, and how to construct groups
|
||
/// using their aspect.
|
||
/// </para>
|
||
/// <para>
|
||
/// Aspects are extracted by giving the name of a method to be called or a
|
||
/// property to be fetched. These names can be simple names or they can be dotted
|
||
/// to chain property access e.g. "Owner.Address.Postcode".
|
||
/// Aspects can also be extracted by installing a delegate.
|
||
/// </para>
|
||
/// <para>
|
||
/// An ObjectListView can show a "this list is empty" message when there is nothing to show in the list,
|
||
/// so that the user knows the control is supposed to be empty.
|
||
/// </para>
|
||
/// <para>
|
||
/// Right clicking on a column header should present a menu which can contain:
|
||
/// commands (sort, group, ungroup); filtering; and column selection. Whether these
|
||
/// parts of the menu appear is controlled by ShowCommandMenuOnRightClick,
|
||
/// ShowFilterMenuOnRightClick and SelectColumnsOnRightClick respectively.
|
||
/// </para>
|
||
/// <para>
|
||
/// The groups created by an ObjectListView can be configured to include other formatting
|
||
/// information, including a group icon, subtitle and task button. Using some undocumented
|
||
/// interfaces, these groups can even on virtual lists.
|
||
/// </para>
|
||
/// <para>
|
||
/// ObjectListView supports dragging rows to other places, including other application.
|
||
/// Special support is provide for drops from other ObjectListViews in the same application.
|
||
/// In many cases, an ObjectListView becomes a full drag source by setting <see cref="IsSimpleDragSource"/> to
|
||
/// true. Similarly, to accept drops, it is usually enough to set <see cref="IsSimpleDropSink"/> to true,
|
||
/// and then handle the <see cref="CanDrop"/> and <see cref="Dropped"/> events (or the <see cref="ModelCanDrop"/> and
|
||
/// <see cref="ModelDropped"/> events, if you only want to handle drops from other ObjectListViews in your application).
|
||
/// </para>
|
||
/// <para>
|
||
/// For these classes to build correctly, the project must have references to these assemblies:
|
||
/// </para>
|
||
/// <list type="bullet">
|
||
/// <item><description>System</description></item>
|
||
/// <item><description>System.Data</description></item>
|
||
/// <item><description>System.Design</description></item>
|
||
/// <item><description>System.Drawing</description></item>
|
||
/// <item><description>System.Windows.Forms (obviously)</description></item>
|
||
/// </list>
|
||
/// </remarks>
|
||
[Designer(typeof(BrightIdeasSoftware.Design.ObjectListViewDesigner))]
|
||
public partial class ObjectListView : ListView, ISupportInitialize {
|
||
|
||
#region Life and death
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> ObjectListView
|
||
/// </summary>
|
||
public ObjectListView() {
|
||
this.ColumnClick += new ColumnClickEventHandler(this.HandleColumnClick);
|
||
this.Layout += new LayoutEventHandler(this.HandleLayout);
|
||
this.ColumnWidthChanging += new ColumnWidthChangingEventHandler(this.HandleColumnWidthChanging);
|
||
this.ColumnWidthChanged += new ColumnWidthChangedEventHandler(this.HandleColumnWidthChanged);
|
||
base.ShowGroups = false;
|
||
base.View = View.Details;
|
||
base.FullRowSelect = true;
|
||
// Turn on owner draw so that we are responsible for our own fates (and isolated from bugs in the underlying ListView)
|
||
this.OwnerDraw = true;
|
||
|
||
// ReSharper disable DoNotCallOverridableMethodsInConstructor
|
||
this.DoubleBuffered = true; // kill nasty flickers. hiss... me hates 'em
|
||
this.ShowSortIndicators = true;
|
||
|
||
// Setup the overlays that will be controlled by the IDE settings
|
||
this.InitializeStandardOverlays();
|
||
this.InitializeEmptyListMsgOverlay();
|
||
// ReSharper restore DoNotCallOverridableMethodsInConstructor
|
||
}
|
||
|
||
/// <summary>
|
||
/// Dispose of any resources this instance has been using
|
||
/// </summary>
|
||
/// <param name="disposing"></param>
|
||
protected override void Dispose(bool disposing) {
|
||
base.Dispose(disposing);
|
||
|
||
if (!disposing)
|
||
return;
|
||
|
||
foreach (GlassPanelForm glassPanel in this.glassPanels) {
|
||
glassPanel.Unbind();
|
||
glassPanel.Dispose();
|
||
}
|
||
this.glassPanels.Clear();
|
||
|
||
this.UnsubscribeNotifications(null);
|
||
}
|
||
|
||
#endregion
|
||
|
||
// TODO
|
||
//public CheckBoxSettings CheckBoxSettings {
|
||
// get { return checkBoxSettings; }
|
||
// private set { checkBoxSettings = value; }
|
||
//}
|
||
|
||
#region Static properties
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7>ڴ<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>¡<EFBFBD>
|
||
/// </summary>
|
||
public static bool IsLeftMouseDown {
|
||
get { return (Control.MouseButtons & MouseButtons.Left) == MouseButtons.Left; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD>ó<EFBFBD><C3B3><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>Vista<74><61><EFBFBD><EFBFBD><EFBFBD>߰汾<DFB0><E6B1BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
static public bool IsVistaOrLater {
|
||
get {
|
||
if (!ObjectListView.sIsVistaOrLater.HasValue)
|
||
ObjectListView.sIsVistaOrLater = Environment.OSVersion.Version.Major >= 6;
|
||
return ObjectListView.sIsVistaOrLater.Value;
|
||
}
|
||
}
|
||
static private bool? sIsVistaOrLater;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD>ó<EFBFBD><C3B3><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>Win7<6E><37><EFBFBD><EFBFBD><EFBFBD>߰汾<DFB0><E6B1BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
static public bool IsWin7OrLater {
|
||
get {
|
||
if (!ObjectListView.sIsWin7OrLater.HasValue) {
|
||
// For some reason, Win7 is v6.1, not v7.0
|
||
Version version = Environment.OSVersion.Version;
|
||
ObjectListView.sIsWin7OrLater = version.Major > 6 || (version.Major == 6 && version.Minor > 0);
|
||
}
|
||
return ObjectListView.sIsWin7OrLater.Value;
|
||
}
|
||
}
|
||
static private bool? sIsWin7OrLater;
|
||
|
||
/// <summary>
|
||
/// Gets or sets how what smoothing mode will be applied to graphic operations.
|
||
/// </summary>
|
||
static public System.Drawing.Drawing2D.SmoothingMode SmoothingMode {
|
||
get { return ObjectListView.sSmoothingMode; }
|
||
set { ObjectListView.sSmoothingMode = value; }
|
||
}
|
||
static private System.Drawing.Drawing2D.SmoothingMode sSmoothingMode =
|
||
System.Drawing.Drawing2D.SmoothingMode.HighQuality;
|
||
|
||
/// <summary>
|
||
/// Gets or sets how should text be renderered.
|
||
/// </summary>
|
||
static public System.Drawing.Text.TextRenderingHint TextRenderingHint {
|
||
get { return ObjectListView.sTextRendereringHint; }
|
||
set { ObjectListView.sTextRendereringHint = value; }
|
||
}
|
||
static private System.Drawing.Text.TextRenderingHint sTextRendereringHint =
|
||
System.Drawing.Text.TextRenderingHint.SystemDefault;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD><C3B5><EFBFBD>KeyΪNullʱ<6C><CAB1><EFBFBD><EFBFBD><EFBFBD>ڱ<EFBFBD><DAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>乫<EFBFBD><E4B9AB><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD><D4B1>ػ<EFBFBD><D8BB><EFBFBD>
|
||
/// </summary>
|
||
static public string GroupTitleDefault {
|
||
get { return ObjectListView.sGroupTitleDefault; }
|
||
set { ObjectListView.sGroupTitleDefault = value ?? "{<7B><EFBFBD><DEB7><EFBFBD>}"; }
|
||
}static private string sGroupTitleDefault = "{<7B><EFBFBD><DEB7><EFBFBD>}";
|
||
|
||
/// <summary>
|
||
/// Convert the given enumerable into an ArrayList as efficiently as possible
|
||
/// </summary>
|
||
/// <param name="collection">The source collection</param>
|
||
/// <param name="alwaysCreate">If true, this method will always create a new
|
||
/// collection.</param>
|
||
/// <returns>An ArrayList with the same contents as the given collection.</returns>
|
||
/// <remarks>
|
||
/// <para>When we move to .NET 3.5, we can use LINQ and not need this method.</para>
|
||
/// </remarks>
|
||
public static ArrayList EnumerableToArray(IEnumerable collection, bool alwaysCreate) {
|
||
if (collection == null)
|
||
return new ArrayList();
|
||
|
||
if (!alwaysCreate) {
|
||
ArrayList array = collection as ArrayList;
|
||
if (array != null)
|
||
return array;
|
||
|
||
IList iList = collection as IList;
|
||
if (iList != null)
|
||
return ArrayList.Adapter(iList);
|
||
}
|
||
|
||
ICollection iCollection = collection as ICollection;
|
||
if (iCollection != null)
|
||
return new ArrayList(iCollection);
|
||
|
||
ArrayList newObjects = new ArrayList();
|
||
foreach (object x in collection)
|
||
newObjects.Add(x);
|
||
return newObjects;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// Return the count of items in the given enumerable
|
||
/// </summary>
|
||
/// <param name="collection"></param>
|
||
/// <returns></returns>
|
||
/// <remarks>When we move to .NET 3.5, we can use LINQ and not need this method.</remarks>
|
||
public static int EnumerableCount(IEnumerable collection) {
|
||
if (collection == null)
|
||
return 0;
|
||
|
||
ICollection iCollection = collection as ICollection;
|
||
if (iCollection != null)
|
||
return iCollection.Count;
|
||
|
||
int i = 0;
|
||
// ReSharper disable once UnusedVariable
|
||
foreach (object x in collection)
|
||
i++;
|
||
return i;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Return whether or not the given enumerable is empty. A string is regarded as
|
||
/// an empty collection.
|
||
/// </summary>
|
||
/// <param name="collection"></param>
|
||
/// <returns>True if the given collection is null or empty</returns>
|
||
/// <remarks>
|
||
/// <para>When we move to .NET 3.5, we can use LINQ and not need this method.</para>
|
||
/// </remarks>
|
||
public static bool IsEnumerableEmpty(IEnumerable collection) {
|
||
return collection == null || (collection is string) || !collection.GetEnumerator().MoveNext();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets whether all ObjectListViews will silently ignore missing aspect errors.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// By default, if an ObjectListView is asked to display an aspect
|
||
/// (i.e. a field/property/method)
|
||
/// that does not exist from a model, it displays an error message in that cell, since that
|
||
/// condition is normally a programming error. There are some use cases where
|
||
/// this is not an error -- in those cases, set this to true and ObjectListView will
|
||
/// simply display an empty cell.
|
||
/// </para>
|
||
/// <para>Be warned: if you set this to true, it can be very difficult to track down
|
||
/// typing mistakes or name changes in AspectNames.</para>
|
||
/// </remarks>
|
||
public static bool IgnoreMissingAspects {
|
||
get { return Munger.IgnoreMissingAspects; }
|
||
set { Munger.IgnoreMissingAspects = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets whether the control will draw a rectangle in each cell showing the cell padding.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// This can help with debugging display problems from cell padding.
|
||
/// </para>
|
||
/// <para>As with all cell padding, this setting only takes effect when the control is owner drawn.</para>
|
||
/// </remarks>
|
||
public static bool ShowCellPaddingBounds {
|
||
get { return sShowCellPaddingBounds; }
|
||
set { sShowCellPaddingBounds = value; }
|
||
}
|
||
private static bool sShowCellPaddingBounds;
|
||
|
||
/// <summary>
|
||
/// Gets the style that will be used by default to format disabled rows
|
||
/// </summary>
|
||
public static SimpleItemStyle DefaultDisabledItemStyle {
|
||
get {
|
||
if (sDefaultDisabledItemStyle == null) {
|
||
sDefaultDisabledItemStyle = new SimpleItemStyle();
|
||
sDefaultDisabledItemStyle.ForeColor = Color.DarkGray;
|
||
}
|
||
return sDefaultDisabledItemStyle;
|
||
}
|
||
}
|
||
private static SimpleItemStyle sDefaultDisabledItemStyle;
|
||
|
||
/// <summary>
|
||
/// Gets the style that will be used by default to format hot rows
|
||
/// </summary>
|
||
public static HotItemStyle DefaultHotItemStyle {
|
||
get {
|
||
if (sDefaultHotItemStyle == null) {
|
||
sDefaultHotItemStyle = new HotItemStyle();
|
||
sDefaultHotItemStyle.BackColor = Color.FromArgb(224, 235, 253);
|
||
}
|
||
return sDefaultHotItemStyle;
|
||
}
|
||
}
|
||
private static HotItemStyle sDefaultHotItemStyle;
|
||
|
||
#endregion
|
||
|
||
#region Public properties
|
||
|
||
/// <summary>
|
||
/// Gets or sets an model filter that is combined with any column filtering that the end-user specifies.
|
||
/// </summary>
|
||
/// <remarks>This is different from the ModelFilter property, since setting that will replace
|
||
/// any column filtering, whereas setting this will combine this filter with the column filtering</remarks>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual IModelFilter AdditionalFilter
|
||
{
|
||
get { return this.additionalFilter; }
|
||
set
|
||
{
|
||
if (this.additionalFilter == value)
|
||
return;
|
||
this.additionalFilter = value;
|
||
this.UpdateColumnFiltering();
|
||
}
|
||
}
|
||
private IModelFilter additionalFilter;
|
||
|
||
/// <summary>
|
||
/// Get or set all the columns that this control knows about.
|
||
/// Only those columns where IsVisible is true will be seen by the user.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// If you want to add new columns programmatically, add them to
|
||
/// AllColumns and then call RebuildColumns(). Normally, you do not have to
|
||
/// deal with this property directly. Just use the IDE.
|
||
/// </para>
|
||
/// <para>If you do add or remove columns from the AllColumns collection,
|
||
/// you have to call RebuildColumns() to make those changes take effect.</para>
|
||
/// </remarks>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
|
||
public virtual List<OLVColumn> AllColumns {
|
||
get { return this.allColumns; }
|
||
set { this.allColumns = value ?? new List<OLVColumn>(); }
|
||
}
|
||
private List<OLVColumn> allColumns = new List<OLVColumn>();
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><C3BF>һ<EFBFBD>еı<D0B5><C4B1><EFBFBD>ɫ
|
||
/// </summary>
|
||
[Category("ObjectListView"),
|
||
Description("<22><><EFBFBD><EFBFBD>ʹ<EFBFBD>ý<EFBFBD><C3BD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>еı<D0B5><C4B1><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>ʲô<CAB2><C3B4>ɫ?"),
|
||
DefaultValue(typeof(Color), "")]
|
||
public Color AlternateRowBackColor {
|
||
get { return alternateRowBackColor; }
|
||
set { alternateRowBackColor = value; }
|
||
}
|
||
private Color alternateRowBackColor = Color.Empty;
|
||
|
||
/// <summary>
|
||
///<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>õĽ<C3B5><C4BD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ɫ<EFBFBD><C9AB>Ĭ<EFBFBD><C4AC><EFBFBD><EFBFBD>ɫ
|
||
/// </summary>
|
||
[Browsable(false)]
|
||
public virtual Color AlternateRowBackColorOrDefault {
|
||
get {
|
||
return this.alternateRowBackColor == Color.Empty ? Color.LemonChiffon : this.alternateRowBackColor;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
///<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǿ<EFBFBD><C7BF>ObjectListViewʼ<77>հ<EFBFBD><D5B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>з<EFBFBD><D0B7>顣
|
||
/// </summary>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual OLVColumn AlwaysGroupByColumn {
|
||
get { return alwaysGroupByColumn; }
|
||
set { alwaysGroupByColumn = value; }
|
||
}
|
||
private OLVColumn alwaysGroupByColumn;
|
||
|
||
/// <summary>
|
||
///<2F><><EFBFBD><EFBFBD>AlwaysGroupByColumn<6D><6E>Ϊ<EFBFBD>գ<EFBFBD><D5A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD><D4BD><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD><EFBFBD>ζ<EFBFBD><CEB6><EFBFBD>Щ<EFBFBD><D0A9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
///<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ե<EFBFBD>ֵΪSortOrder.None<6E><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD><EFBFBD><F2BDABB8><EFBFBD><EFBFBD>û<EFBFBD><C3BB>ϴε<CFB4><CEB5><EFBFBD><EFBFBD>ı<EFBFBD><C4B1><EFBFBD><EFBFBD>л<EFBFBD><D0BB><EFBFBD>
|
||
/// </summary>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual SortOrder AlwaysGroupBySortOrder {
|
||
get { return alwaysGroupBySortOrder; }
|
||
set { alwaysGroupBySortOrder = value; }
|
||
}
|
||
private SortOrder alwaysGroupBySortOrder = SortOrder.None;
|
||
|
||
/// <summary>
|
||
/// Give access to the image list that is actually being used by the control
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Normally, it is preferable to use SmallImageList. Only use this property
|
||
/// if you know exactly what you are doing.
|
||
/// </remarks>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual ImageList BaseSmallImageList {
|
||
get { return base.SmallImageList; }
|
||
set { base.SmallImageList = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
///<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ñ༭<C3B1><E0BCAD>Ԫ<EFBFBD><D4AA><EFBFBD>ķ<EFBFBD>ʽ
|
||
/// </summary>
|
||
/// <remarks>Columns can also be marked as editable.</remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ñ༭<C3B1><E0BCAD>Ԫ<EFBFBD><D4AA><EFBFBD>ķ<EFBFBD>ʽ"),
|
||
DefaultValue(CellEditActivateMode.None)]
|
||
public virtual CellEditActivateMode CellEditActivation {
|
||
get { return cellEditActivation; }
|
||
set {
|
||
cellEditActivation = value;
|
||
if (this.Created)
|
||
this.Invalidate();
|
||
}
|
||
}
|
||
private CellEditActivateMode cellEditActivation = CellEditActivateMode.None;
|
||
|
||
/// <summary>
|
||
///<2F>༭<EFBFBD><E0BCAD>Ԫ<EFBFBD><D4AA>ʱ<EFBFBD><CAB1><EFBFBD>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA>(<28><>ȥ<EFBFBD><C8A5>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC>ʹ<EFBFBD>õ<EFBFBD><C3B5>κοռ<CEBF>)<29><>
|
||
/// Ĭ<><C4AC>ֵΪ true.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>This is always treated as true when the control is NOT owner drawn.</para>
|
||
/// <para>
|
||
/// When this is false and the control is owner drawn,
|
||
/// ObjectListView will try to calculate the width of the cell's
|
||
/// actual contents, and then size the editing control to be just the right width. If this is true,
|
||
/// the whole width of the cell will be used, regardless of the cell's contents.
|
||
/// </para>
|
||
/// <para>Each column can have a different value for property. This value from the control is only
|
||
/// used when a column is not specified one way or another.</para>
|
||
/// <para>Regardless of this setting, developers can specify the exact size of the editing control
|
||
/// by listening for the CellEditStarting event.</para>
|
||
/// </remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22>༭<EFBFBD><E0BCAD>Ԫ<EFBFBD><D4AA>ʱ<EFBFBD><CAB1><EFBFBD>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD>"),
|
||
DefaultValue(true)]
|
||
public virtual bool CellEditUseWholeCell {
|
||
get { return cellEditUseWholeCell; }
|
||
set { cellEditUseWholeCell = value; }
|
||
}
|
||
private bool cellEditUseWholeCell;
|
||
|
||
/// <summary>
|
||
/// Gets or sets the engine that will handle key presses during a cell edit operation.
|
||
/// Settings this to null will reset it to default value.
|
||
/// </summary>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public CellEditKeyEngine CellEditKeyEngine {
|
||
get { return this.cellEditKeyEngine ?? (this.cellEditKeyEngine = new CellEditKeyEngine()); }
|
||
set { this.cellEditKeyEngine = value; }
|
||
}
|
||
private CellEditKeyEngine cellEditKeyEngine;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1>ǰ<EFBFBD><C7B0><EFBFBD>ڱ༭<DAB1><E0BCAD>Ԫ<EFBFBD><D4AA><EFBFBD>Ŀؼ<C4BF><D8BC><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>This will obviously be null if no cell is being edited.</remarks>
|
||
[Browsable(false)]
|
||
public Control CellEditor {
|
||
get {
|
||
return this.cellEditor;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
///<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ñ༭<C3B1>ؼ<EFBFBD><D8BC><EFBFBD><EFBFBD><EFBFBD>Ե<EFBFBD><D4B5><EFBFBD>ұ<EFBFBD>Ե<EFBFBD>ĵ<EFBFBD>Ԫ<EFBFBD><D4AA>ʱTab<61><62><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>
|
||
///<2F><><EFBFBD><EFBFBD>ΪFalse(Ĭ<><C4AC>ֵ)<29><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Tab<61><62><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>ͬһ<CDAC>е<EFBFBD><D0B5><EFBFBD>һ<EFBFBD>ࡣ
|
||
///<2F><><EFBFBD><EFBFBD>ΪTrue<75><65><EFBFBD>༭<EFBFBD><E0BCAD><EFBFBD>ұߵĵ<DFB5>Ԫ<EFBFBD><D4AA>ʱ<EFBFBD><CAB1>Tab<61><62><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>У<EFBFBD>
|
||
///<2F>༭<EFBFBD><E0BCAD><EFBFBD><EFBFBD><EFBFBD>ߵĵ<DFB5>Ԫ<EFBFBD><D4AA>ʱ<EFBFBD><CAB1>Shift-Tab<61><62><EFBFBD>ϼ<EFBFBD><CFBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>һ<EFBFBD>С<EFBFBD>
|
||
/// </summary>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>Ԫ<EFBFBD><D4AA><EFBFBD>༭ʱ<E0BCAD>Ƿ<EFBFBD>Ӧʹ<D3A6><CAB9>Tab/Shift-Tab<61><62><EFBFBD>ϼ<EFBFBD><CFBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? "),
|
||
DefaultValue(false)]
|
||
public virtual bool CellEditTabChangesRows {
|
||
get { return cellEditTabChangesRows; }
|
||
set {
|
||
cellEditTabChangesRows = value;
|
||
if (cellEditTabChangesRows) {
|
||
this.CellEditKeyEngine.SetKeyBehaviour(Keys.Tab, CellEditCharacterBehaviour.ChangeColumnRight, CellEditAtEdgeBehaviour.ChangeRow);
|
||
this.CellEditKeyEngine.SetKeyBehaviour(Keys.Tab|Keys.Shift, CellEditCharacterBehaviour.ChangeColumnLeft, CellEditAtEdgeBehaviour.ChangeRow);
|
||
} else {
|
||
this.CellEditKeyEngine.SetKeyBehaviour(Keys.Tab, CellEditCharacterBehaviour.ChangeColumnRight, CellEditAtEdgeBehaviour.Wrap);
|
||
this.CellEditKeyEngine.SetKeyBehaviour(Keys.Tab | Keys.Shift, CellEditCharacterBehaviour.ChangeColumnLeft, CellEditAtEdgeBehaviour.Wrap);
|
||
}
|
||
}
|
||
}
|
||
private bool cellEditTabChangesRows;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ñ༭<C3B1><E0BCAD>Ԫ<EFBFBD><D4AA>ʱEnter<65><72><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>
|
||
/// <20><><EFBFBD><EFBFBD>ΪFalse(Ĭ<><C4AC>ֵ)<29><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Enter<65><72><EFBFBD><EFBFBD><EFBFBD><EFBFBD><F2B5A5B5><EFBFBD><EFBFBD>ɱ༭<C9B1><E0BCAD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// <20><><EFBFBD><EFBFBD>ΪTrue<75><65><EFBFBD><EFBFBD>Enter<65><72><EFBFBD><EFBFBD><EFBFBD>ɱ༭<C9B1><E0BCAD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD>ǰ<EFBFBD><C7B0>Ԫ<EFBFBD><D4AA><EFBFBD>·<EFBFBD><C2B7>ĵ<EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µı༭<C4B1><E0BCAD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD>ڵײ<DAB5><D7B2><EFBFBD>Ԫ<EFBFBD><D4AA>ʱ<EFBFBD><CAB1><EFBFBD>е<EFBFBD><D0B5><EFBFBD>һ<EFBFBD>еĶ<D0B5><C4B6><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ñ༭<C3B1><E0BCAD>Ԫ<EFBFBD><D4AA>ʱEnter<65><72><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ"),
|
||
DefaultValue(false)]
|
||
public virtual bool CellEditEnterChangesRows {
|
||
get { return cellEditEnterChangesRows; }
|
||
set {
|
||
cellEditEnterChangesRows = value;
|
||
if (cellEditEnterChangesRows) {
|
||
this.CellEditKeyEngine.SetKeyBehaviour(Keys.Enter, CellEditCharacterBehaviour.ChangeRowDown, CellEditAtEdgeBehaviour.ChangeColumn);
|
||
this.CellEditKeyEngine.SetKeyBehaviour(Keys.Enter | Keys.Shift, CellEditCharacterBehaviour.ChangeRowUp, CellEditAtEdgeBehaviour.ChangeColumn);
|
||
} else {
|
||
this.CellEditKeyEngine.SetKeyBehaviour(Keys.Enter, CellEditCharacterBehaviour.EndEdit, CellEditAtEdgeBehaviour.EndEdit);
|
||
this.CellEditKeyEngine.SetKeyBehaviour(Keys.Enter | Keys.Shift, CellEditCharacterBehaviour.EndEdit, CellEditAtEdgeBehaviour.EndEdit);
|
||
}
|
||
}
|
||
}
|
||
private bool cellEditEnterChangesRows;
|
||
|
||
/// <summary>
|
||
///<2F><>ȡ<EFBFBD><C8A1>ʾ<EFBFBD><CABE>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD>ʾ<EFBFBD>Ĺ<EFBFBD><C4B9><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD>ؼ<EFBFBD>
|
||
/// </summary>
|
||
[Browsable(false)]
|
||
public ToolTipControl CellToolTip {
|
||
get {
|
||
if (this.cellToolTip == null) {
|
||
this.CreateCellToolTip();
|
||
}
|
||
return this.cellToolTip;
|
||
}
|
||
}
|
||
private ToolTipControl cellToolTip;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ø<EFBFBD><C3B8><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD>Χ<EFBFBD><CEA7><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڿ<EFBFBD><DABF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>롣
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>Each value of the given rectangle will be treated as an inset from
|
||
/// the corresponding side. The width of the rectangle is the padding for the
|
||
/// right cell edge. The height of the rectangle is the padding for the bottom
|
||
/// cell edge.
|
||
/// </para>
|
||
/// <para>
|
||
/// So, this.olv1.CellPadding = new Rectangle(1, 2, 3, 4); will leave one pixel
|
||
/// of space to the left of the cell, 2 pixels at the top, 3 pixels of space
|
||
/// on the right edge, and 4 pixels of space at the bottom of each cell.
|
||
/// </para>
|
||
/// <para>
|
||
/// This setting only takes effect when the control is owner drawn.
|
||
/// </para>
|
||
/// <para>This setting only affects the contents of the cell. The background is
|
||
/// not affected.</para>
|
||
/// <para>If you set this to a foolish value, your control will appear to be empty.</para>
|
||
/// </remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ø<EFBFBD><C3B8><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD>Χ<EFBFBD><CEA7><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڿ<EFBFBD><DABF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>롣"),
|
||
DefaultValue(null)]
|
||
public Rectangle? CellPadding {
|
||
get { return this.cellPadding; }
|
||
set { this.cellPadding = value; }
|
||
}
|
||
private Rectangle? cellPadding;
|
||
|
||
/// <summary>
|
||
///<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><C4AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD>ʽ<EFBFBD><CABD>
|
||
/// </summary>
|
||
/// <remarks>This setting only takes effect when the control is owner drawn. It will only be noticable
|
||
/// when RowHeight has been set such that there is some vertical space in each row.</remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><C4AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD>ʽ<EFBFBD><CABD>"),
|
||
DefaultValue(StringAlignment.Center)]
|
||
public virtual StringAlignment CellVerticalAlignment {
|
||
get { return this.cellVerticalAlignment; }
|
||
set { this.cellVerticalAlignment = value; }
|
||
}
|
||
private StringAlignment cellVerticalAlignment = StringAlignment.Center;
|
||
|
||
/// <summary>
|
||
/// Should this list show checkboxes?
|
||
/// </summary>
|
||
public new bool CheckBoxes {
|
||
get { return base.CheckBoxes; }
|
||
set {
|
||
// Due to code in the base ListView class, turning off CheckBoxes on a virtual
|
||
// list always throws an InvalidOperationException. We have to do some major hacking
|
||
// to get around that
|
||
if (this.VirtualMode) {
|
||
// Leave virtual mode
|
||
this.StateImageList = null;
|
||
this.VirtualListSize = 0;
|
||
this.VirtualMode = false;
|
||
|
||
// Change the CheckBox setting while not in virtual mode
|
||
base.CheckBoxes = value;
|
||
|
||
// Reinstate virtual mode
|
||
this.VirtualMode = true;
|
||
|
||
// Re-enact the bits that we lost by switching to virtual mode
|
||
this.ShowGroups = this.ShowGroups;
|
||
this.BuildList(true);
|
||
} else {
|
||
base.CheckBoxes = value;
|
||
// Initialize the state image list so we can display indetermined values.
|
||
this.InitializeStateImageList();
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD>е<EFBFBD>ģ<EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δѡ<CEB4><D1A1><EFBFBD>л<EFBFBD>ѡ<EFBFBD>ж<EFBFBD><D0B6>У<EFBFBD><D0A3><EFBFBD>NULL
|
||
/// </summary>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual Object CheckedObject {
|
||
get {
|
||
IList checkedObjects = this.CheckedObjects;
|
||
return checkedObjects.Count == 1 ? checkedObjects[0] : null;
|
||
}
|
||
set {
|
||
this.CheckedObjects = new ArrayList(new Object[] { value });
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Get or set the collection of model objects that are checked.
|
||
/// When setting this property, any row whose model object isn't
|
||
/// in the given collection will be unchecked. Setting to null is
|
||
/// equivilent to unchecking all.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// This property returns a simple collection. Changes made to the returned
|
||
/// collection do NOT affect the list. This is different to the behaviour of
|
||
/// CheckedIndicies collection.
|
||
/// </para>
|
||
/// <para>
|
||
/// .NET's CheckedItems property is not helpful. It is just a short-hand for
|
||
/// iterating through the list looking for items that are checked.
|
||
/// </para>
|
||
/// <para>
|
||
/// The performance of the get method is O(n), where n is the number of items
|
||
/// in the control. The performance of the set method is
|
||
/// O(n + m) where m is the number of objects being checked. Be careful on long lists.
|
||
/// </para>
|
||
/// </remarks>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual IList CheckedObjects {
|
||
get {
|
||
ArrayList list = new ArrayList();
|
||
if (this.CheckBoxes) {
|
||
for (int i = 0; i < this.GetItemCount(); i++) {
|
||
OLVListItem olvi = this.GetItem(i);
|
||
if (olvi.CheckState == CheckState.Checked)
|
||
list.Add(olvi.RowObject);
|
||
}
|
||
}
|
||
return list;
|
||
}
|
||
set {
|
||
if (!this.CheckBoxes)
|
||
return;
|
||
|
||
Stopwatch sw = Stopwatch.StartNew();
|
||
|
||
// Set up an efficient way of testing for the presence of a particular model
|
||
Hashtable table = new Hashtable(this.GetItemCount());
|
||
if (value != null) {
|
||
foreach (object x in value)
|
||
table[x] = true;
|
||
}
|
||
|
||
this.BeginUpdate();
|
||
foreach (Object x in this.Objects) {
|
||
this.SetObjectCheckedness(x, table.ContainsKey(x) ? CheckState.Checked : CheckState.Unchecked);
|
||
}
|
||
this.EndUpdate();
|
||
|
||
Debug.WriteLine(String.Format("PERF - Setting CheckedObjects on {2} objects took {0}ms / {1} ticks", sw.ElapsedMilliseconds, sw.ElapsedTicks, this.GetItemCount()));
|
||
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
///<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD>ö<EFBFBD>ٶ<EFBFBD><D9B6><EFBFBD><EFBFBD>е<EFBFBD>ѡ<EFBFBD>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Useful for checking all objects in the list.
|
||
/// </remarks>
|
||
/// <example>
|
||
/// this.olv1.CheckedObjectsEnumerable = this.olv1.Objects;
|
||
/// </example>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual IEnumerable CheckedObjectsEnumerable {
|
||
get {
|
||
return this.CheckedObjects;
|
||
}
|
||
set {
|
||
this.CheckedObjects = ObjectListView.EnumerableToArray(value, true);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets Columns for this list. We hide the original so we can associate
|
||
/// a specialised editor with it.
|
||
/// </summary>
|
||
[Editor("BrightIdeasSoftware.Design.OLVColumnCollectionEditor", "System.Drawing.Design.UITypeEditor")]
|
||
new public ListView.ColumnHeaderCollection Columns {
|
||
get {
|
||
return base.Columns;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
///<2F><>ȡ/<2F><><EFBFBD>õ<EFBFBD><C3B5>б<EFBFBD><D0B1>л<EFBFBD><D0BB><EFBFBD>TileView(ƽ<><C6BD><EFBFBD><EFBFBD>ͼ)ʱӦʹ<D3A6>õ<EFBFBD><C3B5>е<EFBFBD><D0B5>б<EFBFBD><D0B1><EFBFBD>
|
||
/// </summary>
|
||
[Browsable(false),
|
||
Obsolete("Use GetFilteredColumns() and OLVColumn.IsTileViewColumn instead"),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public List<OLVColumn> ColumnsForTileView {
|
||
get { return this.GetFilteredColumns(View.Tile); }
|
||
}
|
||
|
||
/// <summary>
|
||
///<2F><><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD>ʾ<EFBFBD><CABE>˳<EFBFBD>ؿɼ<D8BF><C9BC><EFBFBD>
|
||
/// </summary>
|
||
[Browsable(false)]
|
||
public virtual List<OLVColumn> ColumnsInDisplayOrder {
|
||
get {
|
||
OLVColumn[] columnsInDisplayOrder = new OLVColumn[this.Columns.Count];
|
||
foreach (OLVColumn col in this.Columns) {
|
||
columnsInDisplayOrder[col.DisplayIndex] = col;
|
||
}
|
||
return new List<OLVColumn>(columnsInDisplayOrder);
|
||
}
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1>ʾ<EFBFBD>б<EFBFBD><D0B1>Ŀؼ<C4BF><D8BC><EFBFBD><EFBFBD><EFBFBD>ȥ<EFBFBD>κα<CEBA><CEB1><EFBFBD><EFBFBD>ؼ<EFBFBD>
|
||
/// </summary>
|
||
[Browsable(false)]
|
||
public Rectangle ContentRectangle {
|
||
get {
|
||
Rectangle r = this.ClientRectangle;
|
||
|
||
// If the listview has a header control, remove the header from the control area
|
||
if ((this.View == View.Details || this.ShowHeaderInAllViews) && this.HeaderControl != null) {
|
||
Rectangle hdrBounds = new Rectangle();
|
||
NativeMethods.GetClientRect(this.HeaderControl.Handle, ref hdrBounds);
|
||
r.Y = hdrBounds.Height;
|
||
r.Height = r.Height - hdrBounds.Height;
|
||
}
|
||
|
||
return r;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
///<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD><C3B5>û<EFBFBD><C3BB><EFBFBD>Ctrl+C<><43><EFBFBD>ϼ<EFBFBD>ʱ<EFBFBD>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6>ѡ<EFBFBD><D1A1><EFBFBD>и<EFBFBD><D0B8>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD><C3B5>û<EFBFBD><C3BB><EFBFBD>Ctrl+C<><43><EFBFBD>ϼ<EFBFBD>ʱ<EFBFBD>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6>ѡ<EFBFBD><D1A1><EFBFBD>и<EFBFBD><D0B8>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"),
|
||
DefaultValue(true)]
|
||
public virtual bool CopySelectionOnControlC {
|
||
get { return copySelectionOnControlC; }
|
||
set { copySelectionOnControlC = value; }
|
||
}
|
||
private bool copySelectionOnControlC = true;
|
||
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ð<EFBFBD>Ctrl+C<><43><EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>幦<EFBFBD><E5B9A6><EFBFBD>Ƿ<EFBFBD>Ӧʹ<D3A6>ð<EFBFBD>װ<EFBFBD><D7B0>DragSource<63><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD><C3B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD>ݶ<EFBFBD><DDB6><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>This is normally what is desired, unless a custom DragSource is installed
|
||
/// that does some very specialized drag-drop behaviour.</remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ð<EFBFBD>Ctrl + C<><43><EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>幦<EFBFBD><E5B9A6><EFBFBD>Ƿ<EFBFBD>Ӧʹ<D3A6>ð<EFBFBD>װ<EFBFBD><D7B0>DragSource<63><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD><C3B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD>ݶ<EFBFBD><DDB6><EFBFBD><EFBFBD><EFBFBD>"),
|
||
DefaultValue(true)]
|
||
public bool CopySelectionOnControlCUsesDragSource {
|
||
get { return this.copySelectionOnControlCUsesDragSource; }
|
||
set { this.copySelectionOnControlCUsesDragSource = value; }
|
||
}
|
||
private bool copySelectionOnControlCUsesDragSource = true;
|
||
|
||
/// <summary>
|
||
/// Gets the list of decorations that will be drawn the ListView
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// Do not modify the contents of this list directly. Use the AddDecoration() and RemoveDecoration() methods.
|
||
/// </para>
|
||
/// <para>
|
||
/// A decoration scrolls with the list contents. An overlay is fixed in place.
|
||
/// </para>
|
||
/// </remarks>
|
||
[Browsable(false)]
|
||
protected IList<IDecoration> Decorations {
|
||
get { return this.decorations; }
|
||
}
|
||
private readonly List<IDecoration> decorations = new List<IDecoration>();
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><DFBB><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ⱦ<EFBFBD><C8BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δָ<CEB4><D6B8><EFBFBD>ض<EFBFBD><D8B6><EFBFBD>Ⱦ<EFBFBD><C8BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD><D4BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ΪNULL<4C><4C><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD>ΪHighlightTextRenende</remarks>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public IRenderer DefaultRenderer {
|
||
get { return this.defaultRenderer; }
|
||
set { this.defaultRenderer = value ?? new HighlightTextRenderer(); }
|
||
}
|
||
private IRenderer defaultRenderer = new HighlightTextRenderer();
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD>ڻ<EFBFBD><DABB>Ƹ<EFBFBD><C6B8><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ⱦ<EFBFBD><C8BE><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <param name="model">The row model for the row</param>
|
||
/// <param name="column">The column to be drawn</param>
|
||
/// <returns>The renderer used for drawing a cell. Must not return null.</returns>
|
||
public IRenderer GetCellRenderer(object model, OLVColumn column) {
|
||
IRenderer renderer = this.CellRendererGetter == null ? null : this.CellRendererGetter(model, column);
|
||
return renderer ?? column.Renderer ?? this.DefaultRenderer;
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ý<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD>ڽ<EFBFBD><DABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD>
|
||
/// </summary>
|
||
/// <remarks>If this is not set explicitly, <see cref="ObjectListView.DefaultDisabledItemStyle"/> will be used.</remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ý<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD>ڽ<EFBFBD><DABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD>"),
|
||
DefaultValue(null)]
|
||
public SimpleItemStyle DisabledItemStyle
|
||
{
|
||
get { return disabledItemStyle; }
|
||
set { disabledItemStyle = value; }
|
||
}
|
||
private SimpleItemStyle disabledItemStyle;
|
||
|
||
/// <summary>
|
||
///<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѽ<EFBFBD><D1BD>õ<EFBFBD>ģ<EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><F2BCA4BB>ѽ<EFBFBD><D1BD>õĶ<C3B5><C4B6><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual IEnumerable DisabledObjects
|
||
{
|
||
get
|
||
{
|
||
return disabledObjects.Keys;
|
||
}
|
||
set
|
||
{
|
||
this.disabledObjects.Clear();
|
||
DisableObjects(value);
|
||
}
|
||
}
|
||
private readonly Hashtable disabledObjects = new Hashtable();
|
||
|
||
/// <summary>
|
||
/// <20>жϴ˸<CFB4><CBB8><EFBFBD>ģ<EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7>ѽ<EFBFBD><D1BD><EFBFBD>
|
||
/// </summary>
|
||
/// <param name="model"></param>
|
||
/// <returns></returns>
|
||
public bool IsDisabled(object model)
|
||
{
|
||
return model != null && this.disabledObjects.ContainsKey(model);
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD>ø<EFBFBD><C3B8><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD><F3A1A3BD>õĶ<C3B5><C4B6><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD>
|
||
/// </summary>
|
||
/// <param name="model">Must not be null</param>
|
||
public void DisableObject(object model) {
|
||
ArrayList list = new ArrayList();
|
||
list.Add(model);
|
||
this.DisableObjects(list);
|
||
}
|
||
|
||
/// <summary>
|
||
///<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>и<EFBFBD><D0B8><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD>
|
||
/// </summary>
|
||
/// <param name="models"></param>
|
||
public void DisableObjects(IEnumerable models)
|
||
{
|
||
if (models == null)
|
||
return;
|
||
ArrayList list = ObjectListView.EnumerableToArray(models, false);
|
||
foreach (object model in list)
|
||
{
|
||
if (model == null)
|
||
continue;
|
||
|
||
this.disabledObjects[model] = true;
|
||
int modelIndex = this.IndexOf(model);
|
||
if (modelIndex >= 0)
|
||
NativeMethods.DeselectOneItem(this, modelIndex);
|
||
}
|
||
this.RefreshObjects(list);
|
||
}
|
||
|
||
/// <summary>
|
||
///<2F><><EFBFBD>ø<EFBFBD><C3B8><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٴ<EFBFBD>ѡ<EFBFBD><EFBFBD><F1B2A2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <param name="model">Must not be null</param>
|
||
public void EnableObject(object model)
|
||
{
|
||
this.disabledObjects.Remove(model);
|
||
this.RefreshObject(model);
|
||
}
|
||
|
||
/// <summary>
|
||
///<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>и<EFBFBD><D0B8><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD>
|
||
/// </summary>
|
||
/// <param name="models"></param>
|
||
public void EnableObjects(IEnumerable models)
|
||
{
|
||
if (models == null)
|
||
return;
|
||
ArrayList list = ObjectListView.EnumerableToArray(models, false);
|
||
foreach (object model in list)
|
||
{
|
||
if (model != null)
|
||
this.disabledObjects.Remove(model);
|
||
}
|
||
this.RefreshObjects(list);
|
||
}
|
||
|
||
/// <summary>
|
||
///<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>н<EFBFBD><D0BD>õĶ<C3B5><C4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ⲻ<EFBFBD>ᴥ<EFBFBD><E1B4A5><EFBFBD>ػ<EFBFBD><D8BB><EFBFBD><EFBFBD>ؽ<EFBFBD>
|
||
/// </summary>
|
||
protected void ClearDisabledObjects()
|
||
{
|
||
this.disabledObjects.Clear();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the object that controls how drags start from this control
|
||
/// </summary>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public IDragSource DragSource {
|
||
get { return this.dragSource; }
|
||
set { this.dragSource = value; }
|
||
}
|
||
private IDragSource dragSource;
|
||
|
||
/// <summary>
|
||
/// Gets or sets the object that controls how drops are accepted and processed
|
||
/// by this ListView.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// If the given sink is an instance of SimpleDropSink, then events from the drop sink
|
||
/// will be automatically forwarded to the ObjectListView (which means that handlers
|
||
/// for those event can be configured within the IDE).
|
||
/// </para>
|
||
/// <para>If this is set to null, the control will not accept drops.</para>
|
||
/// </remarks>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public IDropSink DropSink {
|
||
get { return this.dropSink; }
|
||
set {
|
||
if (this.dropSink == value)
|
||
return;
|
||
|
||
// Stop listening for events on the old sink
|
||
SimpleDropSink oldSink = this.dropSink as SimpleDropSink;
|
||
if (oldSink != null) {
|
||
oldSink.CanDrop -= new EventHandler<OlvDropEventArgs>(this.DropSinkCanDrop);
|
||
oldSink.Dropped -= new EventHandler<OlvDropEventArgs>(this.DropSinkDropped);
|
||
oldSink.ModelCanDrop -= new EventHandler<ModelDropEventArgs>(this.DropSinkModelCanDrop);
|
||
oldSink.ModelDropped -= new EventHandler<ModelDropEventArgs>(this.DropSinkModelDropped);
|
||
}
|
||
|
||
this.dropSink = value;
|
||
this.AllowDrop = (value != null);
|
||
if (this.dropSink != null)
|
||
this.dropSink.ListView = this;
|
||
|
||
// Start listening for events on the new sink
|
||
SimpleDropSink newSink = value as SimpleDropSink;
|
||
if (newSink != null) {
|
||
newSink.CanDrop += new EventHandler<OlvDropEventArgs>(this.DropSinkCanDrop);
|
||
newSink.Dropped += new EventHandler<OlvDropEventArgs>(this.DropSinkDropped);
|
||
newSink.ModelCanDrop += new EventHandler<ModelDropEventArgs>(this.DropSinkModelCanDrop);
|
||
newSink.ModelDropped += new EventHandler<ModelDropEventArgs>(this.DropSinkModelDropped);
|
||
}
|
||
}
|
||
}
|
||
private IDropSink dropSink;
|
||
|
||
// Forward events from the drop sink to the control itself
|
||
void DropSinkCanDrop(object sender, OlvDropEventArgs e) { this.OnCanDrop(e); }
|
||
void DropSinkDropped(object sender, OlvDropEventArgs e) { this.OnDropped(e); }
|
||
void DropSinkModelCanDrop(object sender, ModelDropEventArgs e) { this.OnModelCanDrop(e); }
|
||
void DropSinkModelDropped(object sender, ModelDropEventArgs e) { this.OnModelDropped(e); }
|
||
|
||
/// <summary>
|
||
/// This registry decides what control should be used to edit what cells, based
|
||
/// on the type of the value in the cell.
|
||
/// </summary>
|
||
/// <see cref="EditorRegistry"/>
|
||
/// <remarks>All instances of ObjectListView share the same editor registry.</remarks>
|
||
// ReSharper disable FieldCanBeMadeReadOnly.Global
|
||
static public EditorRegistry EditorRegistry = new EditorRegistry();
|
||
// ReSharper restore FieldCanBeMadeReadOnly.Global
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD><CDBC>û<EFBFBD><C3BB><EFBFBD><EFBFBD>ʱӦ<CAB1><D3A6>ʾ<EFBFBD><CABE><EFBFBD>ı<EFBFBD><C4B1><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>If the EmptyListMsgOverlay has been changed to something other than a TextOverlay,
|
||
/// this property does nothing</remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22><><EFBFBD>б<EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>ڿؼ<DABF><D8BC><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD>Ϣ"),
|
||
DefaultValue(null),
|
||
Localizable(true)]
|
||
public virtual String EmptyListMsg {
|
||
get {
|
||
TextOverlay overlay = this.EmptyListMsgOverlay as TextOverlay;
|
||
return overlay == null ? null : overlay.Text;
|
||
}
|
||
set {
|
||
TextOverlay overlay = this.EmptyListMsgOverlay as TextOverlay;
|
||
if (overlay != null) {
|
||
overlay.Text = value;
|
||
this.Invalidate();
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD>ϢʱӦʹ<D3A6>õ<EFBFBD><C3B5><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>If the EmptyListMsgOverlay has been changed to something other than a TextOverlay,
|
||
/// this property does nothing</remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD>ϢʱӦʹ<D3A6>õ<EFBFBD><C3B5><EFBFBD><EFBFBD><EFBFBD>"),
|
||
DefaultValue(null)]
|
||
public virtual Font EmptyListMsgFont {
|
||
get {
|
||
TextOverlay overlay = this.EmptyListMsgOverlay as TextOverlay;
|
||
return overlay == null ? null : overlay.Font;
|
||
}
|
||
set {
|
||
TextOverlay overlay = this.EmptyListMsgOverlay as TextOverlay;
|
||
if (overlay != null)
|
||
overlay.Font = value;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD>ء<EFBFBD><D8A1>б<EFBFBD>Ϊ<EFBFBD>ա<EFBFBD><D5A1><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><C4AC>ֵ
|
||
/// </summary>
|
||
[Browsable(false)]
|
||
public virtual Font EmptyListMsgFontOrDefault {
|
||
get {
|
||
return this.EmptyListMsgFont ?? new Font("Tahoma", 14);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets the overlay responsible for drawing the List Empty msg.
|
||
/// </summary>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual IOverlay EmptyListMsgOverlay {
|
||
get { return this.emptyListMsgOverlay; }
|
||
set {
|
||
if (this.emptyListMsgOverlay != value) {
|
||
this.emptyListMsgOverlay = value;
|
||
this.Invalidate();
|
||
}
|
||
}
|
||
}
|
||
private IOverlay emptyListMsgOverlay;
|
||
|
||
/// <summary>
|
||
///<2F><>ȡ<EFBFBD><C8A1>ɸѡ<C9B8><D1A1><EFBFBD>Ҵ<EFBFBD><D2B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC>ϡ<EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// This collection is the result of filtering the current list of objects.
|
||
/// It is not a snapshot of the filtered list that was last used to build the control.
|
||
/// </para>
|
||
/// <para>
|
||
/// Normal warnings apply when using this with virtual lists. It will work, but it
|
||
/// may take a while.
|
||
/// </para>
|
||
/// </remarks>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
virtual public IEnumerable FilteredObjects {
|
||
get {
|
||
if (this.UseFiltering)
|
||
return this.FilterObjects(this.Objects, this.ModelFilter, this.ListFilter);
|
||
|
||
return this.Objects;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ý<EFBFBD><C3BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɸѡ<C9B8><D1A1><EFBFBD>˵<EFBFBD><CBB5>IJ<EFBFBD><C4B2>Զ<EFBFBD><D4B6><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks><3E><><EFBFBD><EFBFBD>ΪNULL<4C><4C><EFBFBD><EFBFBD><F2B2BBBB><EFBFBD><EFBFBD><EFBFBD>ɸѡ<C9B8><D1A1><EFBFBD>˵<EFBFBD><CBB5><EFBFBD></remarks>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public FilterMenuBuilder FilterMenuBuildStrategy {
|
||
get { return filterMenuBuilder; }
|
||
set { filterMenuBuilder = value; }
|
||
}
|
||
private FilterMenuBuilder filterMenuBuilder = new FilterMenuBuilder();
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>þ<EFBFBD><C3BE>м<EFBFBD><D0BC>̽<EFBFBD><CCBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// Setting an object to be focused does *not* select it. If you want to select and focus a row,
|
||
/// use <see cref="SelectedObject"/>.
|
||
/// </para>
|
||
/// <para>
|
||
/// This property is not generally used and is only useful in specialized situations.
|
||
/// </para>
|
||
/// </remarks>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual Object FocusedObject {
|
||
get { return this.FocusedItem == null ? null : ((OLVListItem)this.FocusedItem).RowObject; }
|
||
set {
|
||
OLVListItem item = this.ModelToItem(value);
|
||
if (item != null)
|
||
item.Focused = true;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD>Groups<70><73><EFBFBD>ϣ<EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD>ڡ<EFBFBD><DAA1><EFBFBD><EFBFBD>ԡ<EFBFBD><D4A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>в<EFBFBD><D0B2>ɼ<EFBFBD><C9BC><EFBFBD>
|
||
/// </summary>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
new public ListViewGroupCollection Groups {
|
||
get { return base.Groups; }
|
||
}
|
||
|
||
/// <summary>
|
||
///<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>÷<EFBFBD><C3B7><EFBFBD>ʹ<EFBFBD>õ<EFBFBD>ImageList
|
||
/// </summary>
|
||
/// <remarks><3E><><EFBFBD><EFBFBD>δ<EFBFBD><CEB4><EFBFBD>ô<EFBFBD>ѡ<EFBFBD><EFBFBD><EEA3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>⽫<EFBFBD><E2BDAB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD>κ<EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD></remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>÷<EFBFBD><C3B7><EFBFBD>ʹ<EFBFBD>õ<EFBFBD>ImageList"),
|
||
DefaultValue(null)]
|
||
public ImageList GroupImageList {
|
||
get { return this.groupImageList; }
|
||
set {
|
||
this.groupImageList = value;
|
||
if (this.Created) {
|
||
NativeMethods.SetGroupImageList(this, value);
|
||
}
|
||
}
|
||
}
|
||
private ImageList groupImageList;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>Ϊ<EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĿʱӦ<CAB1><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǩ<EFBFBD>ĸ<EFBFBD>ʽ
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD>ʽ<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռλ<D5BC><CEBB><EFBFBD><EFBFBD>
|
||
/// <list type="bullet">
|
||
/// <item><description>{0} - ԭ<><D4AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></description></item>
|
||
/// <item><description>{1} - <20><><EFBFBD>е<EFBFBD><D0B5><EFBFBD>Ŀ<EFBFBD><C4BF></description></item>
|
||
/// </list>
|
||
/// </remarks>
|
||
/// <example>"[{0} [{1} <20><>]"</example>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>Ϊ<EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĿʱӦ<CAB1><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǩ<EFBFBD>ĸ<EFBFBD>ʽ"),
|
||
DefaultValue(null),
|
||
Localizable(true)]
|
||
public virtual string GroupWithItemCountFormat {
|
||
get { return groupWithItemCountFormat; }
|
||
set { groupWithItemCountFormat = value; }
|
||
}
|
||
private string groupWithItemCountFormat;
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD>this.GroupWithItemCountFormat<61><74><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><C4AC>ֵ
|
||
/// </summary>
|
||
[Browsable(false)]
|
||
public virtual string GroupWithItemCountFormatOrDefault {
|
||
get {
|
||
return String.IsNullOrEmpty(this.GroupWithItemCountFormat) ? "{0} [{1} <20><>]" : this.GroupWithItemCountFormat;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĿʱӦ<CAB1><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǩ<EFBFBD>ĸ<EFBFBD>ʽ
|
||
/// </summary>
|
||
/// <remarks>
|
||
///<2F><><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD>ʽ<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռλ<D5BC><CEBB><EFBFBD><EFBFBD>
|
||
/// <list type="bullet">
|
||
/// <item><description>{0} - ԭ<><D4AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></description></item>
|
||
/// <item><description>{1} - <20><><EFBFBD>е<EFBFBD><D0B5><EFBFBD>Ŀ<EFBFBD><C4BF> (<28><><EFBFBD><EFBFBD>1)</description></item>
|
||
/// </list>
|
||
/// </remarks>
|
||
/// <example>"[{0} [{1} <20><>]"</example>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĿʱӦ<CAB1><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǩ<EFBFBD>ĸ<EFBFBD>ʽ"),
|
||
DefaultValue(null),
|
||
Localizable(true)]
|
||
public virtual string GroupWithItemCountSingularFormat {
|
||
get { return groupWithItemCountSingularFormat; }
|
||
set { groupWithItemCountSingularFormat = value; }
|
||
}
|
||
private string groupWithItemCountSingularFormat;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡGroupWithItemCountSingularFormat<61><74><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><C4AC>ֵ
|
||
/// </summary>
|
||
[Browsable(false)]
|
||
public virtual string GroupWithItemCountSingularFormatOrDefault {
|
||
get {
|
||
return String.IsNullOrEmpty(this.GroupWithItemCountSingularFormat) ? "{0} [{1} <20><>]" : this.GroupWithItemCountSingularFormat;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
///<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD>ObjectListView<65>е<EFBFBD><D0B5><EFBFBD><EFBFBD>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD>۵<EFBFBD><DBB5><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ֧<D6BB><D6A7>Vista<74><61>֮<EFBFBD><D6AE><EFBFBD><EFBFBD>ϵͳ.
|
||
/// </remarks>
|
||
[Browsable(true),
|
||
Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD>ObjectListView<65>е<EFBFBD><D0B5><EFBFBD><EFBFBD>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD>۵<EFBFBD> (Vista<74><61>֮<EFBFBD><D6AE><EFBFBD><EFBFBD>ϵͳ<CFB5><CDB3>֧<EFBFBD><D6A7>)."),
|
||
DefaultValue(true)]
|
||
public bool HasCollapsibleGroups {
|
||
get { return hasCollapsibleGroups; }
|
||
set { hasCollapsibleGroups = value; }
|
||
}
|
||
private bool hasCollapsibleGroups = true;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1>ǰ<EFBFBD>б<EFBFBD><D0B1>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5>б<EFBFBD>Ϊ<EFBFBD><CEAA>ʱ<EFBFBD><CAB1>ʾ<EFBFBD><CABE><EFBFBD>ı<EFBFBD>
|
||
/// </summary>
|
||
[Browsable(false)]
|
||
public virtual bool HasEmptyListMsg {
|
||
get { return !String.IsNullOrEmpty(this.EmptyListMsg); }
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>Ƶĵ<C6B5><C4B5>Ӳ<EFBFBD>
|
||
/// </summary>
|
||
[Browsable(false)]
|
||
public bool HasOverlays {
|
||
get {
|
||
return (this.Overlays.Count > 2 ||
|
||
this.imageOverlay.Image != null ||
|
||
!String.IsNullOrEmpty(this.textOverlay.Text));
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><>ȡListView<65><77><EFBFBD><EFBFBD>ͷ<EFBFBD>ؼ<EFBFBD>
|
||
/// </summary>
|
||
[Browsable(false)]
|
||
public HeaderControl HeaderControl {
|
||
get { return this.headerControl ?? (this.headerControl = new HeaderControl(this)); }
|
||
}
|
||
private HeaderControl headerControl;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD>ı<EFBFBD><C4B1>Ļ<EFBFBD><C4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks><3E><><EFBFBD><EFBFBD><EFBFBD>п<EFBFBD><D0BF><EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD>HeaderFormatStyle<6C><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD>á<EFBFBD></remarks>
|
||
[DefaultValue(null)]
|
||
[Browsable(false)]
|
||
[Obsolete("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>HeaderFormatStyle", false)]
|
||
public Font HeaderFont {
|
||
get { return this.HeaderFormatStyle == null ? null : this.HeaderFormatStyle.Normal.Font; }
|
||
set {
|
||
if (value == null && this.HeaderFormatStyle == null)
|
||
return;
|
||
|
||
if (this.HeaderFormatStyle == null)
|
||
this.HeaderFormatStyle = new HeaderFormatStyle();
|
||
|
||
this.HeaderFormatStyle.SetFont(value);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ý<EFBFBD><C3BD><EFBFBD><EFBFBD>ڻ<EFBFBD><DABB><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// <20><><EFBFBD><EFBFBD>HeaderUsesThemesΪfalseʱ<65><CAB1>ʹ<EFBFBD>ô<EFBFBD>ѡ<EFBFBD>
|
||
/// </para>
|
||
/// <para>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD>п<EFBFBD><D0BF><EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD>HeaderFormatStyle<6C><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD>á<EFBFBD>
|
||
/// </para>
|
||
/// </remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ý<EFBFBD><C3BD><EFBFBD><EFBFBD>ڻ<EFBFBD><DABB><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ"),
|
||
DefaultValue(null)]
|
||
public HeaderFormatStyle HeaderFormatStyle {
|
||
get { return this.headerFormatStyle; }
|
||
set { this.headerFormatStyle = value; }
|
||
}
|
||
private HeaderFormatStyle headerFormatStyle;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ñ<EFBFBD><C3B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶ȡ<DFB6>-1<><31>ʾû<CABE><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5>
|
||
/// </summary>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ñ<EFBFBD><C3B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶ȡ<DFB6>-1<><31>ʾû<CABE><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5>"),
|
||
DefaultValue(-1)]
|
||
public int HeaderMaximumHeight
|
||
{
|
||
get { return headerMaximumHeight; }
|
||
set { headerMaximumHeight = value; }
|
||
}
|
||
private int headerMaximumHeight = -1;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ñ<EFBFBD><C3B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>߶ȡ<DFB6>-1<><31>ʾû<CABE><C3BB><EFBFBD><EFBFBD>Сֵ<D0A1><D6B5>
|
||
/// </summary>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ñ<EFBFBD><C3B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>߶ȡ<DFB6>-1<><31>ʾû<CABE><C3BB><EFBFBD><EFBFBD>Сֵ<D0A1><D6B5>"),
|
||
DefaultValue(-1)]
|
||
public int HeaderMinimumHeight
|
||
{
|
||
get { return headerMinimumHeight; }
|
||
set { headerMinimumHeight = value; }
|
||
}
|
||
private int headerMinimumHeight = -1;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7>ϸ<EFBFBD><CFB8><EFBFBD><EFBFBD>ղ<EFBFBD><D5B2><EFBFBD>ϵͳ<CFB5><CDB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʊ<EFBFBD><C6B1>⡣
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
///<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊtrue<75><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD>ȫ<EFBFBD><C8AB>ϵͳ<CFB5><CDB3><EFBFBD>֣<EFBFBD><D6A3><EFBFBD><EFBFBD><EFBFBD>ҪObjectListViews<77><73><EFBFBD>κ<EFBFBD><CEBA><EFBFBD><EFBFBD><EFBFBD><E2B4A6><EFBFBD><EFBFBD>
|
||
///ҳü<D2B3>н<EFBFBD>û<EFBFBD><C3BB>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD>û<EFBFBD>й<EFBFBD><D0B9><EFBFBD><EFBFBD><EFBFBD>ָʾ<D6B8><CABE><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><D6BB>С<EFBFBD>û<EFBFBD><C3BB>ҳü<D2B3><C3BC>ʽ<EFBFBD><CABD>û<EFBFBD>и<EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD>
|
||
/// </para>
|
||
/// <para><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ΪFalse<73><65>ObjectListView<65><77><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD>õķ<C3B5>ʽ<EFBFBD><CABD><EFBFBD>ֱ<EFBFBD><D6B1>⡣
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>ܣ<EFBFBD><DCA3><EFBFBD>ObjectListView<65>Ὣ<EFBFBD><E1BDAB>Ⱦί<C8BE>и<EFBFBD><D0B8><EFBFBD><EFBFBD><EFBFBD>ϵͳ<CFB5><CDB3>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ObjectListView<65><77><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB>Ʊ<EFBFBD><C6B1>⡣
|
||
/// </para>
|
||
/// <para>
|
||
/// û<><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<CFB5><CDB3>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD><EFBFBD>٣<EFBFBD><D9A3><EFBFBD><EFBFBD><EFBFBD>ָʾ<D6B8><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>DZ<EFBFBD><EFBFBD>ġ<EFBFBD>
|
||
/// </para>
|
||
/// </remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7>ϸ<EFBFBD><CFB8><EFBFBD><EFBFBD>ղ<EFBFBD><D5B2><EFBFBD>ϵͳ<CFB5><CDB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʊ<EFBFBD><C6B1><EFBFBD>"),
|
||
DefaultValue(false)]
|
||
public bool HeaderUsesThemes {
|
||
get { return this.headerUsesThemes; }
|
||
set { this.headerUsesThemes = value; }
|
||
}
|
||
private bool headerUsesThemes;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><D0B5>ı<EFBFBD><C4B1>Ƿ<EFBFBD><C7B7>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD>С<EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para><3E><><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD>֮<EFBFBD><D6AE>Ӧ<EFBFBD>û<EFBFBD><C3BB>з<EFBFBD><D0B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD><EFBFBD>Խ<EFBFBD><D4BD><EFBFBD>ʡ<EFBFBD>ԡ<EFBFBD></para>
|
||
/// <para>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>HeaderUsesThemes<65><73><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊfalse<73><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<CFB5><CDB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><C4B1><EFBFBD>
|
||
/// </para>
|
||
/// </remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><D0B5>ı<EFBFBD><C4B1>Ƿ<EFBFBD><C7B7>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD>"),
|
||
DefaultValue(false)]
|
||
public bool HeaderWordWrap {
|
||
get { return this.headerWordWrap; }
|
||
set {
|
||
this.headerWordWrap = value;
|
||
if (this.headerControl != null)
|
||
this.headerControl.WordWrap = value;
|
||
}
|
||
}
|
||
private bool headerWordWrap;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1>ʾ<EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD>Ĺ<EFBFBD><C4B9><EFBFBD><EFBFBD><EFBFBD>ʾ
|
||
/// </summary>
|
||
[Browsable(false)]
|
||
public ToolTipControl HeaderToolTip {
|
||
get {
|
||
return this.HeaderControl.ToolTip;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
///<2F><>ȡ<EFBFBD><C8A1><EFBFBD>굱ǰ<EAB5B1><C7B0><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual int HotRowIndex {
|
||
get { return this.hotRowIndex; }
|
||
protected set { this.hotRowIndex = value; }
|
||
}
|
||
private int hotRowIndex;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD>굱ǰ<EAB5B1><C7B0><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual int HotColumnIndex {
|
||
get { return this.hotColumnIndex; }
|
||
protected set { this.hotColumnIndex = value; }
|
||
}
|
||
private int hotColumnIndex;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD>굱ǰ<EAB5B1><C7B0><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual HitTestLocation HotCellHitLocation {
|
||
get { return this.hotCellHitLocation; }
|
||
protected set { this.hotCellHitLocation = value; }
|
||
}
|
||
private HitTestLocation hotCellHitLocation;
|
||
|
||
/// <summary>
|
||
/// Gets an extended indication of the part of item/subitem/group that the mouse is currently over
|
||
/// </summary>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual HitTestLocationEx HotCellHitLocationEx
|
||
{
|
||
get { return this.hotCellHitLocationEx; }
|
||
protected set { this.hotCellHitLocationEx = value; }
|
||
}
|
||
private HitTestLocationEx hotCellHitLocationEx;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5>顣
|
||
/// </summary>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public OLVGroup HotGroup
|
||
{
|
||
get { return hotGroup; }
|
||
internal set { hotGroup = value; }
|
||
}
|
||
private OLVGroup hotGroup;
|
||
|
||
/// <summary>
|
||
///<2F><><EFBFBD>ڡ<EFBFBD><DAA1>ȡ<EFBFBD>״̬<D7B4><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڹ<EFBFBD><DAB9><EFBFBD><EFBFBD>·<EFBFBD><C2B7><EFBFBD>-1<><31>ʾû<CABE><C3BB><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF>
|
||
/// </summary>
|
||
[Browsable(false),
|
||
Obsolete("<22><>ʹ<EFBFBD><CAB9> HotRowIndex <20><><EFBFBD><EFBFBD>", false)]
|
||
public virtual int HotItemIndex {
|
||
get { return this.HotRowIndex; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ö<EFBFBD><C3B6>α<EFBFBD><CEB1>µ<EFBFBD><C2B5><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD>ʽ
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
///<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>UseHotItemΪtrueʱ<65><CAB1>Ч<EFBFBD><D0A7>
|
||
/// </para>
|
||
/// <para><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD>е<EFBFBD><D0B5>Ӳ㣬<D3B2><E3A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>á<EFBFBD>*֮ǰ* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԡ<EFBFBD>֮<EFBFBD><D6AE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԡ<EFBFBD> </para>
|
||
/// </remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ö<EFBFBD><C3B6>α<EFBFBD><CEB1>µ<EFBFBD><C2B5><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD>ʽ"),
|
||
DefaultValue(null)]
|
||
public virtual HotItemStyle HotItemStyle {
|
||
get { return this.hotItemStyle; }
|
||
set {
|
||
if (this.HotItemStyle != null)
|
||
this.RemoveOverlay(this.HotItemStyle.Overlay);
|
||
this.hotItemStyle = value;
|
||
if (this.HotItemStyle != null)
|
||
this.AddOverlay(this.HotItemStyle.Overlay);
|
||
}
|
||
}
|
||
private HotItemStyle hotItemStyle;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD>Ѱ<EFBFBD>װ<EFBFBD><D7B0><EFBFBD>ȵ<EFBFBD><C8B5><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><C4AC>ֵ<EFBFBD><D6B5>
|
||
/// </summary>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual HotItemStyle HotItemStyleOrDefault {
|
||
get { return this.HotItemStyle ?? ObjectListView.DefaultHotItemStyle; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD>ʽӦ<CABD><D3A6><EFBFBD>ڳ<EFBFBD><DAB3><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD>ʽӦ<CABD><D3A6><EFBFBD>ڳ<EFBFBD><DAB3><EFBFBD><EFBFBD><EFBFBD>"),
|
||
DefaultValue(null)]
|
||
public virtual HyperlinkStyle HyperlinkStyle {
|
||
get { return this.hyperlinkStyle; }
|
||
set { this.hyperlinkStyle = value; }
|
||
}
|
||
private HyperlinkStyle hyperlinkStyle;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD>еı<D0B5><C4B1><EFBFBD>Ӧ<EFBFBD><D3A6>ʹ<EFBFBD><CAB9>ʲô<CAB2><C3B4>ɫ
|
||
/// </summary>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD>еı<D0B5><C4B1><EFBFBD>Ӧ<EFBFBD><D3A6>ʹ<EFBFBD><CAB9>ʲô<CAB2><C3B4>ɫ"),
|
||
DefaultValue(typeof(Color), "")]
|
||
public virtual Color SelectedBackColor {
|
||
get { return this.selectedBackColor; }
|
||
set { this.selectedBackColor = value; }
|
||
}
|
||
private Color selectedBackColor = Color.Empty;
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD>еı<D0B5><C4B1><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><C4AC>ֵ
|
||
/// </summary>
|
||
[Browsable(false)]
|
||
public virtual Color SelectedBackColorOrDefault {
|
||
get {
|
||
return this.SelectedBackColor.IsEmpty ? SystemColors.Highlight : this.SelectedBackColor;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6>ʹ<EFBFBD><CAB9>ʲô<CAB2><C3B4>ɫ
|
||
/// </summary>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6>ʹ<EFBFBD><CAB9>ʲô<CAB2><C3B4>ɫ"),
|
||
DefaultValue(typeof(Color), "")]
|
||
public virtual Color SelectedForeColor {
|
||
get { return this.selectedForeColor; }
|
||
set { this.selectedForeColor = value; }
|
||
}
|
||
private Color selectedForeColor = Color.Empty;
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><C4AC>ֵ
|
||
/// </summary>
|
||
[Browsable(false)]
|
||
public virtual Color SelectedForeColorOrDefault {
|
||
get {
|
||
return this.SelectedForeColor.IsEmpty ? SystemColors.HighlightText : this.SelectedForeColor;
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// ʹ<><CAB9> SelectedBackColor <20><><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
[Obsolete("ʹ<><CAB9> SelectedBackColor <20><><EFBFBD><EFBFBD>")]
|
||
public virtual Color HighlightBackgroundColor { get { return this.SelectedBackColor; } set { this.SelectedBackColor = value; } }
|
||
/// <summary>
|
||
/// ʹ<><CAB9> SelectedBackColorOrDefault <20><><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
[Obsolete("ʹ<><CAB9> SelectedBackColorOrDefault <20><><EFBFBD><EFBFBD>")]
|
||
public virtual Color HighlightBackgroundColorOrDefault { get { return this.SelectedBackColorOrDefault; } }
|
||
/// <summary>
|
||
/// ʹ<><CAB9> SelectedForeColor <20><><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
[Obsolete("ʹ<><CAB9> SelectedForeColor <20><><EFBFBD><EFBFBD>")]
|
||
public virtual Color HighlightForegroundColor { get { return this.SelectedForeColor; } set { this.SelectedForeColor = value; } }
|
||
/// <summary>
|
||
/// ʹ<><CAB9> SelectedForeColorOrDefault <20><><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
[Obsolete("ʹ<><CAB9> SelectedForeColorOrDefault <20><><EFBFBD><EFBFBD>")]
|
||
public virtual Color HighlightForegroundColorOrDefault { get { return this.SelectedForeColorOrDefault; } }
|
||
/// <summary>
|
||
/// ʹ<><CAB9> UnfocusedSelectedBackColor <20><><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
[Obsolete("ʹ<><CAB9> UnfocusedSelectedBackColor <20><><EFBFBD><EFBFBD>")]
|
||
public virtual Color UnfocusedHighlightBackgroundColor { get { return this.UnfocusedSelectedBackColor; } set { this.UnfocusedSelectedBackColor = value; } }
|
||
/// <summary>
|
||
/// ʹ<><CAB9> UnfocusedSelectedBackColorOrDefault <20><><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
[Obsolete("ʹ<><CAB9> UnfocusedSelectedBackColorOrDefault <20><><EFBFBD><EFBFBD>")]
|
||
public virtual Color UnfocusedHighlightBackgroundColorOrDefault { get { return this.UnfocusedSelectedBackColorOrDefault; } }
|
||
/// <summary>
|
||
/// ʹ<><CAB9> UnfocusedSelectedForeColor <20><><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
[Obsolete("ʹ<><CAB9> UnfocusedSelectedForeColor <20><><EFBFBD><EFBFBD>")]
|
||
public virtual Color UnfocusedHighlightForegroundColor { get { return this.UnfocusedSelectedForeColor; } set { this.UnfocusedSelectedForeColor = value; } }
|
||
/// <summary>
|
||
/// ʹ<><CAB9> UnfocusedSelectedForeColorOrDefault <20><><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
[Obsolete("ʹ<><CAB9> UnfocusedSelectedForeColorOrDefault <20><><EFBFBD><EFBFBD>")]
|
||
public virtual Color UnfocusedHighlightForegroundColorOrDefault { get { return this.UnfocusedSelectedForeColorOrDefault; } }
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>а<EFBFBD><D0B0><EFBFBD><EFBFBD>ڸ<EFBFBD><DAB8>ƻ<EFBFBD><C6BB>϶<EFBFBD><CFB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD>ó<EFBFBD><C3B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><D0B5>ı<EFBFBD><C4B1><EFBFBD>ʾ<EFBFBD><CABE>ʽ<EFBFBD>С<EFBFBD>
|
||
/// <20><><EFBFBD><EFBFBD>ΪFalse(Ĭ<><C4AC>ֵ)<29><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɼ<EFBFBD><C9BC>С<EFBFBD>
|
||
/// </summary>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>а<EFBFBD><D0B0><EFBFBD><EFBFBD>ڸ<EFBFBD><DAB8>ƻ<EFBFBD><C6BB>϶<EFBFBD><CFB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD>ó<EFBFBD><C3B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><D0B5>ı<EFBFBD><C4B1><EFBFBD>ʾ<EFBFBD><CABE>ʽ<EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD><EFBFBD>ΪFalse(Ĭ<><C4AC>ֵ)<29><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɼ<EFBFBD><C9BC>С<EFBFBD>"),
|
||
DefaultValue(false)]
|
||
public virtual bool IncludeHiddenColumnsInDataTransfer {
|
||
get { return includeHiddenColumnsInDataTransfer; }
|
||
set { includeHiddenColumnsInDataTransfer = value; }
|
||
}
|
||
private bool includeHiddenColumnsInDataTransfer;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ø<EFBFBD><C3B8><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>ı<EFBFBD><C4B1>С<EFBFBD>
|
||
/// <20><><EFBFBD><EFBFBD>ΪFalse(Ĭ<><C4AC>ֵ)<29><><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><C4B1>н<EFBFBD><D0BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD>б<EFBFBD><D0B1>⡣
|
||
/// </summary>
|
||
[Category("ObjectListView"),
|
||
Description("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>ı<EFBFBD><C4B1><EFBFBD>."),
|
||
DefaultValue(false)]
|
||
public virtual bool IncludeColumnHeadersInCopy
|
||
{
|
||
get { return includeColumnHeadersInCopy; }
|
||
set { includeColumnHeadersInCopy = value; }
|
||
}
|
||
private bool includeColumnHeadersInCopy;
|
||
|
||
/// <summary>
|
||
///<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD>ڽ<EFBFBD><DABD>е<EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD>༭<EFBFBD><E0BCAD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>TRUE
|
||
/// </summary>
|
||
[Browsable(false)]
|
||
public virtual bool IsCellEditing {
|
||
get { return this.cellEditor != null; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD>ڿ<EFBFBD><DABF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9>ObjectListView<65><77><EFBFBD><EFBFBD>true<75><65>
|
||
/// </summary>
|
||
[Browsable(false)]
|
||
public virtual bool IsDesignMode {
|
||
get { return this.DesignMode; }
|
||
}
|
||
|
||
/// <summary>
|
||
///<2F><>ȡ<EFBFBD><C8A1>ǰ<EFBFBD>б<EFBFBD><D0B1>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>ɸѡ<C9B8><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
virtual public bool IsFiltering {
|
||
get { return this.UseFiltering && (this.ModelFilter != null || this.ListFilter != null); }
|
||
}
|
||
|
||
/// <summary>
|
||
///<2F><><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD>б<EFBFBD><D0B1>м<EFBFBD><D0BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>ֵ<EFBFBD>Բ<EFBFBD><D4B2><EFBFBD>ƥ<EFBFBD><C6A5><EFBFBD>
|
||
///<2F><><EFBFBD><EFBFBD>ΪFalse<73><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʲô<CAB2><C3B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>When this is true, the behavior is like that of ITunes.</remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22><><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD>б<EFBFBD><D0B1>м<EFBFBD><D0BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>ֵ<EFBFBD>Բ<EFBFBD><D4B2><EFBFBD>ƥ<EFBFBD><C6A5><EFBFBD><EFBFBD><EEA3BF><EFBFBD><EFBFBD>ΪFalse<73><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʲô<CAB2><C3B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>"),
|
||
DefaultValue(true)]
|
||
public virtual bool IsSearchOnSortColumn {
|
||
get { return isSearchOnSortColumn; }
|
||
set { isSearchOnSortColumn = value; }
|
||
}
|
||
private bool isSearchOnSortColumn = true;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ô˿ؼ<CBBF><D8BC>Ƿ<EFBFBD><C7B7><EFBFBD>ʹ<EFBFBD><CAB9>SimpleDropSink<6E><6B><EFBFBD><EFBFBD><EFBFBD>϶<EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD>ý<EFBFBD><C3BD>滻<EFBFBD>κ<EFBFBD><CEBA><EFBFBD>ǰ<EFBFBD><C7B0>DropSink<6E><6B>
|
||
/// </para>
|
||
/// <para>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊtrue<75><65><EFBFBD><EFBFBD>SimpleDropSink<6E><6B><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>Ϊ˵<CEAA><CBB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>Խ<EFBFBD><D4BD><EFBFBD><EFBFBD>϶<EFBFBD><CFB6><EFBFBD>
|
||
/// <20>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD>϶<EFBFBD>ijЩ<C4B3><D0A9><EFBFBD><EFBFBD>ʱӦ<CAB1><D3A6>ִ<EFBFBD><D6B4>ʲô<CAB2><C3B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫִ<D2AA><D6B4><EFBFBD><EFBFBD>Щ<EFBFBD><D0A9><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD> :(
|
||
/// </para>
|
||
/// </remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ô˿ؼ<CBBF><D8BC>Ƿ<EFBFBD><C7B7><EFBFBD>ʹ<EFBFBD><CAB9>SimpleDropSink<6E><6B><EFBFBD><EFBFBD><EFBFBD>϶<EFBFBD>"),
|
||
DefaultValue(false)]
|
||
public virtual bool IsSimpleDropSink {
|
||
get { return this.DropSink != null; }
|
||
set {
|
||
this.DropSink = value ? new SimpleDropSink() : null;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ô˿ؼ<CBBF><D8BC>Ƿ<EFBFBD><C7B7><EFBFBD>ʹ<EFBFBD><CAB9>SimpleDragSource<63><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>϶<EFBFBD>
|
||
/// </summary>
|
||
/// <remarks><3E><><EFBFBD><EFBFBD><EFBFBD>ý<EFBFBD><C3BD>滻֮ǰ<D6AE><C7B0><EFBFBD>κ<EFBFBD>DragSource</remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ô˿ؼ<CBBF><D8BC>Ƿ<EFBFBD><C7B7><EFBFBD>ʹ<EFBFBD><CAB9>SimpleDragSource<63><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>϶<EFBFBD>"),
|
||
DefaultValue(false)]
|
||
public virtual bool IsSimpleDragSource {
|
||
get { return this.DragSource != null; }
|
||
set {
|
||
this.DragSource = value ? new SimpleDragSource() : null;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD>Items<6D><73><EFBFBD>ϣ<EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD>ڡ<EFBFBD><DAA1><EFBFBD><EFBFBD>ԡ<EFBFBD><D4A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>в<EFBFBD><D0B2>ɼ<EFBFBD><C9BC><EFBFBD>
|
||
/// </summary>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
new public ListViewItemCollection Items {
|
||
get { return base.Items; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD>б<EFBFBD><D0B1>е<EFBFBD><D0B5><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD>ڷ<EFBFBD><DAB7><EFBFBD>ϸ<EFBFBD><CFB8>ͼ<EFBFBD><CDBC>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ⱦ<EFBFBD><C8BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD><CFB8>Ϣ<EFBFBD><CFA2>ͼ<EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>еij<D0B5><C4B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
[Category("ObjectListView"),
|
||
Description("<22><><EFBFBD>б<EFBFBD><D0B1>е<EFBFBD><D0B5><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD>ڷ<EFBFBD><DAB7><EFBFBD>ϸ<EFBFBD><CFB8>ͼ<EFBFBD><CDBC>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ⱦ<EFBFBD><C8BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD><CFB8>Ϣ<EFBFBD><CFA2>ͼ<EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>еij<D0B5><C4B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"),
|
||
DefaultValue(null)]
|
||
public IRenderer ItemRenderer {
|
||
get { return itemRenderer; }
|
||
set { itemRenderer = value; }
|
||
}
|
||
private IRenderer itemRenderer;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks><3E><><EFBFBD><EFBFBD>PrimarySortColumn<6D>ı<EFBFBD><C4B1><EFBFBD></remarks>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual OLVColumn LastSortColumn {
|
||
get { return this.PrimarySortColumn; }
|
||
set { this.PrimarySortColumn = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD><C4B7><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks><3E><><EFBFBD><EFBFBD> PrimarySortOrder<65>ı<EFBFBD><C4B1><EFBFBD></remarks>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual SortOrder LastSortOrder {
|
||
get { return this.PrimarySortOrder; }
|
||
set { this.PrimarySortOrder = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ɸѡ<C9B8><D1A1><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <20>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Է<EFBFBD>ӳ<EFBFBD><D3B3>ɸѡ<C9B8><D1A1><EFBFBD><EFBFBD>
|
||
/// </remarks>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual IListFilter ListFilter {
|
||
get { return listFilter; }
|
||
set {
|
||
listFilter = value;
|
||
if (this.UseFiltering)
|
||
this.UpdateFiltering();
|
||
}
|
||
}
|
||
private IListFilter listFilter;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ÿ<EFBFBD><C3BF>ģ<EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD><EFBFBD>ɸѡ<C9B8><D1A1>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9> <see cref="AdditionalFilter"/> <20><><EFBFBD><EFBFBD><EFBFBD>Ǵ<EFBFBD><C7B4><EFBFBD><EFBFBD>ԣ<EFBFBD>
|
||
/// <20><>ΪAdditionalFilter<65><72><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>ɸѡ<C9B8><D1A1><EFBFBD><EFBFBD><EFBFBD>ϡ<EFBFBD>
|
||
/// <20><><EFBFBD>ô<EFBFBD><C3B4><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><D6BB><EFBFBD>滻<EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѹ<EFBFBD><D1B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>κ<EFBFBD><CEBA><EFBFBD>ɸѡ<C9B8><D1A1><EFBFBD><EFBFBD></para>
|
||
/// <para>
|
||
/// The list is updated immediately to reflect this filter.
|
||
/// </para>
|
||
/// </remarks>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual IModelFilter ModelFilter {
|
||
get { return modelFilter; }
|
||
set {
|
||
modelFilter = value;
|
||
this.NotifyNewModelFilter();
|
||
if (this.UseFiltering) {
|
||
this.UpdateFiltering();
|
||
|
||
// When the filter changes, it's likely/possible that the selection has also changed.
|
||
// It's expensive to see if the selection has actually changed (for large virtual lists),
|
||
// so we just fake a selection changed event, just in case. SF #144
|
||
this.OnSelectedIndexChanged(EventArgs.Empty);
|
||
}
|
||
}
|
||
}
|
||
private IModelFilter modelFilter;
|
||
|
||
/// <summary>
|
||
/// Gets the hit test info last time the mouse was moved.
|
||
/// </summary>
|
||
/// <remarks>Useful for hot item processing.</remarks>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual OlvListViewHitTestInfo MouseMoveHitTest {
|
||
get { return mouseMoveHitTest; }
|
||
private set { mouseMoveHitTest = value; }
|
||
}
|
||
private OlvListViewHitTestInfo mouseMoveHitTest;
|
||
|
||
/// <summary>
|
||
///<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.NET Groups<70><73><EFBFBD>ԵĹ<D4B5><C4B9><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD>ͬ<EFBFBD><CDAC>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊֻ<CEAA><D6BB><EFBFBD><EFBFBD><EFBFBD>ԡ<EFBFBD>
|
||
/// <20><><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><C4B8>IJ<EFBFBD><C4B2>ᷴӳ<E1B7B4><D3B3>ListView<65><77><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>
|
||
/// <20>ڴ<EFBFBD><DAB4>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӻ<EFBFBD>ɾ<EFBFBD><C9BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IJ<DEB8><C4B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>κ<EFBFBD><CEBA><EFBFBD><EFBFBD>á<EFBFBD>
|
||
/// Ҫִ<D2AA>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>BeforeCreatingGroups<70><73>AboutToCreateGroups<70>¼<EFBFBD><C2BC><EFBFBD>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Щ<EFBFBD>¼<EFBFBD><C2BC>е<EFBFBD><D0B5><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>
|
||
/// </remarks>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public IList<OLVGroup> OLVGroups {
|
||
get { return this.olvGroups; }
|
||
set { this.olvGroups = value; }
|
||
}
|
||
private IList<OLVGroup> olvGroups;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>۵<EFBFBD><DBB5><EFBFBD>OLVGroups<70>ļ<EFBFBD><C4BC>ϡ<EFBFBD>
|
||
/// </summary>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public IEnumerable<OLVGroup> CollapsedGroups {
|
||
get
|
||
{
|
||
if (this.OLVGroups != null)
|
||
{
|
||
foreach (OLVGroup group in this.OLVGroups)
|
||
{
|
||
if (group.Collapsed)
|
||
yield return group;
|
||
}
|
||
}
|
||
}
|
||
set
|
||
{
|
||
if (this.OLVGroups == null)
|
||
return;
|
||
|
||
Hashtable shouldCollapse = new Hashtable();
|
||
if (value != null)
|
||
{
|
||
foreach (OLVGroup group in value)
|
||
shouldCollapse[group.Key] = true;
|
||
}
|
||
foreach (OLVGroup group in this.OLVGroups)
|
||
{
|
||
group.Collapsed = shouldCollapse.ContainsKey(group.Key);
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets or sets whether the user wants to owner draw the header control
|
||
/// themselves. If this is false (the default), ObjectListView will use
|
||
/// custom drawing to render the header, if needed.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// If you listen for the DrawColumnHeader event, you need to set this to true,
|
||
/// otherwise your event handler will not be called.
|
||
/// </remarks>
|
||
[Category("ObjectListView"),
|
||
Description("Should the DrawColumnHeader event be triggered"),
|
||
DefaultValue(false)]
|
||
public bool OwnerDrawnHeader {
|
||
get { return ownerDrawnHeader; }
|
||
set { ownerDrawnHeader = value; }
|
||
}
|
||
private bool ownerDrawnHeader;
|
||
|
||
/// <summary>
|
||
///<2F><>ȡ/<2F><><EFBFBD>ô<EFBFBD><C3B4>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// <20><><EFBFBD>ô<EFBFBD><C3B4><EFBFBD><EFBFBD>Ժؼ<F3A3ACBF><D8BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݽ<EFBFBD><DDBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¡<EFBFBD>
|
||
/// </para>
|
||
/// <para><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܣ<EFBFBD><DCA3>˷<EFBFBD><CBB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD>ݡ<EFBFBD>ʹ<EFBFBD><CAB9> <see cref="SetObjects(IEnumerable, bool)"/> if
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>뱣<EFBFBD><EBB1A3><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD>ݣ<EFBFBD><DDA3><EFBFBD>ִ<EFBFBD><D6B4><EFBFBD><EFBFBD><EFBFBD>²<EFBFBD><C2B2><EFBFBD><EFBFBD><EFBFBD>
|
||
///<2F><><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD>Ǹô<C7B8><C3B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD><C4B2>֣<EFBFBD><D6A3><EFBFBD><EFBFBD><EFBFBD>ΪO(N)<29><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>n<EFBFBD><6E>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></para>
|
||
/// <para><3E>˷<EFBFBD><CBB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̰߳<DFB3>ȫ<EFBFBD>ġ<EFBFBD></para>
|
||
/// <para><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷʵ<C8B7><CAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ի<EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>1000<30><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҪһЩʱ<D0A9><CAB1><EFBFBD><EFBFBD><EFBFBD>ܷ<EFBFBD><DCB7>ء<EFBFBD></para>
|
||
/// <para><3E>˼<EFBFBD><CBBC><EFBFBD>δ<EFBFBD><CEB4><EFBFBD><EFBFBD>ɸѡ<C9B8><D1A1>ʹ<EFBFBD><CAB9> <see cref="FilteredObjects"/> ֻ<><D6BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Щ<EFBFBD><D0A9><EFBFBD>κ<EFBFBD><CEBA>Ѱ<EFBFBD>װ<EFBFBD><D7B0>ɸѡ<C9B8><D1A1><EFBFBD><EFBFBD><EFBFBD>Ҵ<EFBFBD><D2B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD><EFBFBD></para>
|
||
/// </remarks>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual IEnumerable Objects {
|
||
get { return this.objects; }
|
||
set { this.SetObjects(value, true); }
|
||
}
|
||
private IEnumerable objects;
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1>ǰ<EFBFBD>ؼ<EFBFBD><D8BC><EFBFBD><EFBFBD>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɵ<EFBFBD><C9B5>б<EFBFBD>
|
||
/// </summary>
|
||
public virtual IList ObjectsList
|
||
{
|
||
get
|
||
{
|
||
ArrayList list = new ArrayList();
|
||
if (this.Objects == null) { return list; }
|
||
var enumer = this.Objects.GetEnumerator();
|
||
while(enumer.MoveNext())
|
||
{
|
||
list.Add(enumer.Current);
|
||
}
|
||
return list;
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>Ⱥ<EFBFBD><C8BA>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD>ǵĶ<C7B5><C4B6>ϡ<F3BCAFBA>
|
||
/// (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Excel<65><6C><EFBFBD><EFBFBD>ɸѡ<C9B8><D1A1>)
|
||
/// </summary>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual IEnumerable ObjectsForClustering {
|
||
get { return this.Objects; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ý<EFBFBD><C3BD><EFBFBD>ListView<65><77><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD>ͼ<EFBFBD><CDBC>
|
||
/// </summary>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ý<EFBFBD><C3BD><EFBFBD>ListView<65><77><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD>ͼ<EFBFBD><CDBC>"),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
|
||
public ImageOverlay OverlayImage {
|
||
get { return this.imageOverlay; }
|
||
set {
|
||
if (this.imageOverlay == value)
|
||
return;
|
||
|
||
this.RemoveOverlay(this.imageOverlay);
|
||
this.imageOverlay = value;
|
||
this.AddOverlay(this.imageOverlay);
|
||
}
|
||
}
|
||
private ImageOverlay imageOverlay;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ý<EFBFBD><C3BD><EFBFBD>ListView<65><77><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD><C6B5>ı<EFBFBD>
|
||
/// </summary>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ý<EFBFBD><C3BD><EFBFBD>ListView<65><77><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD><C6B5>ı<EFBFBD>"),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
|
||
public TextOverlay OverlayText {
|
||
get { return this.textOverlay; }
|
||
set {
|
||
if (this.textOverlay == value)
|
||
return;
|
||
|
||
this.RemoveOverlay(this.textOverlay);
|
||
this.textOverlay = value;
|
||
this.AddOverlay(this.textOverlay);
|
||
}
|
||
}
|
||
private TextOverlay textOverlay;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>и<EFBFBD><D0B8><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><CDB8><EFBFBD>ȡ<EFBFBD>0<EFBFBD><30>ʾ<EFBFBD><CABE>ȫ<C8AB><CDB8><EFBFBD><EFBFBD>255<35><35>ʾ<EFBFBD><CABE>ȫ<EFBFBD><C8AB><EFBFBD><CDB8><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>
|
||
///<2F><><EFBFBD>Ѿ<EFBFBD><D1BE><EFBFBD>ʱ<EFBFBD>ˣ<EFBFBD><CBA3><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9>Transparency<63><79>
|
||
/// </remarks>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public int OverlayTransparency {
|
||
get { return this.overlayTransparency; }
|
||
set { this.overlayTransparency = Math.Min(255, Math.Max(0, value)); }
|
||
}
|
||
private int overlayTransparency = 128;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>ListView<65><77><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶĸ<C6B5><C4B8><EFBFBD><EFBFBD>б<EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// You can add new overlays and remove overlays that you have added, but
|
||
/// don't mess with the overlays that you didn't create.
|
||
/// </remarks>
|
||
[Browsable(false)]
|
||
protected IList<IOverlay> Overlays {
|
||
get { return this.overlays; }
|
||
}
|
||
private readonly List<IOverlay> overlays = new List<IOverlay>();
|
||
|
||
/// <summary>
|
||
/// Gets or sets whether the ObjectListView will be owner drawn. Defaults to true.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// When this is true, all of ObjectListView's neat features are available.
|
||
/// </para>
|
||
/// <para>We have to reimplement this property, even though we just call the base
|
||
/// property, in order to change the [DefaultValue] to true.
|
||
/// </para>
|
||
/// </remarks>
|
||
[Category("Appearance"),
|
||
Description("Should the ListView do its own rendering"),
|
||
DefaultValue(true)]
|
||
public new bool OwnerDraw {
|
||
get { return base.OwnerDraw; }
|
||
set { base.OwnerDraw = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɺ<EFBFBD>ɸѡ<C9B8><D1A1><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD><D4BD><EFBFBD>δ<EFBFBD><CEB4>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD>CheckStateGetter/Putterʱ<72><CAB1><EFBFBD><EFBFBD><EFBFBD>á<EFBFBD>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9>CheckStateGetter/Putter<65><72><EFBFBD><EFBFBD>ô<EFBFBD><C3B4>Щ<EFBFBD><D0A9><EFBFBD><EFBFBD><EFBFBD>Ѿ<EFBFBD><D1BE>־û<D6BE><C3BB><EFBFBD><EFBFBD>еļ<D0B5><C4BC><EFBFBD><EFBFBD>ԡ<EFBFBD>
|
||
/// </para>
|
||
/// <para><3E><>Ĭ<EFBFBD><C4AC>ֵΪtrue<75><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ΪFalse<73><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɻ<EFBFBD>ɸѡ<C9B8>б<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>ѡ<EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>ֵ<EFBFBD><D6B5>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1>н<EFBFBD><D0BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊfalse<73><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>밲װCheckStateGetter/Putters<72><73></para>
|
||
/// </remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɺ<EFBFBD>ɸѡ<C9B8><D1A1><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD>ֵ"),
|
||
DefaultValue(true)]
|
||
public virtual bool PersistentCheckBoxes {
|
||
get { return persistentCheckBoxes; }
|
||
set {
|
||
if (persistentCheckBoxes == value)
|
||
return;
|
||
persistentCheckBoxes = value;
|
||
this.ClearPersistentCheckState();
|
||
}
|
||
}
|
||
private bool persistentCheckBoxes = true;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ü<EFBFBD>סģ<D7A1>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD>ĸ<EFBFBD>ѡ<EFBFBD><D1A1>״̬<D7B4><CCAC><EFBFBD>ֵ<EFBFBD>
|
||
/// </summary>
|
||
/// <remarks><3E><>PersistentCheckBoxsֵΪTRUEʱ<45><CAB1><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD>.</remarks>
|
||
protected Dictionary<Object, CheckState> CheckStateMap {
|
||
get { return checkStateMap ?? (checkStateMap = new Dictionary<object, CheckState>()); }
|
||
set { checkStateMap = value; }
|
||
}
|
||
private Dictionary<Object, CheckState> checkStateMap;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual OLVColumn PrimarySortColumn {
|
||
get { return this.primarySortColumn; }
|
||
set {
|
||
this.primarySortColumn = value;
|
||
if (this.TintSortColumn)
|
||
this.SelectedColumn = value;
|
||
}
|
||
}
|
||
private OLVColumn primarySortColumn;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD><C4B7><EFBFBD>
|
||
/// </summary>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual SortOrder PrimarySortOrder {
|
||
get { return primarySortOrder; }
|
||
set { primarySortOrder = value; }
|
||
}
|
||
private SortOrder primarySortOrder;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ò<EFBFBD><C3B2>ɱ༭<C9B1><E0BCAD>ѡ<EFBFBD><D1A1><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD>á<EFBFBD>Ĭ<EFBFBD><C4AC><EFBFBD><EFBFBD>false<73><65>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ(owner drawn mode)<29><><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7></para>
|
||
/// </remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ò<EFBFBD><C3B2>ɱ༭<C9B1><E0BCAD>ѡ<EFBFBD><D1A1><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>"),
|
||
DefaultValue(false)]
|
||
public virtual bool RenderNonEditableCheckboxesAsDisabled {
|
||
get { return renderNonEditableCheckboxesAsDisabled; }
|
||
set { renderNonEditableCheckboxesAsDisabled = value; }
|
||
}
|
||
private bool renderNonEditableCheckboxesAsDisabled;
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>λָ<CEBB><D6B8><EFBFBD>ؼ<EFBFBD><D8BC><EFBFBD>ÿ<EFBFBD>еĸ߶ȡ<DFB6>
|
||
/// </summary>
|
||
/// <remarks><para><3E>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD>е<EFBFBD><D0B5>и<EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1>Сͼ<D0A1><CDBC><EFBFBD>б<EFBFBD><D0B1><EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǹü<C7B8><C3BC><EFBFBD>(ԭ<><D4AD><EFBFBD>ǣ<EFBFBD><C7A3><EFBFBD><EFBFBD><EFBFBD>Ȼ<EFBFBD><C8BB><EFBFBD>ܽ<EFBFBD><DCBD>и<EFBFBD><D0B8><EFBFBD><EFBFBD><EFBFBD>ΪС<CEAA>ڿؼ<DABF><D8BC><EFBFBD>ʹ<EFBFBD>õ<EFBFBD><C3B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>и<EFBFBD>)<29><></para>
|
||
/// <para><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ-1<><31>ʾʹ<CABE><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㷽<EFBFBD><E3B7BD><EFBFBD><EFBFBD></para>
|
||
/// <para><bold><3E>˹<EFBFBD><CBB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>鹦<EFBFBD>ܣ<EFBFBD></bold><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>ô˹<C3B4><CBB9>ܣ<EFBFBD><DCA3><EFBFBD><EFBFBD>ij<EFBFBD><C4B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܻᷢ<DCBB><E1B7A2><EFBFBD><EFBFBD><EFBFBD>벻<EFBFBD><EBB2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>顣</para>
|
||
/// </remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>λָ<CEBB><D6B8><EFBFBD>ؼ<EFBFBD><D8BC><EFBFBD>ÿ<EFBFBD>еĸ߶<C4B8>"),
|
||
DefaultValue(-1)]
|
||
public virtual int RowHeight {
|
||
get { return rowHeight; }
|
||
set {
|
||
if (value < 1)
|
||
rowHeight = -1;
|
||
else
|
||
rowHeight = value;
|
||
if (this.DesignMode)
|
||
return;
|
||
this.SetupBaseImageList();
|
||
if (this.CheckBoxes)
|
||
this.InitializeStateImageList();
|
||
}
|
||
}
|
||
private int rowHeight = -1;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡÿ<C8A1><C3BF><EFBFBD>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD>
|
||
/// </summary>
|
||
[Browsable(false)]
|
||
public virtual int RowHeightEffective {
|
||
get {
|
||
switch (this.View) {
|
||
case View.List:
|
||
case View.SmallIcon:
|
||
case View.Details:
|
||
return Math.Max(this.SmallImageSize.Height, this.Font.Height);
|
||
|
||
case View.Tile:
|
||
return this.TileSize.Height;
|
||
|
||
case View.LargeIcon:
|
||
if (this.LargeImageList == null)
|
||
return this.Font.Height;
|
||
|
||
return Math.Max(this.LargeImageList.ImageSize.Height, this.Font.Height);
|
||
|
||
default:
|
||
// This should never happen
|
||
return 0;
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD>˿ؼ<CBBF><D8BC><EFBFBD>ÿҳ<C3BF><D2B3><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
[Browsable(false)]
|
||
public virtual int RowsPerPage {
|
||
get {
|
||
return NativeMethods.GetCountPerPage(this);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
///<2F><>ȡ/<2F><><EFBFBD>ý<EFBFBD><C3BD><EFBFBD><EFBFBD>ڽ<EFBFBD><DABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>ȵıȽϵ<C8BD><CFB5><EFBFBD>(<28>ڶ<EFBFBD><DAB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)<29><>
|
||
/// </summary>
|
||
/// <remarks><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD>档<EFBFBD><E6A1A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD><D4B1>̷<EFBFBD>ʽ<EFBFBD><CABD><EFBFBD>á<EFBFBD></remarks>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual OLVColumn SecondarySortColumn {
|
||
get { return this.secondarySortColumn; }
|
||
set { this.secondarySortColumn = value; }
|
||
}
|
||
private OLVColumn secondarySortColumn;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD>ʹ<EFBFBD><CAB9>Second darySortColumnʱ<6E><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʲô˳<C3B4><CBB3><EFBFBD>ȽϽ<C8BD><CFBD><EFBFBD>
|
||
/// </summary>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual SortOrder SecondarySortOrder {
|
||
get { return this.secondarySortOrder; }
|
||
set { this.secondarySortOrder = value; }
|
||
}
|
||
private SortOrder secondarySortOrder = SortOrder.None;
|
||
|
||
/// <summary>
|
||
///<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD><C3B5>û<EFBFBD><C3BB><EFBFBD>Ctrl+A<><41><EFBFBD>ϼ<EFBFBD>ʱ<EFBFBD>Ƿ<EFBFBD>Ӧѡ<D3A6><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD><C3B5>û<EFBFBD><C3BB><EFBFBD>Ctrl+A<><41><EFBFBD>ϼ<EFBFBD>ʱ<EFBFBD>Ƿ<EFBFBD>Ӧѡ<D3A6><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"),
|
||
DefaultValue(true)]
|
||
public virtual bool SelectAllOnControlA {
|
||
get { return selectAllOnControlA; }
|
||
set { selectAllOnControlA = value; }
|
||
}
|
||
private bool selectAllOnControlA = true;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD><C3B5>û<EFBFBD><C3BB>Ҽ<EFBFBD><D2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>ʾһ<CABE><D2BB><EFBFBD>˵<EFBFBD><CBB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD>ͼ<EFBFBD>н<EFBFBD><D0BD><EFBFBD>ʾ<EFBFBD><CABE>Щ<EFBFBD><D0A9>
|
||
/// </summary>
|
||
/// <remarks><3E><>ֻ<EFBFBD><D6BB>SelectColumnsOnRightClickBehaviour<75>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>װ<EFBFBD><D7B0><EFBFBD><EFBFBD>.</remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD><C3B5>û<EFBFBD><C3BB>Ҽ<EFBFBD><D2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>ʾһ<CABE><D2BB><EFBFBD>˵<EFBFBD><CBB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD>ͼ<EFBFBD>н<EFBFBD><D0BD><EFBFBD>ʾ<EFBFBD><CABE>Щ<EFBFBD><D0A9>"),
|
||
DefaultValue(true)]
|
||
public virtual bool SelectColumnsOnRightClick {
|
||
get { return this.SelectColumnsOnRightClickBehaviour != ColumnSelectBehaviour.None; }
|
||
set {
|
||
if (value) {
|
||
if (this.SelectColumnsOnRightClickBehaviour == ColumnSelectBehaviour.None)
|
||
this.SelectColumnsOnRightClickBehaviour = ColumnSelectBehaviour.InlineMenu;
|
||
} else {
|
||
this.SelectColumnsOnRightClickBehaviour = ColumnSelectBehaviour.None;
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD><C3B5>Ҽ<EFBFBD><D2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܹ<EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD><C3B5>Ҽ<EFBFBD><D2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܹ<EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD>"),
|
||
DefaultValue(ColumnSelectBehaviour.InlineMenu)]
|
||
public virtual ColumnSelectBehaviour SelectColumnsOnRightClickBehaviour {
|
||
get { return selectColumnsOnRightClickBehaviour; }
|
||
set { selectColumnsOnRightClickBehaviour = value; }
|
||
}
|
||
private ColumnSelectBehaviour selectColumnsOnRightClickBehaviour = ColumnSelectBehaviour.InlineMenu;
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD>˵<EFBFBD><CBB5><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD>Ŀ<EFBFBD>ִ<F3B1A3B3><D6B4><EFBFBD>״̬<D7B4><CCAC><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4><EFBFBD>״̬<D7B4><CCAC><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD>һ<EFBFBD>δ<CEB4><F2BFAABB>رն<D8B1><D5B6><EFBFBD><EFBFBD>С<EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>SelectColumnsOnRightClickBehaviour<75><72><EFBFBD><EFBFBD>ΪInlineMenuʱ<75><CAB1><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>ΪSubMenu<6E>˵<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>ѡ<EFBFBD><EFBFBD><EEB2BB><EFBFBD><EFBFBD><EFBFBD>á<EFBFBD></remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22><><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD>˵<EFBFBD><CBB5><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD>Ŀ<EFBFBD>ִ<F3B1A3B3><D6B4><EFBFBD>״̬<D7B4><CCAC><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4><EFBFBD>״̬<D7B4><CCAC><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD>һ<EFBFBD>δ<CEB4><F2BFAABB>رն<D8B1><D5B6><EFBFBD><EFBFBD>С<EFBFBD>"),
|
||
DefaultValue(true)]
|
||
public virtual bool SelectColumnsMenuStaysOpen {
|
||
get { return selectColumnsMenuStaysOpen; }
|
||
set { selectColumnsMenuStaysOpen = value; }
|
||
}
|
||
private bool selectColumnsMenuStaysOpen = true;
|
||
|
||
/// <summary>
|
||
///<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// <20><><EFBFBD><EFBFBD>TintSortColumnΪtrue<75><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>н<EFBFBD><D0BD>Զ<EFBFBD><D4B6><EFBFBD>Ϊѡ<CEAA><D1A1><EFBFBD>С<EFBFBD>
|
||
/// </para>
|
||
/// <para>
|
||
/// ɫ<><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB>SelectedColumnTint<6E><74><EFBFBD>ơ<EFBFBD>
|
||
/// </para>
|
||
/// </remarks>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public OLVColumn SelectedColumn {
|
||
get { return this.selectedColumn; }
|
||
set {
|
||
this.selectedColumn = value;
|
||
if (value == null) {
|
||
this.RemoveDecoration(this.selectedColumnDecoration);
|
||
} else {
|
||
if (!this.HasDecoration(this.selectedColumnDecoration))
|
||
this.AddDecoration(this.selectedColumnDecoration);
|
||
}
|
||
}
|
||
}
|
||
private OLVColumn selectedColumn;
|
||
private readonly TintedColumnDecoration selectedColumnDecoration = new TintedColumnDecoration();
|
||
|
||
/// <summary>
|
||
/// Gets or sets the decoration that will be drawn on all selected rows
|
||
/// </summary>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual IDecoration SelectedRowDecoration {
|
||
get { return this.selectedRowDecoration; }
|
||
set { this.selectedRowDecoration = value; }
|
||
}
|
||
private IDecoration selectedRowDecoration;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6>ʹ<EFBFBD><CAB9>ʲô<CAB2><C3B4>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// ɫ<><C9AB><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Alpha<68>ɻ<EFBFBD><C9BB>ϵģ<CFB5><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD>Ǵ<EFBFBD>ɫ(<28><>Alpha=255)<29><><EFBFBD><EFBFBD><EFBFBD>Ὣ<EFBFBD><E1BDAB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD>к<EFBFBD><D0BA><EFBFBD><EFBFBD><EFBFBD>Alphaֵ<61><D6B5>
|
||
/// </remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6>ʹ<EFBFBD><CAB9>ʲô<CAB2><C3B4>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ"),
|
||
DefaultValue(typeof(Color), "")]
|
||
public virtual Color SelectedColumnTint {
|
||
get { return selectedColumnTint; }
|
||
set {
|
||
this.selectedColumnTint = value.A == 255 ? Color.FromArgb(15, value) : value;
|
||
this.selectedColumnDecoration.Tint = this.selectedColumnTint;
|
||
}
|
||
}
|
||
private Color selectedColumnTint = Color.Empty;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD>ǰѡ<C7B0><D1A1><EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB>ѡ<EFBFBD><D1A1><EFBFBD>κ<EFBFBD><CEBA>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD>˶<EFBFBD><CBB6><EFBFBD><EFBFBD>У<EFBFBD><D0A3><EFBFBD>-1<><31>
|
||
/// </summary>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual int SelectedIndex {
|
||
get { return this.SelectedIndices.Count == 1 ? this.SelectedIndices[0] : -1; }
|
||
set {
|
||
this.SelectedIndices.Clear();
|
||
if (value >= 0 && value < this.Items.Count)
|
||
this.SelectedIndices.Add(value);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
///<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD>ǰѡ<C7B0><D1A1><EFBFBD><EFBFBD>ListViewItem<65><6D><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δѡ<CEB4><D1A1><EFBFBD>κ<EFBFBD><CEBA>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD>˶<EFBFBD><CBB6><EFBFBD><EFBFBD>У<EFBFBD><D0A3><EFBFBD>NULL<4C><4C>
|
||
/// </summary>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual OLVListItem SelectedItem {
|
||
get {
|
||
return this.SelectedIndices.Count == 1 ? this.GetItem(this.SelectedIndices[0]) : null;
|
||
}
|
||
set {
|
||
this.SelectedIndices.Clear();
|
||
if (value != null)
|
||
this.SelectedIndices.Add(value.Index);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD>ֻѡ<D6BB><D1A1><EFBFBD><EFBFBD>һ<EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD>ӵ<EFBFBD>ǰѡ<C7B0><D1A1><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD>ȡģ<C8A1>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD><EFBFBD>
|
||
/// <20><><EFBFBD><EFBFBD>δѡ<CEB4><D1A1><EFBFBD>κ<EFBFBD><CEBA>У<EFBFBD><D0A3><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD>˶<EFBFBD><CBB6><EFBFBD><EFBFBD>У<EFBFBD><D0A3><EFBFBD>NULL<4C><4C>
|
||
/// <20><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>⽫ѡ<E2BDAB><D1A1><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD>ģ<EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڸ<EFBFBD><DAB8><EFBFBD><EFBFBD>ϣ<EFBFBD>ȡ<EFBFBD><C8A1>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>
|
||
/// </summary>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual Object SelectedObject {
|
||
get {
|
||
return this.SelectedIndices.Count == 1 ? this.GetModelObject(this.SelectedIndices[0]) : null;
|
||
}
|
||
set {
|
||
// If the given model is already selected, don't do anything else (prevents an flicker)
|
||
object selectedObject = this.SelectedObject;
|
||
if (selectedObject != null && selectedObject.Equals(value))
|
||
return;
|
||
|
||
this.SelectedIndices.Clear();
|
||
this.SelectObject(value, true);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20>ӵ<EFBFBD>ǰѡ<C7B0><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD>ȡģ<C8A1>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD><EFBFBD>
|
||
/// <20><><EFBFBD><EFBFBD>δѡ<CEB4><D1A1><EFBFBD>κ<EFBFBD><CEBA>У<EFBFBD><D0A3>ص<F2B7B5BB><D8B5>б<EFBFBD>Ϊ<EFBFBD>ա<EFBFBD>
|
||
/// <20><><EFBFBD>ô<EFBFBD>ֵʱ<D6B5><CAB1><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD>ģ<EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD>ȡ<EFBFBD><C8A1>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>
|
||
/// </summary>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual IList SelectedObjects {
|
||
get {
|
||
ArrayList list = new ArrayList();
|
||
foreach (int index in this.SelectedIndices)
|
||
list.Add(this.GetModelObject(index));
|
||
return list;
|
||
}
|
||
set {
|
||
this.SelectedIndices.Clear();
|
||
this.SelectObjects(value);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD><C3B5>û<EFBFBD><C3BB>Ҽ<EFBFBD><D2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>ʾһ<CABE><D2BB><EFBFBD>˵<EFBFBD><CBB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1>Ҫ<EFBFBD><D2AA><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD><CDBC>ִ<EFBFBD>еij<D0B5><C4B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD><C3B5>û<EFBFBD><C3BB>Ҽ<EFBFBD><D2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>ʾһ<CABE><D2BB><EFBFBD>˵<EFBFBD><CBB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1>Ҫ<EFBFBD><D2AA><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD><CDBC>ִ<EFBFBD>еij<D0B5><C4B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"),
|
||
DefaultValue(false)]
|
||
public virtual bool ShowCommandMenuOnRightClick {
|
||
get { return showCommandMenuOnRightClick; }
|
||
set { showCommandMenuOnRightClick = value; }
|
||
}
|
||
private bool showCommandMenuOnRightClick;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD><C3B5>Ҽ<EFBFBD><D2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ؼ<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>ObjectListView<65>Ƿ<EFBFBD><C7B7><EFBFBD>ɸѡ<C9B8>˵<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
[Category("ObjectListView"),
|
||
Description("<22><><EFBFBD><EFBFBD>ΪTrue<75><65><EFBFBD><EFBFBD><EFBFBD>Ҽ<EFBFBD><D2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1>⽫<EFBFBD><E2BDAB>ʾɸѡ<C9B8><D1A1><EFBFBD>˵<EFBFBD>ѡ<EFBFBD><D1A1>"),
|
||
DefaultValue(true)]
|
||
public bool ShowFilterMenuOnRightClick {
|
||
get { return showFilterMenuOnRightClick; }
|
||
set { showFilterMenuOnRightClick = value; }
|
||
}
|
||
private bool showFilterMenuOnRightClick = true;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD>Ŀ
|
||
/// </summary>
|
||
[Category("Appearance"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD>Ŀ"),
|
||
DefaultValue(false)]
|
||
new public virtual bool ShowGroups {
|
||
get { return base.ShowGroups; }
|
||
set {
|
||
this.GroupImageList = this.GroupImageList;
|
||
base.ShowGroups = value;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾλͼ<CEBB><CDBC><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// The only reason for not wanting to have sort indicators is that, on pre-XP versions of
|
||
/// Windows, having sort indicators required the ListView to have a small image list, and
|
||
/// as soon as you give a ListView a SmallImageList, the text of column 0 is bumped 16
|
||
/// pixels to the right, even if you never used an image.
|
||
/// </remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾλͼ<CEBB><CDBC><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"),
|
||
DefaultValue(true)]
|
||
public virtual bool ShowSortIndicators {
|
||
get { return showSortIndicators; }
|
||
set { showSortIndicators = value; }
|
||
}
|
||
private bool showSortIndicators;
|
||
|
||
/// <summary>
|
||
/// <20>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD>ͼ<EFBFBD><CDBC>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para><3E><><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><DFBB>Ƶģ<C6B5><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾͼ<CABE><CDBC></para>
|
||
/// </remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD>ͼ<EFBFBD><CDBC>"),
|
||
DefaultValue(false)]
|
||
public virtual bool ShowImagesOnSubItems {
|
||
get { return showImagesOnSubItems; }
|
||
set {
|
||
showImagesOnSubItems = value;
|
||
if (this.Created)
|
||
this.ApplyExtendedStyles();
|
||
if (value && this.VirtualMode)
|
||
this.OwnerDraw = true;
|
||
}
|
||
}
|
||
private bool showImagesOnSubItems;
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD><D4BF>Ʒ<EFBFBD><C6B7><EFBFBD><EFBFBD><EFBFBD>ǩ<EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>ʾ<EFBFBD>÷<EFBFBD><C3B7><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>
|
||
///<2F><><EFBFBD>ĸ<EFBFBD>ʽ<EFBFBD><CABD>GroupWithItemCountFormat/GroupWithItemCountSingularFormat<61><74><EFBFBD>Կ<EFBFBD><D4BF><EFBFBD>
|
||
/// </remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22><><EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD><D4BF>Ʒ<EFBFBD><C6B7><EFBFBD><EFBFBD><EFBFBD>ǩ<EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>ʾ<EFBFBD>÷<EFBFBD><C3B7><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD>"),
|
||
DefaultValue(false)]
|
||
public virtual bool ShowItemCountOnGroups {
|
||
get { return showItemCountOnGroups; }
|
||
set { showItemCountOnGroups = value; }
|
||
}
|
||
private bool showItemCountOnGroups;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ÿؼ<C3BF><D8BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD>ʾ<EFBFBD>б<EFBFBD><D0B1><EFBFBD>(True)<29><><EFBFBD><EFBFBD><EFBFBD>ǽ<EFBFBD><C7BD><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD><CFB8>Ϣ<EFBFBD><CFA2>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD>ʾ<EFBFBD>б<EFBFBD><D0B1><EFBFBD>(False)
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD>Թ<EFBFBD><D4B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>JPP 2010/04/06<30><36>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD>ؼ<EFBFBD>֮ǰ<D6AE><C7B0><EFBFBD>õģ<C3B5><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// <20><><EFBFBD>ǣ<EFBFBD><C7A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD>ؼ<EFBFBD><D8BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>رգ<D8B1><D5A3><EFBFBD><EFBFBD>ؼ<EFBFBD><D8BC><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD>临ѡ<E4B8B4><D1A1>(<28><><EFBFBD>֣<EFBFBD>)
|
||
/// </para>
|
||
/// <para>
|
||
/// Ҫ<>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD>ؼ<EFBFBD><D8BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܸ<EFBFBD><DCB8>ӡ<EFBFBD>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǹرյģ<D5B5><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>DZ<EFBFBD><C7B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD>֡<EFBFBD>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD>״̬<D7B4><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD>رգ<D8B1><D5A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD>´<EFBFBD><C2B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʊ<EFBFBD><C6B1><EFBFBD>
|
||
/// <20><><EFBFBD>´<EFBFBD><C2B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>⣬<EFBFBD><E2A3AC>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD>ǵĸ<C7B5>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD>ʧ<EFBFBD><CAA7>
|
||
/// </para>
|
||
/// <para>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD>Բ<EFBFBD><D4B2>ܹ<EFBFBD><DCB9><EFBFBD><EFBFBD><EFBFBD> Win XP ϵͳ.</para>
|
||
/// </remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ÿؼ<C3BF><D8BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD>ʾ<EFBFBD>б<EFBFBD><D0B1><EFBFBD>(True)<29><><EFBFBD><EFBFBD><EFBFBD>ǽ<EFBFBD><C7BD><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD><CFB8>Ϣ<EFBFBD><CFA2>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD>ʾ<EFBFBD>б<EFBFBD><D0B1><EFBFBD>(False)"),
|
||
DefaultValue(true)]
|
||
public bool ShowHeaderInAllViews {
|
||
get { return ObjectListView.IsVistaOrLater && showHeaderInAllViews; }
|
||
set {
|
||
if (showHeaderInAllViews == value)
|
||
return;
|
||
|
||
showHeaderInAllViews = value;
|
||
|
||
// If the control isn't already created, everything is fine.
|
||
if (!this.Created)
|
||
return;
|
||
|
||
// If the header is being hidden, we have to recreate the control
|
||
// to remove the style (not sure why this is)
|
||
if (showHeaderInAllViews)
|
||
this.ApplyExtendedStyles();
|
||
else
|
||
this.RecreateHandle();
|
||
|
||
// Still more complications. The change doesn't become visible until the View is changed
|
||
if (this.View != View.Details) {
|
||
View temp = this.View;
|
||
this.View = View.Details;
|
||
this.View = temp;
|
||
}
|
||
}
|
||
}
|
||
private bool showHeaderInAllViews = true;
|
||
|
||
/// <summary>
|
||
///<2F><>дSmallImageList<73><74><EFBFBD>ԣ<EFBFBD><D4A3>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD>ǿ<EFBFBD><C7BF><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks><para><3E><><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9>RowHeight<68><74><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD>иߣ<D0B8><DFA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD>RowHeight֮ǰ<D6AE><C7B0>ȫ<EFBFBD><C8AB>ʼ<EFBFBD><CABC>SmallImageList<73><74>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>и<EFBFBD>֮<EFBFBD><D6AE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٴν<D9B4>ͼ<EFBFBD><CDBC><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ؼ<EFBFBD><D8BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><F2B5A5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD>ģ<EFBFBD>
|
||
/// <code>listView1.SmallImageList = listView1.SmallImageList;</code></para>
|
||
/// </remarks>
|
||
new public ImageList SmallImageList {
|
||
get { return this.shadowedImageList; }
|
||
set {
|
||
this.shadowedImageList = value;
|
||
if (this.UseSubItemCheckBoxes)
|
||
this.SetupSubItemCheckBoxes();
|
||
this.SetupBaseImageList();
|
||
}
|
||
}
|
||
private ImageList shadowedImageList;
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD>Сͼ<D0A1><CDBC><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD>Ĵ<EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><C4AC>ֵ
|
||
/// </summary>
|
||
[Browsable(false)]
|
||
public virtual Size SmallImageSize {
|
||
get {
|
||
return this.BaseSmallImageList == null ? new Size(16, 16) : this.BaseSmallImageList.ImageSize;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD>Ӧ<EFBFBD>ð<EFBFBD><C3B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ΪFalse<73><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>ͬһ<CDAC>н<EFBFBD><D0BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
[Category("ObjectListView"),
|
||
Description("<22><><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD>Ӧ<EFBFBD>ð<EFBFBD><C3B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ΪFalse<73><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>ͬһ<CDAC>н<EFBFBD><D0BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"),
|
||
DefaultValue(true)]
|
||
public virtual bool SortGroupItemsByPrimaryColumn {
|
||
get { return this.sortGroupItemsByPrimaryColumn; }
|
||
set { this.sortGroupItemsByPrimaryColumn = value; }
|
||
}
|
||
private bool sortGroupItemsByPrimaryColumn = true;
|
||
|
||
/// <summary>
|
||
///<2F><><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĩβ<C4A9><CEB2><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD>ͷ֮<CDB7><D6AE>Ӧ<EFBFBD><D3A6><EFBFBD>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
[Category("ObjectListView"),
|
||
Description("<22><><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĩβ<C4A9><CEB2><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD>ͷ֮<CDB7><D6AE>Ӧ<EFBFBD><D3A6><EFBFBD>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"),
|
||
DefaultValue(0)]
|
||
public virtual int SpaceBetweenGroups {
|
||
get { return this.spaceBetweenGroups; }
|
||
set {
|
||
if (this.spaceBetweenGroups == value)
|
||
return;
|
||
|
||
this.spaceBetweenGroups = value;
|
||
this.SetGroupSpacing();
|
||
}
|
||
}
|
||
private int spaceBetweenGroups;
|
||
|
||
private void SetGroupSpacing() {
|
||
if (!this.IsHandleCreated)
|
||
return;
|
||
|
||
NativeMethods.LVGROUPMETRICS metrics = new NativeMethods.LVGROUPMETRICS();
|
||
metrics.cbSize = ((uint)Marshal.SizeOf(typeof(NativeMethods.LVGROUPMETRICS)));
|
||
metrics.mask = (uint)GroupMetricsMask.LVGMF_BORDERSIZE;
|
||
metrics.Bottom = (uint)this.SpaceBetweenGroups;
|
||
NativeMethods.SetGroupMetrics(this, metrics);
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><CEA2>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
[Category("ObjectListView"),
|
||
Description("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><CEA2>ɫ<EFBFBD><C9AB>"),
|
||
DefaultValue(false)]
|
||
public virtual bool TintSortColumn {
|
||
get { return this.tintSortColumn; }
|
||
set {
|
||
this.tintSortColumn = value;
|
||
if (value && this.PrimarySortColumn != null)
|
||
this.SelectedColumn = this.PrimarySortColumn;
|
||
else
|
||
this.SelectedColumn = null;
|
||
}
|
||
}
|
||
private bool tintSortColumn;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD>̬<EFBFBD><CCAC>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <20><><EFBFBD><EFBFBD>ΪTrue<75><65><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬(ͨ<><CDA8><EFBFBD>Dz<EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD>)<29><>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD>ѡ<EFBFBD>к<EFBFBD>ȡ<EFBFBD><C8A1>ѡ<EFBFBD><D1A1>֮<EFBFBD>佻<EFBFBD>浥<EFBFBD><E6B5A5><EFBFBD><EFBFBD>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ΪFalseʱ<65><CAB1>CheckStateGetter<65>Կ<EFBFBD><D4BF>Է<EFBFBD><D4B7>ز<EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD>
|
||
/// </remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD>̬<EFBFBD><CCAC>ѡ<EFBFBD><D1A1>"),
|
||
DefaultValue(false)]
|
||
public virtual bool TriStateCheckBoxes {
|
||
get { return triStateCheckBoxes; }
|
||
set {
|
||
triStateCheckBoxes = value;
|
||
if (value && !this.CheckBoxes)
|
||
this.CheckBoxes = true;
|
||
this.InitializeStateImageList();
|
||
}
|
||
}
|
||
private bool triStateCheckBoxes;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD><D4BD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD><CFB8>Ϣ<EFBFBD><CFA2>ͼ<EFBFBD><CDBC><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD>ʾ<EFBFBD><CABE>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>á<EFBFBD>
|
||
/// </para>
|
||
/// <para>
|
||
/// <20><>ʾ<EFBFBD><CABE>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD>ԭ<EFBFBD><D4AD><EFBFBD>ǣ<EFBFBD><C7A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD>۹<EFBFBD><DBB9><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD>Σ<EFBFBD>
|
||
/// Windows msg LVM_GETTOPINDEX<45><58><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>0<EFBFBD><30>
|
||
/// </para>
|
||
/// </remarks>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual int TopItemIndex {
|
||
get {
|
||
if (this.View == View.Details && this.IsHandleCreated)
|
||
return NativeMethods.GetTopIndex(this);
|
||
|
||
return -1;
|
||
}
|
||
set {
|
||
int newTopIndex = Math.Min(value, this.GetItemCount() - 1);
|
||
if (this.View != View.Details || newTopIndex < 0)
|
||
return;
|
||
|
||
try {
|
||
this.TopItem = this.Items[newTopIndex];
|
||
|
||
// Setting the TopItem sometimes gives off by one errors,
|
||
// that (bizarrely) are correct on a second attempt
|
||
if (this.TopItem != null && this.TopItem.Index != newTopIndex)
|
||
this.TopItem = this.GetItem(newTopIndex);
|
||
}
|
||
catch (NullReferenceException) {
|
||
// There is a bug in the .NET code where setting the TopItem
|
||
// will sometimes throw null reference exceptions
|
||
// There is nothing we can do to get around it.
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ý<EFBFBD><C3BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7>ᴥ<EFBFBD><E1B4A5>CellOver<65>¼<EFBFBD><C2BC><EFBFBD>
|
||
/// Ĭ<><C4AC>Ϊtrue<75><65>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><C6B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮ǰ<D6AE><C7B0><EFBFBD>ᴥ<EFBFBD><E1B4A5>CellOver<65>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD>ΪHeader<65><72><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD>Ŀؼ<C4BF><D8BC><EFBFBD>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD>ó<EFBFBD><C3B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>⣬<EFBFBD>뽫<EFBFBD><EBBDAB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ΪFalse<73><65>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֪<EFBFBD><D6AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>ڱ<EFBFBD><DAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><C6B6><EFBFBD><EFBFBD>뽫<EFBFBD><EBBDAB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊtrue(Ĭ<><C4AC>ֵ)<29><>
|
||
/// </remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ý<EFBFBD><C3BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7>ᴥ<EFBFBD><E1B4A5>CellOver<65>¼<EFBFBD><C2BC><EFBFBD>"),
|
||
DefaultValue(true)]
|
||
public bool TriggerCellOverEventsWhenOverHeader
|
||
{
|
||
get { return triggerCellOverEventsWhenOverHeader; }
|
||
set { triggerCellOverEventsWhenOverHeader = value; }
|
||
}
|
||
private bool triggerCellOverEventsWhenOverHeader = true;
|
||
|
||
/// <summary>
|
||
/// ͨ<><CDA8><EFBFBD>϶<EFBFBD><CFB6>ָ<EFBFBD><D6B8>ߵ<EFBFBD><DFB5><EFBFBD><EFBFBD>еĴ<D0B5>Сʱ<D0A1><CAB1><EFBFBD>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ո<EFBFBD><D5B8><EFBFBD><EFBFBD>еĴ<D0B5>С<EFBFBD><D0A1>
|
||
/// <20><><EFBFBD><EFBFBD>ΪFalse<73><65><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1><EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD>࣬<EFBFBD>⿴<EFBFBD><E2BFB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֣<EFBFBD><D6A3><EFBFBD><EFBFBD>е<EFBFBD><D0B5>ұ<EFBFBD>Ե<EFBFBD><D4B5><EFBFBD><EFBFBD><EFBFBD>϶<EFBFBD><CFB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڿռ<DABF><D5BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><b><3E><><EFBFBD><EFBFBD>Ե</b><3E><><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><C6B6><EFBFBD>
|
||
/// </para>
|
||
/// <para><3E><><EFBFBD>ǺϺ<C7BA><CFBA><EFBFBD><DFBC><EFBFBD><EFBFBD><EFBFBD>Ϊ--ֻ<>ǿ<EFBFBD><C7BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԡ<EFBFBD>
|
||
/// </para>
|
||
/// <para>
|
||
/// <20><><EFBFBD>ǵ<EFBFBD><C7B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>в<EFBFBD><D0B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ұߵ<D2B1><DFB5>У<EFBFBD><D0A3><EFBFBD><EFBFBD>ùرո<D8B1><D5B8><EFBFBD><EFBFBD>ԡ<EFBFBD></para>
|
||
/// </remarks>
|
||
[Category("ObjectListView"),
|
||
Description("ͨ<><CDA8><EFBFBD>϶<EFBFBD><CFB6>ָ<EFBFBD><D6B8>ߵ<EFBFBD><DFB5><EFBFBD><EFBFBD>еĴ<D0B5>Сʱ<D0A1><CAB1><EFBFBD>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ո<EFBFBD><D5B8><EFBFBD><EFBFBD>еĴ<D0B5>С"),
|
||
DefaultValue(true)]
|
||
public virtual bool UpdateSpaceFillingColumnsWhenDraggingColumnDivider {
|
||
get { return updateSpaceFillingColumnsWhenDraggingColumnDivider; }
|
||
set { updateSpaceFillingColumnsWhenDraggingColumnDivider = value; }
|
||
}
|
||
private bool updateSpaceFillingColumnsWhenDraggingColumnDivider = true;
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD>ؼ<EFBFBD>û<EFBFBD>н<EFBFBD><D0BD><EFBFBD>ʱ<EFBFBD><CAB1>Ӧ<EFBFBD><D3A6>ʹ<EFBFBD><CAB9>ʲô<CAB2><C3B4>ɫ<EFBFBD><C9AB>Ϊѡ<CEAA><D1A1><EFBFBD>еı<D0B5><C4B1><EFBFBD>
|
||
/// </summary>
|
||
[Category("ObjectListView"),
|
||
Description("<22><><EFBFBD>ؼ<EFBFBD>û<EFBFBD>н<EFBFBD><D0BD><EFBFBD>ʱ<EFBFBD><CAB1>Ӧ<EFBFBD><D3A6>ʹ<EFBFBD><CAB9>ʲô<CAB2><C3B4>ɫ<EFBFBD><C9AB>Ϊѡ<CEAA><D1A1><EFBFBD>еı<D0B5><C4B1><EFBFBD>"),
|
||
DefaultValue(typeof(Color), "")]
|
||
public virtual Color UnfocusedSelectedBackColor {
|
||
get { return this.unfocusedSelectedBackColor; }
|
||
set { this.unfocusedSelectedBackColor = value; }
|
||
}
|
||
private Color unfocusedSelectedBackColor = Color.Empty;
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD>ؼ<EFBFBD>û<EFBFBD>н<EFBFBD><D0BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><C4AC>ֵʱ<D6B5><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD>еı<D0B5><C4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ
|
||
/// </summary>
|
||
[Browsable(false)]
|
||
public virtual Color UnfocusedSelectedBackColorOrDefault {
|
||
get {
|
||
return this.UnfocusedSelectedBackColor.IsEmpty ? SystemColors.Control : this.UnfocusedSelectedBackColor;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
///<2F><><EFBFBD>ؼ<EFBFBD>û<EFBFBD>н<EFBFBD><D0BD><EFBFBD>ʱ<EFBFBD><CAB1>Ӧ<EFBFBD><D3A6>ʹ<EFBFBD><CAB9>ʲô<CAB2><C3B4>ɫ<EFBFBD><C9AB>Ϊѡ<CEAA><D1A1><EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB>
|
||
/// </summary>
|
||
[Category("ObjectListView"),
|
||
Description("<22><><EFBFBD>ؼ<EFBFBD>û<EFBFBD>н<EFBFBD><D0BD><EFBFBD>ʱ<EFBFBD><CAB1>Ӧ<EFBFBD><D3A6>ʹ<EFBFBD><CAB9>ʲô<CAB2><C3B4>ɫ<EFBFBD><C9AB>Ϊѡ<CEAA><D1A1><EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB>"),
|
||
DefaultValue(typeof(Color), "")]
|
||
public virtual Color UnfocusedSelectedForeColor {
|
||
get { return this.unfocusedSelectedForeColor; }
|
||
set { this.unfocusedSelectedForeColor = value; }
|
||
}
|
||
private Color unfocusedSelectedForeColor = Color.Empty;
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD>ؼ<EFBFBD>û<EFBFBD>н<EFBFBD><D0BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><C4AC>ֵʱ<D6B5><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ
|
||
/// </summary>
|
||
[Browsable(false)]
|
||
public virtual Color UnfocusedSelectedForeColorOrDefault {
|
||
get {
|
||
return this.UnfocusedSelectedForeColor.IsEmpty ? SystemColors.ControlText : this.UnfocusedSelectedForeColor;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1>Ƿ<EFBFBD>ÿ<EFBFBD><C3BF>һ<EFBFBD><D2BB><EFBFBD>ṩ<EFBFBD><E1B9A9>ͬ<EFBFBD>ı<EFBFBD><C4B1><EFBFBD>ɫ<EFBFBD><C9AB>Ĭ<EFBFBD><C4AC>ֵΪfalse<73><65>
|
||
/// </summary>
|
||
/// <remarks><para><3E><><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><D0B5><EFBFBD>ɫ<EFBFBD><C9AB>AlternateRowBackColor<6F>ṩ<EFBFBD><E1B9A9></para>
|
||
/// <para><3E><>.NET<45>У<EFBFBD><D0A3>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD>ڷ<EFBFBD><DAB7><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1>ģʽ<C4A3><CABD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܡ<EFBFBD><DCA1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ<C4A3>£<EFBFBD><C2A3><EFBFBD>ѡ<EFBFBD>в<EFBFBD><D0B2><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD>ȷ<EFBFBD>ı<EFBFBD><C4B1><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD>ơ<EFBFBD></para></remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1>Ƿ<EFBFBD>ÿ<EFBFBD><C3BF>һ<EFBFBD><D2BB><EFBFBD>ṩ<EFBFBD><E1B9A9>ͬ<EFBFBD>ı<EFBFBD><C4B1><EFBFBD>ɫ<EFBFBD><C9AB>Ĭ<EFBFBD><C4AC>ֵΪfalse<73><65>"),
|
||
DefaultValue(false)]
|
||
public virtual bool UseAlternatingBackColors {
|
||
get { return useAlternatingBackColors; }
|
||
set { useAlternatingBackColors = value; }
|
||
}
|
||
private bool useAlternatingBackColors;
|
||
|
||
/// <summary>
|
||
/// <20>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6>Ϊ<EFBFBD>ؼ<EFBFBD><D8BC>е<EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>FormatCell<6C>¼<EFBFBD><C2BC><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>£<EFBFBD><C2A3><EFBFBD>ִ<EFBFBD>е<EFBFBD>Ԫ<EFBFBD><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD>á<EFBFBD>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA>ObjectListView<65><77><EFBFBD><EFBFBD>Ϊÿ<CEAA><C3BF><EFBFBD><EFBFBD>Ԫ<EFBFBD><EFBFBD>Format Cell<6C>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٶȻ<D9B6><C8BB>Կ<EFBFBD>һЩ<D2BB><D0A9>
|
||
/// <20><><EFBFBD>ˣ<EFBFBD>Ĭ<EFBFBD><C4AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>£<EFBFBD><C2A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊÿ<CEAA><C3BF><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD>
|
||
/// </para>
|
||
/// <para>ObjectListView*ȷʵ*<2A><>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>FormatRow<6F>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>п<EFBFBD><D0BF>Ծ<EFBFBD><D4BE><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>FormatCell<6C>¼<EFBFBD><C2BC><EFBFBD>
|
||
/// </para>
|
||
/// <para>
|
||
/// <20><><EFBFBD>۴<EFBFBD><DBB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Σ<EFBFBD>ֻ<EFBFBD>е<EFBFBD>ObjectListView<65><77><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD><CFB8>ͼ<EFBFBD><CDBC>ʱ<EFBFBD>Ż<EFBFBD><C5BB><EFBFBD><EFBFBD><EFBFBD>FormatCell<6C>¼<EFBFBD><C2BC><EFBFBD></para>
|
||
/// </remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6>Ϊ<EFBFBD>ؼ<EFBFBD><D8BC>е<EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>FormatCell<6C>¼<EFBFBD>"),
|
||
DefaultValue(false)]
|
||
public bool UseCellFormatEvents {
|
||
get { return useCellFormatEvents; }
|
||
set { useCellFormatEvents = value; }
|
||
}
|
||
private bool useCellFormatEvents;
|
||
|
||
/// <summary>
|
||
/// <20><>ѡ<EFBFBD><D1A1><EFBFBD>Ƿ<EFBFBD>Ӧʹ<D3A6>÷DZ<C3B7>ǰ<D7BC><C7B0>ɫ<EFBFBD>ͱ<EFBFBD><CDB1><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD>ƣ<EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>V2.9<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ѡ<EFBFBD><D1A1><EFBFBD>Ƿ<EFBFBD>Ӧʹ<D3A6>÷DZ<C3B7>ǰ<D7BC><C7B0>ɫ<EFBFBD>ͱ<EFBFBD><CDB1><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD>"),
|
||
DefaultValue(false)]
|
||
public bool UseCustomSelectionColors {
|
||
get { return false; }
|
||
// ReSharper disable once ValueParameterNotUsed
|
||
set { }
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD>ObjectListView<65>Ƿ<EFBFBD><C7B7><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD>Vista<74><61>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD>ơ<EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȱ<EFBFBD>ݣ<EFBFBD>
|
||
/// <list type="bullet">
|
||
/// <item><description><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Vista<74><61><EFBFBD><EFBFBD><EFBFBD>߰汾</description></item>
|
||
/// <item><description><3E><><EFBFBD><EFBFBD><EFBFBD>ܺܺõ<DCBA><C3B5><EFBFBD>AlternateRowBackColors<72><73><EFBFBD><EFBFBD>ʹ<EFBFBD>á<EFBFBD></description></item>
|
||
/// <item><description><3E><><EFBFBD><EFBFBD><EFBFBD>ܺܺõ<DCBA><C3B5><EFBFBD>HotItemStyles<65><73><EFBFBD><EFBFBD>ʹ<EFBFBD>á<EFBFBD></description></item>
|
||
/// <item><description><3E><><EFBFBD><EFBFBD>FullRowSelectΪfalse<73><65><EFBFBD>⿴<EFBFBD><E2BFB4><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>ɵ<EFBFBD><C9B5></description></item>
|
||
/// <item><description><3E><><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><DFBB>Ƶ<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<28><>Ϊ<EFBFBD><CEAA><EFBFBD>еĻ<D0B5><C4BB>ƶ<EFBFBD><C6B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ⱦ<EFBFBD><C8BE><EFBFBD><EFBFBD><EFBFBD>ɵ<EFBFBD>)<29><>
|
||
/// <20><><EFBFBD>ˣ<EFBFBD><CBA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>TreeListViewһ<77><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD>ǡ<EFBFBD><C7A1><EFBFBD><EFBFBD>롱<EFBFBD><EBA1B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><DFBB>Ƶġ<C6B5><C4A1><EFBFBD><EFBFBD><EFBFBD>Ȼ<EFBFBD><C8BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7></description></item>
|
||
/// </list>
|
||
///<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Vista/Win7<6E><37><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD>ޡ<EFBFBD><DEA1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ø<EFBFBD><C3B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>飬<EFBFBD>벻Ҫ<EBB2BB><D2AA>Թ<EFBFBD><D4B9>
|
||
/// </para>
|
||
/// <para>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ΪTrueʱ<65><CAB1>ObjectListView<65><77><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ġ<EFBFBD>
|
||
/// <20>⽫<EFBFBD><E2BDAB><EFBFBD><EFBFBD>ObjectListView<65><77><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ư<EFBFBD><C6AF><EFBFBD>Ļ<EFBFBD><C4BB>ڻ<EFBFBD>ͼ<EFBFBD>Ĺ<EFBFBD><C4B9>ܡ<EFBFBD>
|
||
/// </para>
|
||
/// </remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD>ObjectListView<65>Ƿ<EFBFBD><C7B7><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD>Vista<74><61>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"),
|
||
DefaultValue(false)]
|
||
public bool UseExplorerTheme {
|
||
get { return useExplorerTheme; }
|
||
set {
|
||
useExplorerTheme = value;
|
||
if (this.Created)
|
||
NativeMethods.SetWindowTheme(this.Handle, value ? "explorer" : "", null);
|
||
|
||
this.OwnerDraw = !value;
|
||
}
|
||
}
|
||
private bool useExplorerTheme;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>ɸѡ
|
||
/// </summary>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>ɸѡ"),
|
||
DefaultValue(false)]
|
||
virtual public bool UseFiltering {
|
||
get { return useFiltering; }
|
||
set {
|
||
if (useFiltering == value)
|
||
return;
|
||
useFiltering = value;
|
||
this.UpdateFiltering();
|
||
}
|
||
}
|
||
private bool useFiltering;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6>ָʾ<D6B8><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>еı<D0B5><C4B1><EFBFBD><EFBFBD>У<EFBFBD><D0A3>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɸѡ<C9B8><D1A1><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊtrue<75><65>HeaderUsesThemes<65><73><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD>Ϊfalse<73><65><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>ֻ<EFBFBD><D6BB><EFBFBD>ڲ<EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>ɸѡ<C9B8><D1A1>ָʾ<D6B8><CABE><EFBFBD><EFBFBD></remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6>ָʾ<D6B8><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>еı<D0B5><C4B1><EFBFBD><EFBFBD>У<EFBFBD><D0A3>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɸѡ<C9B8><D1A1><EFBFBD><EFBFBD>"),
|
||
DefaultValue(false)]
|
||
virtual public bool UseFilterIndicator {
|
||
get { return useFilterIndicator; }
|
||
set {
|
||
if (this.useFilterIndicator == value)
|
||
return;
|
||
useFilterIndicator = value;
|
||
if (this.useFilterIndicator)
|
||
this.HeaderUsesThemes = false;
|
||
this.Invalidate();
|
||
}
|
||
}
|
||
private bool useFilterIndicator;
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><C2B7>Ŀؼ<C4BF>(<28><>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ť)<29>Ƿ<EFBFBD>Ӧ<EFBFBD>ñ<EFBFBD><C3B1><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>Hot<6F><74>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para><3E><><EFBFBD><EFBFBD>ΪFalse<73><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD>ڿؼ<DABF><D8BC><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>ؼ<EFBFBD><D8BC>Ļ<EFBFBD><C4BB>Ʒ<EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC></para>
|
||
/// <para>
|
||
/// <20><><EFBFBD><EFBFBD>ΪFalse<73><65><EFBFBD><EFBFBD>UseHotItem<65><6D>UseHyperLinksΪFalse<73><65><EFBFBD><EFBFBD>ObjectListView<65><77><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><C6B6><EFBFBD>ijЩ<C4B3><D0A9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><C6B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9>CPU<50><55>
|
||
/// </para>
|
||
/// </remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22><><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><C2B7>Ŀؼ<C4BF>(<28><>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ť)<29>Ƿ<EFBFBD>Ӧ<EFBFBD>ñ<EFBFBD><C3B1><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>Hot<6F><74>"),
|
||
DefaultValue(true)]
|
||
public bool UseHotControls {
|
||
get { return this.useHotControls; }
|
||
set { this.useHotControls = value; }
|
||
}
|
||
private bool useHotControls = true;
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD><C2B5><EFBFBD><EFBFBD>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD>ⷽʽ<E2B7BD><CABD><EFBFBD>ø<EFBFBD>ʽ<EFBFBD><CABD>
|
||
/// </summary>
|
||
[Category("ObjectListView"),
|
||
Description("<22><><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD><C2B5><EFBFBD><EFBFBD>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD>ⷽʽ<E2B7BD><CABD><EFBFBD>ø<EFBFBD>ʽ"),
|
||
DefaultValue(false)]
|
||
public bool UseHotItem {
|
||
get { return this.useHotItem; }
|
||
set {
|
||
this.useHotItem = value;
|
||
if (value)
|
||
this.AddOverlay(this.HotItemStyleOrDefault.Overlay);
|
||
else
|
||
this.RemoveOverlay(this.HotItemStyleOrDefault.Overlay);
|
||
}
|
||
}
|
||
private bool useHotItem;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><C3B4>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD>Ƿ<EFBFBD>Ӧ<EFBFBD>ڵ<EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD>ӡ<EFBFBD>
|
||
/// </summary>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><C3B4>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD>Ƿ<EFBFBD>Ӧ<EFBFBD>ڵ<EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"),
|
||
DefaultValue(false)]
|
||
public bool UseHyperlinks {
|
||
get { return this.useHyperlinks; }
|
||
set {
|
||
this.useHyperlinks = value;
|
||
if (value && this.HyperlinkStyle == null)
|
||
this.HyperlinkStyle = new HyperlinkStyle();
|
||
}
|
||
}
|
||
private bool useHyperlinks;
|
||
|
||
/// <summary>
|
||
/// <20>˿ؼ<CBBF><D8BC>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD>(Overlays)
|
||
/// </summary>
|
||
/// <remarks><3E><><EFBFBD><EFBFBD>(Overlays)<29><>Ĭ<EFBFBD><C4AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õģ<C3B5>ֻ<EFBFBD><D6BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>á<EFBFBD></remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22>˿ؼ<CBBF><D8BC>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD>(Overlays)"),
|
||
DefaultValue(true)]
|
||
public bool UseOverlays {
|
||
get { return this.useOverlays; }
|
||
set { this.useOverlays = value; }
|
||
}
|
||
private bool useOverlays = true;
|
||
|
||
/// <summary>
|
||
/// <20>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD>˿ؼ<CBBF><D8BC><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ΪTrue<75><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>ÿؼ<C3BF><D8BC>ṩһ<E1B9A9><D2BB>SmallImageList(<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB>һ<EFBFBD><D2BB>SmallImageList)<29><>
|
||
/// <20><><EFBFBD>⣬<EFBFBD><E2A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>»<EFBFBD><C2BB>Ƹ<EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD></remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD>˿ؼ<CBBF><D8BC><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD>"),
|
||
DefaultValue(false)]
|
||
public bool UseSubItemCheckBoxes {
|
||
get { return this.useSubItemCheckBoxes; }
|
||
set {
|
||
this.useSubItemCheckBoxes = value;
|
||
if (value)
|
||
this.SetupSubItemCheckBoxes();
|
||
}
|
||
}
|
||
private bool useSubItemCheckBoxes;
|
||
|
||
/// <summary>
|
||
///<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ObjectListView<65>Ƿ<EFBFBD><C7B7><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Vista<74>İ<EFBFBD><EFBFBD><CDB8>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD>ơ<EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// <20><>UseExplorerTheme<6D><65>ͬ<EFBFBD><CDAC><EFBFBD>ǣ<EFBFBD><C7A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Vista<74>ķ<EFBFBD><C4B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>XP<58><50><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD>Ҽ<EFBFBD><D2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD><EFBFBD>ڷ<EFBFBD><DAB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>
|
||
/// </para>
|
||
/// <para>
|
||
///<2F>⽫<EFBFBD>滻<EFBFBD>κ<EFBFBD><CEBA>Ѱ<EFBFBD>װ<EFBFBD><D7B0>SelectedRowDecory<72><79>
|
||
/// </para>
|
||
/// <para>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϲ<EFBFBD><CFB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD>ԣ<EFBFBD>
|
||
/// ֻ<>贴<EFBFBD><E8B4B4><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><D4BC><EFBFBD>RowBorderDecory<72><79><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>SelectedRowDecory<72><79>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </para>
|
||
/// </remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ObjectListView<65>Ƿ<EFBFBD><C7B7><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Vista<74>İ<EFBFBD><EFBFBD><CDB8>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"),
|
||
DefaultValue(false)]
|
||
public bool UseTranslucentSelection {
|
||
get { return useTranslucentSelection; }
|
||
set {
|
||
useTranslucentSelection = value;
|
||
if (value) {
|
||
RowBorderDecoration rbd = new RowBorderDecoration();
|
||
rbd.BorderPen = new Pen(Color.FromArgb(154, 223, 251));
|
||
rbd.FillBrush = new SolidBrush(Color.FromArgb(48, 163, 217, 225));
|
||
rbd.BoundsPadding = new Size(0, 0);
|
||
rbd.CornerRounding = 6.0f;
|
||
this.SelectedRowDecoration = rbd;
|
||
} else
|
||
this.SelectedRowDecoration = null;
|
||
}
|
||
}
|
||
private bool useTranslucentSelection;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ObjectListView<65>Ƿ<EFBFBD><C7B7><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Vista<74>İ<EFBFBD><EFBFBD><CDB8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD>ơ<EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// <20><><EFBFBD>ô<EFBFBD><C3B4><EFBFBD>滻<EFBFBD>κ<EFBFBD><CEBA>Ѱ<EFBFBD>װ<EFBFBD><D7B0>HotItemStyle<6C><65>
|
||
/// </para>
|
||
/// <para>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϲ<EFBFBD><CFB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀʹ<C4BF>õ<EFBFBD><C3B5><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD>ԣ<EFBFBD>
|
||
/// ֻ<>贴<EFBFBD><E8B4B4><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><D4BC><EFBFBD>HotItemStyle<6C><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>HotItemStyle<6C><65><EFBFBD>ԣ<EFBFBD><D4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </para>
|
||
/// </remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ObjectListView<65>Ƿ<EFBFBD><C7B7><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Vista<74>İ<EFBFBD><EFBFBD><CDB8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD>ơ<EFBFBD>"),
|
||
DefaultValue(false)]
|
||
public bool UseTranslucentHotItem {
|
||
get { return useTranslucentHotItem; }
|
||
set {
|
||
useTranslucentHotItem = value;
|
||
if (value) {
|
||
RowBorderDecoration rbd = new RowBorderDecoration();
|
||
rbd.BorderPen = new Pen(Color.FromArgb(154, 223, 251));
|
||
rbd.BoundsPadding = new Size(0, 0);
|
||
rbd.CornerRounding = 6.0f;
|
||
rbd.FillGradientFrom = Color.FromArgb(0, 255, 255, 255);
|
||
rbd.FillGradientTo = Color.FromArgb(64, 183, 237, 240);
|
||
HotItemStyle his = new HotItemStyle();
|
||
his.Decoration = rbd;
|
||
this.HotItemStyle = his;
|
||
} else
|
||
this.HotItemStyle = null;
|
||
this.UseHotItem = value;
|
||
}
|
||
}
|
||
private bool useTranslucentHotItem;
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ/<2F><><EFBFBD>ô<EFBFBD><C3B4>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD>ʹ<EFBFBD>õ<EFBFBD><C3B5><EFBFBD>ͼ<EFBFBD><CDBC>ʽ
|
||
/// </summary>
|
||
/// <remarks><3E>л<EFBFBD><D0BB><EFBFBD>ƽ<EFBFBD><C6BD>(Tile)<29><><EFBFBD><EFBFBD>ϸ<EFBFBD><CFB8>Ϣ(Details)<29><>ͼ<EFBFBD>ᰲװ<E1B0B2>ʺϸ<CABA><CFB8><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><C7A3><EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD>ͼ<EFBFBD>У<EFBFBD>ÿ<EFBFBD>ж<EFBFBD><D0B6><EFBFBD>ʾΪһ<CEAA><D2BB><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2></remarks>
|
||
[Category("Appearance"),
|
||
Description("<22><>ȡ/<2F><><EFBFBD>ô<EFBFBD><C3B4>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD>ʹ<EFBFBD>õ<EFBFBD><C3B5><EFBFBD>ͼ<EFBFBD><CDBC>ʽ"),
|
||
DefaultValue(null)]
|
||
new public View View
|
||
{
|
||
get { return base.View; }
|
||
set {
|
||
if (base.View == value)
|
||
return;
|
||
|
||
if (this.Frozen) {
|
||
base.View = value;
|
||
this.SetupBaseImageList();
|
||
} else {
|
||
this.Freeze();
|
||
|
||
if (value == View.Tile)
|
||
this.CalculateReasonableTileSize();
|
||
|
||
base.View = value;
|
||
this.SetupBaseImageList();
|
||
this.Unfreeze();
|
||
}
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Callbacks
|
||
|
||
/// <summary>
|
||
/// <20><>ί<EFBFBD>н<EFBFBD><D0BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5>ȡ<EFBFBD><C8A1>
|
||
/// </summary>
|
||
/// <remarks><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD>뵣<EFBFBD>IJ<EFBFBD>ȷ<EFBFBD><C8B7>״̬(<28><><EFBFBD><EFBFBD><EFBFBD>൱<EFBFBD><E0B5B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)<29><><EFBFBD><EFBFBD>ʹ<EFBFBD>ô<EFBFBD>ѡ<EFBFBD>
|
||
/// <para>
|
||
/// <20><><EFBFBD><EFBFBD>CheckStateGetter<65><72><EFBFBD>Եı<D4B5><C4B1>ݰ<EFBFBD>װ<EFBFBD><D7B0>
|
||
/// </para>
|
||
/// </remarks>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual BooleanCheckStateGetterDelegate BooleanCheckStateGetter {
|
||
set {
|
||
if (value == null)
|
||
this.CheckStateGetter = null;
|
||
else
|
||
this.CheckStateGetter = delegate(Object x) {
|
||
return value(x) ? CheckState.Checked : CheckState.Unchecked;
|
||
};
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// This delegate sets the checkedness of an object as a boolean only. It must return
|
||
/// true or false indicating if the object was checked or not.
|
||
/// </summary>
|
||
/// <remarks>Use this if you never want to worry about the
|
||
/// Indeterminate state (which is fairly common).
|
||
/// <para>
|
||
/// This is a convenience wrapper around the CheckStatePutter property.
|
||
/// </para>
|
||
/// </remarks>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual BooleanCheckStatePutterDelegate BooleanCheckStatePutter {
|
||
set {
|
||
if (value == null)
|
||
this.CheckStatePutter = null;
|
||
else
|
||
this.CheckStatePutter = delegate(Object x, CheckState state) {
|
||
bool isChecked = (state == CheckState.Checked);
|
||
return value(x, isChecked) ? CheckState.Checked : CheckState.Unchecked;
|
||
};
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD>Ƿ<EFBFBD><C7B7>ܹ<EFBFBD><DCB9><EFBFBD>ʾ<EFBFBD><CABE>
|
||
/// </summary>
|
||
[Browsable(false)]
|
||
public virtual bool CanShowGroups {
|
||
get {
|
||
return true;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ObjectListView<65>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Application.Idle<6C>¼<EFBFBD><C2BC><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks><3E><>ijЩ<C4B3><D0A9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<28><><EFBFBD>磬<EFBFBD><E7A3AC>VisualStudio<69><6F>Office<63><65><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>չ<EFBFBD><D5B9><EFBFBD><EFBFBD>ʱ)<29><><EFBFBD>Ӳ<EFBFBD><D3B2><EFBFBD><EFBFBD><EFBFBD>Application.Idle<6C>¼<EFBFBD><C2BC><EFBFBD>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Idle<6C>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ΪFalse<73><65>ObjectListView<65><77><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Щ<EFBFBD>¼<EFBFBD><C2BC><EFBFBD>
|
||
/// </remarks>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual bool CanUseApplicationIdle {
|
||
get { return this.canUseApplicationIdle; }
|
||
set { this.canUseApplicationIdle = value; }
|
||
}
|
||
private bool canUseApplicationIdle = true;
|
||
|
||
/// <summary>
|
||
/// This delegate fetches the renderer for a particular cell.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// If this returns null (or is not installed), the renderer for the column will be used.
|
||
/// If the column renderer is null, then <seealso cref="DefaultRenderer"/> will be used.
|
||
/// </para>
|
||
/// <para>
|
||
/// This is called every time any cell is drawn. It must be efficient!
|
||
/// </para>
|
||
/// </remarks>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual CellRendererGetterDelegate CellRendererGetter
|
||
{
|
||
get { return this.cellRendererGetter; }
|
||
set { this.cellRendererGetter = value; }
|
||
}
|
||
private CellRendererGetterDelegate cellRendererGetter;
|
||
|
||
/// <summary>
|
||
/// This delegate is called when the list wants to show a tooltip for a particular cell.
|
||
/// The delegate should return the text to display, or null to use the default behavior
|
||
/// (which is to show the full text of truncated cell values).
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Displaying the full text of truncated cell values only work for FullRowSelect listviews.
|
||
/// This is MS's behavior, not mine. Don't complain to me :)
|
||
/// </remarks>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual CellToolTipGetterDelegate CellToolTipGetter {
|
||
get { return cellToolTipGetter; }
|
||
set { cellToolTipGetter = value; }
|
||
}
|
||
private CellToolTipGetterDelegate cellToolTipGetter;
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD>ѡ<EFBFBD><D1A1>ģ<EFBFBD>͵<EFBFBD><CDB5><EFBFBD><EFBFBD><EFBFBD>(<28><><EFBFBD>ֶ<EFBFBD>)<29><><EFBFBD><EFBFBD><EFBFBD>ơ<EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǿ<EFBFBD><C7BF>ĵġ<C4B5><C4A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>bool(<28><>bool<6F><6C>)<29><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͡<EFBFBD><CDA1><EFBFBD><EFBFBD><EFBFBD>TriStateCheckBooksΪ<73><CEAA>)<29><></para>
|
||
/// <para><3E><><EFBFBD>ô<EFBFBD><C3B4><EFBFBD><EFBFBD>Խ<EFBFBD><D4BD>滻<EFBFBD>κ<EFBFBD><CEBA>Ѱ<EFBFBD>װ<EFBFBD><D7B0>CheckStateGetter<65><72>CheckStatePutter<65><72>
|
||
/// <20>෴<EFBFBD><E0B7B4><EFBFBD>Ժ<EFBFBD><D4BA><EFBFBD><EFBFBD><EFBFBD>CheckStateGetter<65><72>CheckStatePutter<65><72><EFBFBD>Խ<EFBFBD><D4BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD>Ե<EFBFBD><D4B5><EFBFBD>Ϊ<EFBFBD><CEAA></para>
|
||
/// </remarks>
|
||
[Category("ObjectListView"),
|
||
Description("<22><><EFBFBD><EFBFBD>ģ<EFBFBD>͵ġ<CDB5><C4A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԡ<EFBFBD><D4A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ի<EFBFBD><D4BB>ֶε<D6B6><CEB5><EFBFBD><EFBFBD><EFBFBD>"),
|
||
DefaultValue(null)]
|
||
public virtual string CheckedAspectName {
|
||
get { return checkedAspectName; }
|
||
set {
|
||
checkedAspectName = value;
|
||
if (String.IsNullOrEmpty(checkedAspectName)) {
|
||
this.checkedAspectMunger = null;
|
||
this.CheckStateGetter = null;
|
||
this.CheckStatePutter = null;
|
||
} else {
|
||
this.checkedAspectMunger = new Munger(checkedAspectName);
|
||
this.CheckStateGetter = delegate(Object modelObject) {
|
||
bool? result = this.checkedAspectMunger.GetValue(modelObject) as bool?;
|
||
if (result.HasValue)
|
||
return result.Value ? CheckState.Checked : CheckState.Unchecked;
|
||
return this.TriStateCheckBoxes ? CheckState.Indeterminate : CheckState.Unchecked;
|
||
};
|
||
this.CheckStatePutter = delegate(Object modelObject, CheckState newValue) {
|
||
if (this.TriStateCheckBoxes && newValue == CheckState.Indeterminate)
|
||
this.checkedAspectMunger.PutValue(modelObject, null);
|
||
else
|
||
this.checkedAspectMunger.PutValue(modelObject, newValue == CheckState.Checked);
|
||
return this.CheckStateGetter(modelObject);
|
||
};
|
||
}
|
||
}
|
||
}
|
||
private string checkedAspectName;
|
||
private Munger checkedAspectMunger;
|
||
|
||
/// <summary>
|
||
/// ֻҪObjectListView<65><77>Ҫ֪<D2AA><D6AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>еļ<D0B5><C4BC><EFBFBD>״̬<D7B4><CCAC><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD>ô<EFBFBD>ί<EFBFBD>С<EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>.NET has no support for indeterminate values, but as of v2.0, this class allows
|
||
/// indeterminate values.</para>
|
||
/// </remarks>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual CheckStateGetterDelegate CheckStateGetter {
|
||
get { return checkStateGetter; }
|
||
set { checkStateGetter = value; }
|
||
}
|
||
private CheckStateGetterDelegate checkStateGetter;
|
||
|
||
/// <summary>
|
||
/// This delegate will be called whenever the user tries to change the check state of a row.
|
||
/// The delegate should return the state that was actually set, which may be different
|
||
/// to the state given.
|
||
/// </summary>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual CheckStatePutterDelegate CheckStatePutter {
|
||
get { return checkStatePutter; }
|
||
set { checkStatePutter = value; }
|
||
}
|
||
private CheckStatePutterDelegate checkStatePutter;
|
||
|
||
/// <summary>
|
||
/// <20><>ί<EFBFBD>п<EFBFBD><D0BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6>巽ʽ<E5B7BD>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
///ί<>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD>ObjectListView<65>ϰ<EFBFBD>װListViewItemSorter<65><72>
|
||
///<2F><>װItemSorter<65><72>ִ<EFBFBD>ж<EFBFBD>ListViewItems<6D><73><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD>
|
||
///<2F>й<EFBFBD>ItemSorter<65><72><EFBFBD><EFBFBD>ִ<EFBFBD>еIJ<D0B5><C4B2><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>μ<EFBFBD><CEBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>ColumnCompeller<65><72>
|
||
/// </para>
|
||
/// <para>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>VirtualObjectListView<65>ϰ<EFBFBD>װCustomSorter<65><72><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>дIVirtualListDataSource<63><65>SortObjects()<29><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </para>
|
||
/// </remarks>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual SortDelegate CustomSorter {
|
||
get { return customSorter; }
|
||
set { customSorter = value; }
|
||
}
|
||
private SortDelegate customSorter;
|
||
|
||
/// <summary>
|
||
/// This delegate is called when the list wants to show a tooltip for a particular header.
|
||
/// The delegate should return the text to display, or null to use the default behavior
|
||
/// (which is to not show any tooltip).
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// Installing a HeaderToolTipGetter takes precedence over any text in OLVColumn.ToolTipText.
|
||
/// </remarks>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual HeaderToolTipGetterDelegate HeaderToolTipGetter {
|
||
get { return headerToolTipGetter; }
|
||
set { headerToolTipGetter = value; }
|
||
}
|
||
private HeaderToolTipGetterDelegate headerToolTipGetter;
|
||
|
||
/// <summary>
|
||
/// This delegate can be used to format a OLVListItem before it is added to the control.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>The model object for the row can be found through the RowObject property of the OLVListItem object.</para>
|
||
/// <para>All subitems normally have the same style as list item, so setting the forecolor on one
|
||
/// subitem changes the forecolor of all subitems.
|
||
/// To allow subitems to have different attributes, do this:
|
||
/// <code>myListViewItem.UseItemStyleForSubItems = false;</code>.
|
||
/// </para>
|
||
/// <para>If UseAlternatingBackColors is true, the backcolor of the listitem will be calculated
|
||
/// by the control and cannot be controlled by the RowFormatter delegate.
|
||
/// In general, trying to use a RowFormatter
|
||
/// when UseAlternatingBackColors is true does not work well.</para>
|
||
/// <para>As it says in the summary, this is called <b>before</b> the item is added to the control.
|
||
/// Many properties of the OLVListItem itself are not available at that point, including:
|
||
/// Index, Selected, Focused, Bounds, Checked, DisplayIndex.</para>
|
||
/// </remarks>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual RowFormatterDelegate RowFormatter {
|
||
get { return rowFormatter; }
|
||
set { rowFormatter = value; }
|
||
}
|
||
private RowFormatterDelegate rowFormatter;
|
||
|
||
#endregion
|
||
|
||
#region List commands
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><D3B5>˿ؼ<CBBF><D8BC><EFBFBD>
|
||
/// </summary>
|
||
/// <param name="modelObject">Ҫ<><D2AA>ʾ<EFBFBD><CABE>ģ<EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD></param>
|
||
/// <remarks>See AddObjects() for more details</remarks>
|
||
public virtual void AddObject(object modelObject) {
|
||
if (this.InvokeRequired)
|
||
this.Invoke((MethodInvoker)delegate() { this.AddObject(modelObject); });
|
||
else
|
||
this.AddObjects(new object[] { modelObject });
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD><F3BCAFBA><EFBFBD><EFBFBD>ӵ<EFBFBD><D3B5>˿ؼ<CBBF><D8BC><EFBFBD>
|
||
/// </summary>
|
||
/// <param name="modelObjects">Ҫ<><D2AA>ʾ<EFBFBD><CABE>ģ<EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD></param>
|
||
/// <remarks>
|
||
/// <para><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڻ״̬(<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>PrimarySortColumn<6D><6E>Ϊ<EFBFBD><CEAA>)<29><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵĶ<D3B5><C4B6><EFBFBD><F3BDABB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD>á<EFBFBD><C3A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǽ<EFBFBD><C7BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ĩβ<C4A9><CEB2></para>
|
||
/// <para><3E><>ִ<EFBFBD><D6B4><EFBFBD>κμ<CEBA><CEBC><EFBFBD><EFBFBD>Բ鿴<D4B2>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>κζ<CEBA><CEB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ListView<65>С<EFBFBD></para>
|
||
/// <para><3E>ն<EFBFBD><D5B6><EFBFBD><F3BDABB1><EFBFBD>Ĭ<EFBFBD><C4AC><EFBFBD>ԡ<EFBFBD></para>
|
||
/// </remarks>
|
||
public virtual void AddObjects(ICollection modelObjects) {
|
||
if (this.InvokeRequired) {
|
||
this.Invoke((MethodInvoker)delegate() { this.AddObjects(modelObjects); });
|
||
return;
|
||
}
|
||
this.InsertObjects(ObjectListView.EnumerableCount(this.Objects), modelObjects);
|
||
this.Sort(this.PrimarySortColumn, this.PrimarySortOrder);
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD>еĴ<D0B5>С<EFBFBD><D0A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳü<D2B3><C3BC><EFBFBD>Ⱥ<EFBFBD><C8BA><EFBFBD><EFBFBD>ݵ<EFBFBD><DDB5><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5>
|
||
/// </summary>
|
||
public virtual void AutoResizeColumns() {
|
||
foreach (OLVColumn c in this.Columns) {
|
||
this.AutoResizeColumn(c.Index, ColumnHeaderAutoResizeStyle.HeaderSize);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD>κ<EFBFBD><CEBA>Զ<EFBFBD><D4B6><EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD>п<EFBFBD>(<28><><EFBFBD><EFBFBD>Ϊ0<CEAA><30>-1<><31><EFBFBD>н<EFBFBD><D0BD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><DDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD>)<29><>
|
||
/// </summary>
|
||
/// <remarks>
|
||
///<2F><>Ȼ<EFBFBD><C8BB><EFBFBD><EFBFBD>ֻ<EFBFBD><D6BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>Ρ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><D0A3>п<EFBFBD><D0BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>ֵ(<28><><EFBFBD><EFBFBD>0<EFBFBD><30>-1)<29><><EFBFBD><EFBFBD><EFBFBD>˵ڶ<CBB5><DAB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4><EFBFBD>κβ<CEBA><CEB2><EFBFBD><EFBFBD><EFBFBD>
|
||
///<2F><>Ҫǿ<D2AA><C7BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>и<EFBFBD><D0B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><see cref="AutoResizeColumns()"/> <20><>
|
||
/// </remarks>
|
||
public virtual void AutoSizeColumns() {
|
||
// If we are supposed to resize to content, but if there is no content,
|
||
// resize to the header size instead.
|
||
ColumnHeaderAutoResizeStyle resizeToContentStyle = this.GetItemCount() == 0 ?
|
||
ColumnHeaderAutoResizeStyle.HeaderSize :
|
||
ColumnHeaderAutoResizeStyle.ColumnContent;
|
||
foreach (ColumnHeader column in this.Columns) {
|
||
switch (column.Width) {
|
||
case 0:
|
||
this.AutoResizeColumn(column.Index, resizeToContentStyle);
|
||
break;
|
||
case -1:
|
||
this.AutoResizeColumn(column.Index, ColumnHeaderAutoResizeStyle.HeaderSize);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><D0BB><EFBFBD>һ<EFBFBD><D2BB>(<28><><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)<29><><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD>֯<EFBFBD><D6AF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
public virtual void BuildGroups() {
|
||
this.BuildGroups(this.PrimarySortColumn, this.PrimarySortOrder == SortOrder.None ? SortOrder.Ascending : this.PrimarySortOrder);
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD>ݸ<EFBFBD><DDB8><EFBFBD><EFBFBD>н<EFBFBD><D0BD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD>֯<EFBFBD><D6AF><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// <20><><EFBFBD><EFBFBD>AlwaysGroupByColumn<6D><6E><EFBFBD>Բ<EFBFBD>ΪNull<6C><6C><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD><EFBFBD><EEBDAB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֯<EFBFBD><D6AF><EFBFBD><EFBFBD><EFBFBD>ҽ<EFBFBD><D2BD><EFBFBD><EFBFBD>ԡ<EFBFBD>Column<6D><6E><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </para>
|
||
/// <para><3E>˷<EFBFBD><CBB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD>BeforeSorting<6E><67>AfterSorting<6E><67></para>
|
||
/// </remarks>
|
||
/// <param name="column"><3E><>ֵӦ<D6B5><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD></param>
|
||
/// <param name="order"></param>
|
||
public virtual void BuildGroups(OLVColumn column, SortOrder order) {
|
||
// Sanity
|
||
if (this.GetItemCount() == 0 || this.Columns.Count == 0)
|
||
return;
|
||
|
||
BeforeSortingEventArgs args = this.BuildBeforeSortingEventArgs(column, order);
|
||
this.OnBeforeSorting(args);
|
||
if (args.Canceled)
|
||
return;
|
||
|
||
this.BuildGroups(args.ColumnToGroupBy, args.GroupByOrder,
|
||
args.ColumnToSort, args.SortOrder, args.SecondaryColumnToSort, args.SecondarySortOrder);
|
||
|
||
this.OnAfterSorting(new AfterSortingEventArgs(args));
|
||
}
|
||
|
||
private BeforeSortingEventArgs BuildBeforeSortingEventArgs(OLVColumn column, SortOrder order) {
|
||
OLVColumn groupBy = this.AlwaysGroupByColumn ?? column ?? this.GetColumn(0);
|
||
SortOrder groupByOrder = this.AlwaysGroupBySortOrder;
|
||
if (order == SortOrder.None) {
|
||
order = this.Sorting;
|
||
if (order == SortOrder.None)
|
||
order = SortOrder.Ascending;
|
||
}
|
||
if (groupByOrder == SortOrder.None)
|
||
groupByOrder = order;
|
||
|
||
BeforeSortingEventArgs args = new BeforeSortingEventArgs(
|
||
groupBy, groupByOrder,
|
||
column, order,
|
||
this.SecondarySortColumn ?? this.GetColumn(0),
|
||
this.SecondarySortOrder == SortOrder.None ? order : this.SecondarySortOrder);
|
||
if (column != null)
|
||
args.Canceled = !column.Sortable;
|
||
return args;
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD>ݸ<EFBFBD><DDB8><EFBFBD><EFBFBD>н<EFBFBD><D0BD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD>֯<EFBFBD><D6AF><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <param name="groupByColumn"><3E><>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD>һ<EFBFBD>н<EFBFBD><D0BD>з<EFBFBD><D0B7><EFBFBD></param>
|
||
/// <param name="groupByOrder"><3E>齫ʹ<E9BDAB><CAB9>ʲô˳<C3B4><CBB3></param>
|
||
/// <param name="column"><3E><>ֵӦ<D6B5><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA></param>
|
||
/// <param name="order"><3E><><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD><CBB3></param>
|
||
/// <param name="secondaryColumn"><3E><><EFBFBD><EFBFBD>column<6D><6E><EFBFBD>е<EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>ʹ<EFBFBD>ô<EFBFBD><C3B4><EFBFBD><EFBFBD>ṩ<EFBFBD><E1B9A9>ֵ</param>
|
||
/// <param name="secondaryOrder"><3E>μ<EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></param>
|
||
/// <remarks><3E>˷<EFBFBD><CBB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ᴥ<EFBFBD><E1B4A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD>ʹ<EFBFBD><CAB9>BuildGroups()ִ<>д˲<D0B4><CBB2><EFBFBD></remarks>
|
||
public virtual void BuildGroups(OLVColumn groupByColumn, SortOrder groupByOrder,
|
||
OLVColumn column, SortOrder order, OLVColumn secondaryColumn, SortOrder secondaryOrder) {
|
||
// Sanity checks
|
||
if (groupByColumn == null)
|
||
return;
|
||
|
||
// Getting the Count forces any internal cache of the ListView to be flushed. Without
|
||
// this, iterating over the Items will not work correctly if the ListView handle
|
||
// has not yet been created.
|
||
#pragma warning disable 168
|
||
// ReSharper disable once UnusedVariable
|
||
int dummy = this.Items.Count;
|
||
#pragma warning restore 168
|
||
|
||
// Collect all the information that governs the creation of groups
|
||
GroupingParameters parms = this.CollectGroupingParameters(groupByColumn, groupByOrder,
|
||
column, order, secondaryColumn, secondaryOrder);
|
||
|
||
// Trigger an event to let the world create groups if they want
|
||
CreateGroupsEventArgs args = new CreateGroupsEventArgs(parms);
|
||
if (parms.GroupByColumn != null)
|
||
args.Canceled = !parms.GroupByColumn.Groupable;
|
||
this.OnBeforeCreatingGroups(args);
|
||
if (args.Canceled)
|
||
return;
|
||
|
||
// If the event didn't create them for us, use our default strategy
|
||
if (args.Groups == null)
|
||
args.Groups = this.MakeGroups(parms);
|
||
|
||
// Give the world a chance to munge the groups before they are created
|
||
this.OnAboutToCreateGroups(args);
|
||
if (args.Canceled)
|
||
return;
|
||
|
||
// Create the groups now
|
||
this.OLVGroups = args.Groups;
|
||
this.CreateGroups(args.Groups);
|
||
|
||
// Tell the world that new groups have been created
|
||
this.OnAfterCreatingGroups(args);
|
||
lastGroupingParameters = args.Parameters;
|
||
}
|
||
private GroupingParameters lastGroupingParameters;
|
||
|
||
/// <summary>
|
||
/// <20>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӱ<EFBFBD><D3B0><EFBFBD>鴴<EFBFBD><E9B4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
protected virtual GroupingParameters CollectGroupingParameters(OLVColumn groupByColumn, SortOrder groupByOrder,
|
||
OLVColumn sortByColumn, SortOrder sortByOrder, OLVColumn secondaryColumn, SortOrder secondaryOrder) {
|
||
|
||
// If the user tries to group by a non-groupable column, keep the current group by
|
||
// settings, but use the non-groupable column for sorting
|
||
if (!groupByColumn.Groupable && lastGroupingParameters != null) {
|
||
sortByColumn = groupByColumn;
|
||
sortByOrder = groupByOrder;
|
||
groupByColumn = lastGroupingParameters.GroupByColumn;
|
||
groupByOrder = lastGroupingParameters.GroupByOrder;
|
||
}
|
||
|
||
string titleFormat = this.ShowItemCountOnGroups ? groupByColumn.GroupWithItemCountFormatOrDefault : null;
|
||
string titleSingularFormat = this.ShowItemCountOnGroups ? groupByColumn.GroupWithItemCountSingularFormatOrDefault : null;
|
||
GroupingParameters parms = new GroupingParameters(this, groupByColumn, groupByOrder,
|
||
sortByColumn, sortByOrder, secondaryColumn, secondaryOrder,
|
||
titleFormat, titleSingularFormat, this.SortGroupItemsByPrimaryColumn);
|
||
return parms;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Make a list of groups that should be shown according to the given parameters
|
||
/// </summary>
|
||
/// <param name="parms"></param>
|
||
/// <returns>The list of groups to be created</returns>
|
||
/// <remarks>This should not change the state of the control. It is possible that the
|
||
/// groups created will not be used. They may simply be discarded.</remarks>
|
||
protected virtual IList<OLVGroup> MakeGroups(GroupingParameters parms) {
|
||
|
||
// There is a lot of overlap between this method and FastListGroupingStrategy.MakeGroups()
|
||
// Any changes made here may need to be reflected there
|
||
|
||
// Separate the list view items into groups, using the group key as the descrimanent
|
||
NullableDictionary<object, List<OLVListItem>> map = new NullableDictionary<object, List<OLVListItem>>();
|
||
foreach (OLVListItem olvi in parms.ListView.Items) {
|
||
object key = parms.GroupByColumn.GetGroupKey(olvi.RowObject);
|
||
if (!map.ContainsKey(key))
|
||
map[key] = new List<OLVListItem>();
|
||
map[key].Add(olvi);
|
||
}
|
||
|
||
// Sort the items within each group (unless specifically turned off)
|
||
OLVColumn sortColumn = parms.SortItemsByPrimaryColumn ? parms.ListView.GetColumn(0) : parms.PrimarySort;
|
||
if (sortColumn != null && parms.PrimarySortOrder != SortOrder.None) {
|
||
IComparer<OLVListItem> itemSorter = parms.ItemComparer ??
|
||
new ColumnComparer(sortColumn, parms.PrimarySortOrder, parms.SecondarySort, parms.SecondarySortOrder);
|
||
foreach (object key in map.Keys) {
|
||
map[key].Sort(itemSorter);
|
||
}
|
||
}
|
||
|
||
// Make a list of the required groups
|
||
List<OLVGroup> groups = new List<OLVGroup>();
|
||
foreach (object key in map.Keys) {
|
||
string title = parms.GroupByColumn.ConvertGroupKeyToTitle(key);
|
||
if (!String.IsNullOrEmpty(parms.TitleFormat)) {
|
||
int count = map[key].Count;
|
||
string format = (count == 1 ? parms.TitleSingularFormat : parms.TitleFormat);
|
||
try {
|
||
title = String.Format(format, title, count);
|
||
} catch (FormatException) {
|
||
title = "Invalid group format: " + format;
|
||
}
|
||
}
|
||
|
||
OLVGroup lvg = new OLVGroup(title);
|
||
lvg.Collapsible = this.HasCollapsibleGroups;
|
||
lvg.Key = key;
|
||
lvg.SortValue = key as IComparable;
|
||
lvg.Items = map[key];
|
||
if (parms.GroupByColumn.GroupFormatter != null)
|
||
parms.GroupByColumn.GroupFormatter(lvg, parms);
|
||
groups.Add(lvg);
|
||
}
|
||
|
||
// Sort the groups
|
||
if (parms.GroupByOrder != SortOrder.None)
|
||
groups.Sort(parms.GroupComparer ?? new OLVGroupComparer(parms.GroupByOrder));
|
||
|
||
return groups;
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD><EFBFBD><EEA3AC><EFBFBD><EFBFBD><EFBFBD>ܶ<EFBFBD><DCB6>ر<EFBFBD><D8B1><EFBFBD>״̬
|
||
/// </summary>
|
||
public virtual void BuildList() {
|
||
if (this.InvokeRequired)
|
||
this.Invoke(new MethodInvoker(this.BuildList));
|
||
else
|
||
this.BuildList(true);
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD><CDBC>
|
||
/// </summary>
|
||
/// <param name="shouldPreserveState">If this is true, the control will try to preserve the selection,
|
||
/// focused item, and the scroll position (see Remarks)
|
||
/// </param>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// Use this method in situations were the contents of the list is basically the same
|
||
/// as previously.
|
||
/// </para>
|
||
/// </remarks>
|
||
public virtual void BuildList(bool shouldPreserveState) {
|
||
if (this.Frozen)
|
||
return;
|
||
|
||
Stopwatch sw = Stopwatch.StartNew();
|
||
|
||
this.ApplyExtendedStyles();
|
||
this.ClearHotItem();
|
||
int previousTopIndex = this.TopItemIndex;
|
||
Point currentScrollPosition = this.LowLevelScrollPosition;
|
||
|
||
IList previousSelection = new ArrayList();
|
||
Object previousFocus = null;
|
||
if (shouldPreserveState && this.objects != null) {
|
||
previousSelection = this.SelectedObjects;
|
||
OLVListItem focusedItem = this.FocusedItem as OLVListItem;
|
||
if (focusedItem != null)
|
||
previousFocus = focusedItem.RowObject;
|
||
}
|
||
|
||
IEnumerable objectsToDisplay = this.FilteredObjects;
|
||
|
||
this.BeginUpdate();
|
||
try {
|
||
this.Items.Clear();
|
||
this.ListViewItemSorter = null;
|
||
|
||
if (objectsToDisplay != null) {
|
||
// Build a list of all our items and then display them. (Building
|
||
// a list and then doing one AddRange is about 10-15% faster than individual adds)
|
||
List<ListViewItem> itemList = new List<ListViewItem>(); // use ListViewItem to avoid co-variant conversion
|
||
foreach (object rowObject in objectsToDisplay) {
|
||
OLVListItem lvi = new OLVListItem(rowObject);
|
||
this.FillInValues(lvi, rowObject);
|
||
itemList.Add(lvi);
|
||
}
|
||
this.Items.AddRange(itemList.ToArray());
|
||
this.Sort();
|
||
|
||
if (shouldPreserveState) {
|
||
this.SelectedObjects = previousSelection;
|
||
this.FocusedItem = this.ModelToItem(previousFocus);
|
||
}
|
||
}
|
||
} finally {
|
||
this.EndUpdate();
|
||
}
|
||
|
||
this.RefreshHotItem();
|
||
|
||
// We can only restore the scroll position after the EndUpdate() because
|
||
// of caching that the ListView does internally during a BeginUpdate/EndUpdate pair.
|
||
if (shouldPreserveState) {
|
||
// Restore the scroll position. TopItemIndex is best, but doesn't work
|
||
// when the control is grouped.
|
||
if (this.ShowGroups)
|
||
this.LowLevelScroll(currentScrollPosition.X, currentScrollPosition.Y);
|
||
else
|
||
this.TopItemIndex = previousTopIndex;
|
||
}
|
||
|
||
// System.Diagnostics.Debug.WriteLine(String.Format("PERF - Building list for {2} objects took {0}ms / {1} ticks", sw.ElapsedMilliseconds, sw.ElapsedTicks, this.GetItemCount()));
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD>һֱ<D2BB><D6B1>ʹ<EFBFBD>õ<EFBFBD><C3B5><EFBFBD><EFBFBD>л<EFBFBD><D0BB><EFBFBD><EFBFBD><EFBFBD>Ϣ
|
||
/// </summary>
|
||
public virtual void ClearCachedInfo()
|
||
{
|
||
// ObjectListView<65><77>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E0BBBA>(<28><><EFBFBD><EFBFBD><EFBFBD>ܻ<EFBFBD><DCBB><EFBFBD>)
|
||
}
|
||
|
||
/// <summary>
|
||
/// Apply all required extended styles to our control.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// Whenever .NET code sets an extended style, it erases all other extended styles
|
||
/// that it doesn't use. So, we have to explicit reapply the styles that we have
|
||
/// added.
|
||
/// </para>
|
||
/// <para>
|
||
/// Normally, we would override CreateParms property and update
|
||
/// the ExStyle member, but ListView seems to ignore all ExStyles that
|
||
/// it doesn't already know about. Worse, when we set the LVS_EX_HEADERINALLVIEWS
|
||
/// value, bad things happen (the control crashes!).
|
||
/// </para>
|
||
/// </remarks>
|
||
protected virtual void ApplyExtendedStyles() {
|
||
const int LVS_EX_SUBITEMIMAGES = 0x00000002;
|
||
//const int LVS_EX_TRANSPARENTBKGND = 0x00400000;
|
||
const int LVS_EX_HEADERINALLVIEWS = 0x02000000;
|
||
|
||
const int STYLE_MASK = LVS_EX_SUBITEMIMAGES | LVS_EX_HEADERINALLVIEWS;
|
||
int style = 0;
|
||
|
||
if (this.ShowImagesOnSubItems && !this.VirtualMode)
|
||
style ^= LVS_EX_SUBITEMIMAGES;
|
||
|
||
if (this.ShowHeaderInAllViews)
|
||
style ^= LVS_EX_HEADERINALLVIEWS;
|
||
|
||
NativeMethods.SetExtendedStyle(this, style, STYLE_MASK);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Give the listview a reasonable size of its tiles, based on the number of lines of
|
||
/// information that each tile is going to display.
|
||
/// </summary>
|
||
public virtual void CalculateReasonableTileSize() {
|
||
if (this.Columns.Count <= 0)
|
||
return;
|
||
|
||
List<OLVColumn> columns = this.AllColumns.FindAll(delegate(OLVColumn x) {
|
||
return (x.Index == 0) || x.IsTileViewColumn;
|
||
});
|
||
|
||
int imageHeight = (this.LargeImageList == null ? 16 : this.LargeImageList.ImageSize.Height);
|
||
int dataHeight = (this.Font.Height + 1) * columns.Count;
|
||
int tileWidth = (this.TileSize.Width == 0 ? 200 : this.TileSize.Width);
|
||
int tileHeight = Math.Max(this.TileSize.Height, Math.Max(imageHeight, dataHeight));
|
||
this.TileSize = new Size(tileWidth, tileHeight);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Rebuild this list for the given view
|
||
/// </summary>
|
||
/// <param name="view"></param>
|
||
public virtual void ChangeToFilteredColumns(View view) {
|
||
// Store the state
|
||
this.SuspendSelectionEvents();
|
||
IList previousSelection = this.SelectedObjects;
|
||
int previousTopIndex = this.TopItemIndex;
|
||
|
||
this.Freeze();
|
||
this.Clear();
|
||
List<OLVColumn> columns = this.GetFilteredColumns(view);
|
||
if (view == View.Details || this.ShowHeaderInAllViews) {
|
||
// Make sure all columns have a reasonable LastDisplayIndex
|
||
for (int index = 0; index < columns.Count; index++)
|
||
{
|
||
if (columns[index].LastDisplayIndex == -1)
|
||
columns[index].LastDisplayIndex = index;
|
||
}
|
||
// ListView will ignore DisplayIndex FOR ALL COLUMNS if there are any errors,
|
||
// e.g. duplicates (two columns with the same DisplayIndex) or gaps.
|
||
// LastDisplayIndex isn't guaranteed to be unique, so we just sort the columns by
|
||
// the last position they were displayed and use that to generate a sequence
|
||
// we can use for the DisplayIndex values.
|
||
List<OLVColumn> columnsInDisplayOrder = new List<OLVColumn>(columns);
|
||
columnsInDisplayOrder.Sort(delegate(OLVColumn x, OLVColumn y) { return (x.LastDisplayIndex - y.LastDisplayIndex); });
|
||
int i = 0;
|
||
foreach (OLVColumn col in columnsInDisplayOrder)
|
||
col.DisplayIndex = i++;
|
||
}
|
||
|
||
// ReSharper disable once CoVariantArrayConversion
|
||
this.Columns.AddRange(columns.ToArray());
|
||
if (view == View.Details || this.ShowHeaderInAllViews)
|
||
this.ShowSortIndicator();
|
||
this.UpdateFiltering();
|
||
this.Unfreeze();
|
||
|
||
// Restore the state
|
||
this.SelectedObjects = previousSelection;
|
||
this.TopItemIndex = previousTopIndex;
|
||
this.ResumeSelectionEvents();
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20>Ƴ<EFBFBD><C6B3><EFBFBD><EFBFBD>ж<EFBFBD><D0B6><EFBFBD>(<28>̰߳<DFB3>ȫ)
|
||
/// </summary>
|
||
/// <remark>This method can safely be called from background threads.</remark>
|
||
public virtual void ClearObjects() {
|
||
if (this.InvokeRequired)
|
||
this.Invoke(new MethodInvoker(this.ClearObjects));
|
||
else
|
||
this.SetObjects(null);
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD>ѷ<EFBFBD><D1B7><EFBFBD><EFBFBD><EFBFBD>URL<52><4C><EFBFBD>ڴ<EFBFBD>
|
||
/// </summary>
|
||
public virtual void ClearUrlVisited() {
|
||
this.visitedUrlMap = new Dictionary<string, bool>();
|
||
}
|
||
|
||
/// <summary>
|
||
///<2F><>ѡ<EFBFBD><D1A1><EFBFBD>е<EFBFBD><D0B5>ı<EFBFBD><C4B1><EFBFBD>HTML<4D><4C>ʾ<EFBFBD><CABE><EFBFBD>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϡ<EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>Be careful when using this with virtual lists. If the user has selected
|
||
/// 10,000,000 rows, this method will faithfully try to copy all of them to the clipboard.
|
||
/// From the user's point of view, your program will appear to have hung.</remarks>
|
||
public virtual void CopySelectionToClipboard() {
|
||
IList selection = this.SelectedObjects;
|
||
if (selection.Count == 0)
|
||
return;
|
||
|
||
// Use the DragSource object to create the data object, if so configured.
|
||
// This relies on the assumption that DragSource will handle the selected objects only.
|
||
// It is legal for StartDrag to return null.
|
||
object data = null;
|
||
if (this.CopySelectionOnControlCUsesDragSource && this.DragSource != null)
|
||
data = this.DragSource.StartDrag(this, MouseButtons.Left, this.ModelToItem(selection[0]));
|
||
|
||
Clipboard.SetDataObject(data ?? new OLVDataObject(this, selection));
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><C4B1><EFBFBD>HTML<4D><4C>ʾ<EFBFBD><CABE><EFBFBD>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϡ<EFBFBD>
|
||
/// </summary>
|
||
public virtual void CopyObjectsToClipboard(IList objectsToCopy) {
|
||
if (objectsToCopy.Count == 0)
|
||
return;
|
||
|
||
// We don't know where these objects came from, so we can't use the DragSource to create
|
||
// the data object, like we do with CopySelectionToClipboard() above.
|
||
OLVDataObject dataObject = new OLVDataObject(this, objectsToCopy);
|
||
dataObject.CreateTextFormats();
|
||
Clipboard.SetDataObject(dataObject);
|
||
}
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><C4B1><EFBFBD>HTML<4D><4C>ʾ<EFBFBD><CABE><EFBFBD>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϡ<EFBFBD>
|
||
/// </summary>
|
||
public virtual void CopyObjectsToClipboard()
|
||
{
|
||
CopyObjectsToClipboard(ObjectsList);
|
||
}
|
||
/// <summary>
|
||
/// <20><><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>html<6D><6C>ʾ<EFBFBD><CABE>ʽ
|
||
/// </summary>
|
||
public virtual string ObjectsToHtml(IList objectsToConvert) {
|
||
if (objectsToConvert.Count == 0)
|
||
return String.Empty;
|
||
|
||
OLVExporter exporter = new OLVExporter(this, objectsToConvert);
|
||
return exporter.ExportTo(OLVExporter.ExportFormat.HTML);
|
||
}
|
||
|
||
/// <summary>
|
||
/// ȡ<><C8A1>ѡ<EFBFBD><D1A1><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
public virtual void DeselectAll() {
|
||
NativeMethods.DeselectAllItems(this);
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD>ؽ<EFBFBD><D8BD><EFBFBD><EFBFBD>ڸ<EFBFBD><DAB8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ListViewItem<65><6D>
|
||
///<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>գ<EFBFBD><D5A3><EFBFBD><F2B7B5BB>б<EFBFBD><D0B1>еĵ<D0B5>һ<EFBFBD><D2BB><EFBFBD>
|
||
///<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>NULL<4C><4C>
|
||
/// </summary>
|
||
/// <param name="itemToFind">The item that is before the item that is returned, or null</param>
|
||
/// <returns>A ListViewItem</returns>
|
||
public virtual OLVListItem GetNextItem(OLVListItem itemToFind) {
|
||
if (this.ShowGroups) {
|
||
bool isFound = (itemToFind == null);
|
||
foreach (ListViewGroup group in this.Groups) {
|
||
foreach (OLVListItem olvi in group.Items) {
|
||
if (isFound)
|
||
return olvi;
|
||
isFound = (itemToFind == olvi);
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
if (this.GetItemCount() == 0)
|
||
return null;
|
||
if (itemToFind == null)
|
||
return this.GetItem(0);
|
||
if (itemToFind.Index == this.GetItemCount() - 1)
|
||
return null;
|
||
return this.GetItem(itemToFind.Index + 1);
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD>ʾ<EFBFBD><CABE>˳<EFBFBD><EFBFBD><F2B7B5BB><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>
|
||
///<2F><><EFBFBD><EFBFBD><EFBFBD>ؼ<EFBFBD>δ<EFBFBD><CEB4><EFBFBD>飬<EFBFBD><E9A3AC><EFBFBD><EFBFBD>ʾ˳<CABE><CBB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD>˳<EFBFBD><CBB3><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC>
|
||
///<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD><EFBFBD>ʾ˳<CABE><CBB3><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC>
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public virtual OLVListItem GetLastItemInDisplayOrder() {
|
||
if (!this.ShowGroups)
|
||
return this.GetItem(this.GetItemCount() - 1);
|
||
|
||
if (this.Groups.Count > 0) {
|
||
ListViewGroup lastGroup = this.Groups[this.Groups.Count - 1];
|
||
if (lastGroup.Items.Count > 0)
|
||
return (OLVListItem)lastGroup.Items[lastGroup.Items.Count - 1];
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD>ʾ<EFBFBD><CABE>˳<EFBFBD>ص<F2B7B5BB>n<EFBFBD><6E>(<28><>0<EFBFBD><30>ʼ)<29><>
|
||
///<2F><><EFBFBD><EFBFBD><EFBFBD>ؼ<EFBFBD>δ<EFBFBD><CEB4><EFBFBD>飬<EFBFBD><E9A3AC><EFBFBD><EFBFBD>ʾ˳<CABE><CBB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD>˳<EFBFBD><CBB3><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC>
|
||
///<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD><EFBFBD>ʾ˳<CABE><CBB3><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC>
|
||
/// </summary>
|
||
/// <param name="n"></param>
|
||
/// <returns></returns>
|
||
public virtual OLVListItem GetNthItemInDisplayOrder(int n) {
|
||
if (!this.ShowGroups || this.Groups.Count == 0)
|
||
return this.GetItem(n);
|
||
|
||
foreach (ListViewGroup group in this.Groups) {
|
||
if (n < group.Items.Count)
|
||
return (OLVListItem)group.Items[n];
|
||
|
||
n -= group.Items.Count;
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
/// <summary>
|
||
///<2F><><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD>listviewitem<65><6D><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
///<2F><><EFBFBD><EFBFBD><EFBFBD>ؼ<EFBFBD>δ<EFBFBD><CEB4><EFBFBD>飬<EFBFBD><E9A3AC><EFBFBD><EFBFBD>ʾ˳<CABE><CBB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD>˳<EFBFBD><CBB3><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC>
|
||
///<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD><EFBFBD>ʾ˳<CABE><CBB3><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC>
|
||
/// </summary>
|
||
/// <param name="itemIndex"></param>
|
||
/// <returns></returns>
|
||
public virtual int GetDisplayOrderOfItemIndex(int itemIndex) {
|
||
if (!this.ShowGroups || this.Groups.Count == 0)
|
||
return itemIndex;
|
||
|
||
// TODO: This could be optimized
|
||
int i = 0;
|
||
foreach (ListViewGroup lvg in this.Groups) {
|
||
foreach (ListViewItem lvi in lvg.Items) {
|
||
if (lvi.Index == itemIndex)
|
||
return i;
|
||
i++;
|
||
}
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD>ؽ<EFBFBD><D8BD><EFBFBD><EFBFBD>ڸ<EFBFBD><DAB8><EFBFBD><EFBFBD><EFBFBD>֮ǰ<D6AE><C7B0><EFBFBD>ֵ<EFBFBD>ListViewItem<65><6D>
|
||
///<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>գ<EFBFBD><D5A3><EFBFBD><F2B7B5BB>б<EFBFBD><D0B1>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>
|
||
///<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǵ<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>NULL<4C><4C>
|
||
/// </summary>
|
||
/// <param name="itemToFind">The item that is before the item that is returned</param>
|
||
/// <returns>A ListViewItem</returns>
|
||
public virtual OLVListItem GetPreviousItem(OLVListItem itemToFind) {
|
||
if (this.ShowGroups) {
|
||
OLVListItem previousItem = null;
|
||
foreach (ListViewGroup group in this.Groups) {
|
||
foreach (OLVListItem lvi in group.Items) {
|
||
if (lvi == itemToFind)
|
||
return previousItem;
|
||
|
||
previousItem = lvi;
|
||
}
|
||
}
|
||
return itemToFind == null ? previousItem : null;
|
||
}
|
||
if (this.GetItemCount() == 0)
|
||
return null;
|
||
if (itemToFind == null)
|
||
return this.GetItem(this.GetItemCount() - 1);
|
||
if (itemToFind.Index == 0)
|
||
return null;
|
||
return this.GetItem(itemToFind.Index - 1);
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20>ڸ<EFBFBD><DAB8><EFBFBD>λ<EFBFBD><CEBB>֮ǰ<D6AE><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD>
|
||
/// </summary>
|
||
/// <param name="index">Where to insert the objects</param>
|
||
/// <param name="modelObjects">The objects to be inserted</param>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// This operation only makes sense of non-sorted, non-grouped
|
||
/// lists, since any subsequent sort/group operation will rearrange
|
||
/// the list.
|
||
/// </para>
|
||
/// <para>This method only works on ObjectListViews and FastObjectListViews.</para>
|
||
///</remarks>
|
||
public virtual void InsertObjects(int index, ICollection modelObjects) {
|
||
if (this.InvokeRequired) {
|
||
this.Invoke((MethodInvoker)delegate() {
|
||
this.InsertObjects(index, modelObjects);
|
||
});
|
||
return;
|
||
}
|
||
if (modelObjects == null)
|
||
return;
|
||
|
||
this.BeginUpdate();
|
||
try {
|
||
// Give the world a chance to cancel or change the added objects
|
||
ItemsAddingEventArgs args = new ItemsAddingEventArgs(modelObjects);
|
||
this.OnItemsAdding(args);
|
||
if (args.Canceled)
|
||
return;
|
||
modelObjects = args.ObjectsToAdd;
|
||
|
||
this.TakeOwnershipOfObjects();
|
||
ArrayList ourObjects = ObjectListView.EnumerableToArray(this.Objects, false);
|
||
|
||
// If we are filtering the list, there is no way to efficiently
|
||
// insert the objects, so just put them into our collection and rebuild.
|
||
if (this.IsFiltering) {
|
||
index = Math.Max(0, Math.Min(index, ourObjects.Count));
|
||
ourObjects.InsertRange(index, modelObjects);
|
||
this.BuildList(true);
|
||
} else {
|
||
this.ListViewItemSorter = null;
|
||
index = Math.Max(0, Math.Min(index, this.GetItemCount()));
|
||
int i = index;
|
||
foreach (object modelObject in modelObjects) {
|
||
if (modelObject != null) {
|
||
ourObjects.Insert(i, modelObject);
|
||
OLVListItem lvi = new OLVListItem(modelObject);
|
||
this.FillInValues(lvi, modelObject);
|
||
this.Items.Insert(i, lvi);
|
||
i++;
|
||
}
|
||
}
|
||
|
||
for (i = index; i < this.GetItemCount(); i++) {
|
||
OLVListItem lvi = this.GetItem(i);
|
||
this.SetSubItemImages(lvi.Index, lvi);
|
||
}
|
||
|
||
this.PostProcessRows();
|
||
}
|
||
|
||
// Tell the world that the list has changed
|
||
this.SubscribeNotifications(modelObjects);
|
||
this.OnItemsChanged(new ItemsChangedEventArgs());
|
||
} finally {
|
||
this.EndUpdate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD>˱<EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD>ģ<EFBFBD>͵<EFBFBD><CDB5>У<EFBFBD><D0A3><EFBFBD>TRUE
|
||
/// </summary>
|
||
/// <param name="model">The model object to look for</param>
|
||
/// <returns>Is the row selected</returns>
|
||
public bool IsSelected(object model) {
|
||
OLVListItem item = this.ModelToItem(model);
|
||
return item != null && item.Selected;
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>URL<52>Ƿ<EFBFBD><C7B7>ѱ<EFBFBD><D1B1><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <param name="url">The string to be consider</param>
|
||
/// <returns>Has it been visited</returns>
|
||
public virtual bool IsUrlVisited(string url) {
|
||
return this.visitedUrlMap.ContainsKey(url);
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ListView<65><77>
|
||
/// </summary>
|
||
/// <param name="dx">Horizontal delta</param>
|
||
/// <param name="dy">Vertical delta</param>
|
||
public void LowLevelScroll(int dx, int dy) {
|
||
NativeMethods.Scroll(this, dx, dy);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Return a point that represents the current horizontal and vertical scroll positions
|
||
/// </summary>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public Point LowLevelScrollPosition
|
||
{
|
||
get {
|
||
return new Point(NativeMethods.GetScrollPosition(this, true), NativeMethods.GetScrollPosition(this, false));
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
///<2F><>ס<EFBFBD><D7A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>URL<52>ѱ<EFBFBD><D1B1><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <param name="url">The url to be remembered</param>
|
||
/// <remarks>This does not cause the control be redrawn</remarks>
|
||
public virtual void MarkUrlVisited(string url) {
|
||
this.visitedUrlMap[url] = true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD><F3BCAFBA>ƶ<EFBFBD><C6B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks><3E>˲<EFBFBD><CBB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><CEB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ObjectListViews<77><73><EFBFBD><EFBFBD><EFBFBD>塣</remarks>
|
||
/// <param name="index"></param>
|
||
/// <param name="modelObjects"></param>
|
||
public virtual void MoveObjects(int index, ICollection modelObjects) {
|
||
|
||
// We are going to remove all the given objects from our list
|
||
// and then insert them at the given location
|
||
this.TakeOwnershipOfObjects();
|
||
ArrayList ourObjects = ObjectListView.EnumerableToArray(this.Objects, false);
|
||
|
||
List<int> indicesToRemove = new List<int>();
|
||
foreach (object modelObject in modelObjects) {
|
||
if (modelObject != null) {
|
||
int i = this.IndexOf(modelObject);
|
||
if (i >= 0) {
|
||
indicesToRemove.Add(i);
|
||
ourObjects.Remove(modelObject);
|
||
if (i <= index)
|
||
index--;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Remove the objects in reverse order so earlier
|
||
// deletes don't change the index of later ones
|
||
indicesToRemove.Sort();
|
||
indicesToRemove.Reverse();
|
||
try {
|
||
this.BeginUpdate();
|
||
foreach (int i in indicesToRemove) {
|
||
this.Items.RemoveAt(i);
|
||
}
|
||
this.InsertObjects(index, modelObjects);
|
||
} finally {
|
||
this.EndUpdate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
///<2F><><EFBFBD><EFBFBD><EFBFBD>ڸ<EFBFBD><DAB8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD><C2B5><EFBFBD>Ŀ<EFBFBD><C4BF>ʲô<CAB2><C3B4>
|
||
/// </summary>
|
||
/// <param name="x"></param>
|
||
/// <param name="y"></param>
|
||
/// <returns></returns>
|
||
new public ListViewHitTestInfo HitTest(int x, int y) {
|
||
// Everything costs something. Playing with the layout of the header can cause problems
|
||
// with the hit testing. If the header shrinks, the underlying control can throw a tantrum.
|
||
try {
|
||
return base.HitTest(x, y);
|
||
} catch (ArgumentOutOfRangeException) {
|
||
return new ListViewHitTestInfo(null, null, ListViewHitTestLocations.None);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// ʹ<><CAB9>Windows<77>ؼ<EFBFBD><D8BC><EFBFBD>SUBITEMHITTEST<53><54>Ϣִ<CFA2>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԡ<EFBFBD>
|
||
/// <20><><EFBFBD>ṩ<EFBFBD>˱<EFBFBD>ListView.HitTest()<29><><EFBFBD>ṩ<EFBFBD><E1B9A9><EFBFBD>й<EFBFBD><D0B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2>
|
||
/// </summary>
|
||
/// <param name="x"></param>
|
||
/// <param name="y"></param>
|
||
/// <returns></returns>
|
||
protected OlvListViewHitTestInfo LowLevelHitTest(int x, int y) {
|
||
|
||
// If it's not even in the control, don't bother with anything else
|
||
if (!this.ClientRectangle.Contains(x, y))
|
||
return new OlvListViewHitTestInfo(null, null, 0, null, 0);
|
||
|
||
// Is the point over the header?
|
||
OlvListViewHitTestInfo.HeaderHitTestInfo headerHitTestInfo = this.HeaderControl.HitTest(x, y);
|
||
if (headerHitTestInfo != null)
|
||
return new OlvListViewHitTestInfo(this, headerHitTestInfo.ColumnIndex, headerHitTestInfo.IsOverCheckBox, headerHitTestInfo.OverDividerIndex);
|
||
|
||
// Call the native hit test method, which is a little confusing.
|
||
NativeMethods.LVHITTESTINFO lParam = new NativeMethods.LVHITTESTINFO();
|
||
lParam.pt_x = x;
|
||
lParam.pt_y = y;
|
||
int index = NativeMethods.HitTest(this, ref lParam);
|
||
|
||
// Setup the various values we need to make our hit test structure
|
||
bool isGroupHit = (lParam.flags & (int)HitTestLocationEx.LVHT_EX_GROUP) != 0;
|
||
OLVListItem hitItem = isGroupHit || index == -1 ? null : this.GetItem(index);
|
||
OLVListSubItem subItem = (this.View == View.Details && hitItem != null) ? hitItem.GetSubItem(lParam.iSubItem) : null;
|
||
|
||
// Figure out which group is involved in the hit test. This is a little complicated:
|
||
// If the list is virtual:
|
||
// - the returned value is list view item index
|
||
// - iGroup is the *index* of the hit group.
|
||
// If the list is not virtual:
|
||
// - iGroup is always -1.
|
||
// - if the point is over a group, the returned value is the *id* of the hit group.
|
||
// - if the point is not over a group, the returned value is list view item index.
|
||
OLVGroup group = null;
|
||
if (this.ShowGroups && this.OLVGroups != null) {
|
||
if (this.VirtualMode) {
|
||
group = lParam.iGroup >= 0 && lParam.iGroup < this.OLVGroups.Count ? this.OLVGroups[lParam.iGroup] : null;
|
||
} else {
|
||
if (isGroupHit) {
|
||
foreach (OLVGroup olvGroup in this.OLVGroups) {
|
||
if (olvGroup.GroupId == index) {
|
||
group = olvGroup;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
OlvListViewHitTestInfo olvListViewHitTest = new OlvListViewHitTestInfo(hitItem, subItem, lParam.flags, group, lParam.iSubItem);
|
||
// System.Diagnostics.Debug.WriteLine(String.Format("HitTest({0}, {1})=>{2}", x, y, olvListViewHitTest));
|
||
return olvListViewHitTest;
|
||
}
|
||
|
||
/// <summary>
|
||
/// What is under the given point? This takes the various parts of a cell into accout, including
|
||
/// any custom parts that a custom renderer might use
|
||
/// </summary>
|
||
/// <param name="x"></param>
|
||
/// <param name="y"></param>
|
||
/// <returns>An information block about what is under the point</returns>
|
||
public virtual OlvListViewHitTestInfo OlvHitTest(int x, int y) {
|
||
OlvListViewHitTestInfo hti = this.LowLevelHitTest(x, y);
|
||
|
||
// There is a bug/"feature" of the ListView concerning hit testing.
|
||
// If FullRowSelect is false and the point is over cell 0 but not on
|
||
// the text or icon, HitTest will not register a hit. We could turn
|
||
// FullRowSelect on, do the HitTest, and then turn it off again, but
|
||
// toggling FullRowSelect in that way messes up the tooltip in the
|
||
// underlying control. So we have to find another way.
|
||
//
|
||
// It's too hard to try to write the hit test from scratch. Grouping (for
|
||
// example) makes it just too complicated. So, we have to use HitTest
|
||
// but try to get around its limits.
|
||
//
|
||
// First step is to determine if the point was within column 0.
|
||
// If it was, then we only have to determine if there is an actual row
|
||
// under the point. If there is, then we know that the point is over cell 0.
|
||
// So we try a Battleship-style approach: is there a subcell to the right
|
||
// of cell 0? This will return a false negative if column 0 is the rightmost column,
|
||
// so we also check for a subcell to the left. But if only column 0 is visible,
|
||
// then that will fail too, so we check for something at the very left of the
|
||
// control.
|
||
//
|
||
// This will still fail under pathological conditions. If column 0 fills
|
||
// the whole listview and no part of the text column 0 is visible
|
||
// (because it is horizontally scrolled offscreen), then the hit test will fail.
|
||
|
||
// Are we in the buggy context? Details view, not full row select, and
|
||
// failing to find anything
|
||
if (hti.Item == null && !this.FullRowSelect && this.View == View.Details) {
|
||
// Is the point within the column 0? If it is, maybe it should have been a hit.
|
||
// Let's test slightly to the right and then to left of column 0. Hopefully one
|
||
// of those will hit a subitem
|
||
Point sides = NativeMethods.GetScrolledColumnSides(this, 0);
|
||
if (x >= sides.X && x <= sides.Y) {
|
||
// We look for:
|
||
// - any subitem to the right of cell 0?
|
||
// - any subitem to the left of cell 0?
|
||
// - cell 0 at the left edge of the screen
|
||
hti = this.LowLevelHitTest(sides.Y + 4, y);
|
||
if (hti.Item == null)
|
||
hti = this.LowLevelHitTest(sides.X - 4, y);
|
||
if (hti.Item == null)
|
||
hti = this.LowLevelHitTest(4, y);
|
||
|
||
if (hti.Item != null) {
|
||
// We hit something! So, the original point must have been in cell 0
|
||
hti.ColumnIndex = 0;
|
||
hti.SubItem = hti.Item.GetSubItem(0);
|
||
hti.Location = ListViewHitTestLocations.None;
|
||
hti.HitTestLocation = HitTestLocation.InCell;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (this.OwnerDraw)
|
||
this.CalculateOwnerDrawnHitTest(hti, x, y);
|
||
else
|
||
this.CalculateStandardHitTest(hti, x, y);
|
||
|
||
return hti;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Perform a hit test when the control is not owner drawn
|
||
/// </summary>
|
||
/// <param name="hti"></param>
|
||
/// <param name="x"></param>
|
||
/// <param name="y"></param>
|
||
protected virtual void CalculateStandardHitTest(OlvListViewHitTestInfo hti, int x, int y) {
|
||
|
||
// Standard hit test works fine for the primary column
|
||
if (this.View != View.Details || hti.ColumnIndex == 0 ||
|
||
hti.SubItem == null || hti.Column == null)
|
||
return;
|
||
|
||
Rectangle cellBounds = hti.SubItem.Bounds;
|
||
bool hasImage = (this.GetActualImageIndex(hti.SubItem.ImageSelector) != -1);
|
||
|
||
// Unless we say otherwise, it was an general incell hit
|
||
hti.HitTestLocation = HitTestLocation.InCell;
|
||
|
||
// Check if the point is over where an image should be.
|
||
// If there is a checkbox or image there, tag it and exit.
|
||
Rectangle r = cellBounds;
|
||
r.Width = this.SmallImageSize.Width;
|
||
if (r.Contains(x, y)) {
|
||
if (hti.Column.CheckBoxes) {
|
||
hti.HitTestLocation = HitTestLocation.CheckBox;
|
||
return;
|
||
}
|
||
if (hasImage) {
|
||
hti.HitTestLocation = HitTestLocation.Image;
|
||
return;
|
||
}
|
||
}
|
||
|
||
// Figure out where the text actually is and if the point is in it
|
||
// The standard HitTest assumes that any point inside a subitem is
|
||
// a hit on Text -- which is clearly not true.
|
||
Rectangle textBounds = cellBounds;
|
||
textBounds.X += 4;
|
||
if (hasImage)
|
||
textBounds.X += this.SmallImageSize.Width;
|
||
|
||
Size proposedSize = new Size(textBounds.Width, textBounds.Height);
|
||
Size textSize = TextRenderer.MeasureText(hti.SubItem.Text, this.Font, proposedSize, TextFormatFlags.EndEllipsis | TextFormatFlags.SingleLine | TextFormatFlags.NoPrefix);
|
||
textBounds.Width = textSize.Width;
|
||
|
||
switch (hti.Column.TextAlign) {
|
||
case HorizontalAlignment.Center:
|
||
textBounds.X += (cellBounds.Right - cellBounds.Left - textSize.Width) / 2;
|
||
break;
|
||
case HorizontalAlignment.Right:
|
||
textBounds.X = cellBounds.Right - textSize.Width;
|
||
break;
|
||
}
|
||
if (textBounds.Contains(x, y)) {
|
||
hti.HitTestLocation = HitTestLocation.Text;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Perform a hit test when the control is owner drawn. This hands off responsibility
|
||
/// to the renderer.
|
||
/// </summary>
|
||
/// <param name="hti"></param>
|
||
/// <param name="x"></param>
|
||
/// <param name="y"></param>
|
||
protected virtual void CalculateOwnerDrawnHitTest(OlvListViewHitTestInfo hti, int x, int y) {
|
||
// If the click wasn't on an item, give up
|
||
if (hti.Item == null)
|
||
return;
|
||
|
||
// If the list is showing column, but they clicked outside the columns, also give up
|
||
if (this.View == View.Details && hti.Column == null)
|
||
return;
|
||
|
||
// Which renderer was responsible for drawing that point
|
||
IRenderer renderer = this.View == View.Details
|
||
? this.GetCellRenderer(hti.RowObject, hti.Column)
|
||
: this.ItemRenderer;
|
||
|
||
// We can't decide who was responsible. Give up
|
||
if (renderer == null)
|
||
return;
|
||
|
||
// Ask the responsible renderer what is at that point
|
||
renderer.HitTest(hti, x, y);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Pause (or unpause) all animations in the list
|
||
/// </summary>
|
||
/// <param name="isPause">true to pause, false to unpause</param>
|
||
public virtual void PauseAnimations(bool isPause) {
|
||
for (int i = 0; i < this.Columns.Count; i++) {
|
||
OLVColumn col = this.GetColumn(i);
|
||
ImageRenderer renderer = col.Renderer as ImageRenderer;
|
||
if (renderer != null)
|
||
renderer.Paused = isPause;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Rebuild the columns based upon its current view and column visibility settings
|
||
/// </summary>
|
||
public virtual void RebuildColumns() {
|
||
this.ChangeToFilteredColumns(this.View);
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><>ListView<65><77>ɾ<EFBFBD><C9BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD>
|
||
/// </summary>
|
||
/// <param name="modelObject">The model to be removed</param>
|
||
/// <remarks>See RemoveObjects() for more details
|
||
/// <para>This method is thread-safe.</para>
|
||
/// </remarks>
|
||
public virtual void RemoveObject(object modelObject) {
|
||
if (this.InvokeRequired)
|
||
this.Invoke((MethodInvoker)delegate() { this.RemoveObject(modelObject); });
|
||
else
|
||
this.RemoveObjects(new object[] { modelObject });
|
||
}
|
||
|
||
/// <summary>
|
||
///<2F>ӿؼ<D3BF><D8BC><EFBFBD><EFBFBD>Ƴ<EFBFBD><C6B3><EFBFBD><EFBFBD>и<EFBFBD><D0B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <param name="modelObjects">Collection of objects to be removed</param>
|
||
/// <remarks>
|
||
/// <para>Nulls and model objects that are not in the ListView are silently ignored.</para>
|
||
/// <para>This method is thread-safe.</para>
|
||
/// </remarks>
|
||
public virtual void RemoveObjects(ICollection modelObjects) {
|
||
if (this.InvokeRequired) {
|
||
this.Invoke((MethodInvoker)delegate() { this.RemoveObjects(modelObjects); });
|
||
return;
|
||
}
|
||
if (modelObjects == null)
|
||
return;
|
||
|
||
this.BeginUpdate();
|
||
try {
|
||
// Give the world a chance to cancel or change the added objects
|
||
ItemsRemovingEventArgs args = new ItemsRemovingEventArgs(modelObjects);
|
||
this.OnItemsRemoving(args);
|
||
if (args.Canceled)
|
||
return;
|
||
modelObjects = args.ObjectsToRemove;
|
||
|
||
this.TakeOwnershipOfObjects();
|
||
ArrayList ourObjects = ObjectListView.EnumerableToArray(this.Objects, false);
|
||
foreach (object modelObject in modelObjects) {
|
||
if (modelObject != null) {
|
||
// ReSharper disable PossibleMultipleEnumeration
|
||
int i = ourObjects.IndexOf(modelObject);
|
||
if (i >= 0)
|
||
ourObjects.RemoveAt(i);
|
||
// ReSharper restore PossibleMultipleEnumeration
|
||
i = this.IndexOf(modelObject);
|
||
if (i >= 0)
|
||
this.Items.RemoveAt(i);
|
||
}
|
||
}
|
||
this.PostProcessRows();
|
||
|
||
// Tell the world that the list has changed
|
||
this.UnsubscribeNotifications(modelObjects);
|
||
this.OnItemsChanged(new ItemsChangedEventArgs());
|
||
} finally {
|
||
this.EndUpdate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// ѡ<><D1A1><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
public virtual void SelectAll() {
|
||
NativeMethods.SelectAllItems(this);
|
||
}
|
||
|
||
/// <summary>
|
||
///<2F><><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD>½<EFBFBD><C2BD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>̶<EFBFBD><CCB6>ĸ<EFBFBD><C4B8><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD>
|
||
///<2F><><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD><F1B2BBBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// <20>˷<EFBFBD><CBB7><EFBFBD>ʹ<EFBFBD><CAB9>ListView<65><77>ԭ<EFBFBD><D4AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD>
|
||
/// <20><><EFBFBD>м<EFBFBD><D0BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD>
|
||
/// </para>
|
||
/// <list type="bullet">
|
||
/// <item><description><3E><><EFBFBD><EFBFBD>owner drawnģʽ<C4A3>²<EFBFBD><C2B2>ܺܺõع<C3B5><D8B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>owner drawn<77><6E><EFBFBD><EFBFBD>ģʽ<C4A3>£<EFBFBD>
|
||
/// ÿ<><C3BF><EFBFBD><EFBFBD>Ԫ<EFBFBD><EFBFBD><F1B6BCBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>DZ<EFBFBD><C7B1><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD>ı<EFBFBD><C4B1><EFBFBD><EFBFBD><EFBFBD></description></item>
|
||
/// <item><description><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǻܺã<DCBA><C3A3><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD>ϻ<EFBFBD><CFBB>Ƶġ<C6B5></description></item>
|
||
/// <item><description><3E><><EFBFBD><EFBFBD>XP<58><50><EFBFBD><EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>á<EFBFBD></description></item>
|
||
/// <item><description><3E><>Ȼ<EFBFBD><C8BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ý<EFBFBD><C3BD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ɫʱ<C9AB><CAB1>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD></description></item>
|
||
/// </list>
|
||
/// <para>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Щ<EFBFBD><D0A9><EFBFBD>ƣ<EFBFBD>ԭ<EFBFBD><D4AD>ˮӡ<CBAE><D3A1><EFBFBD>൱<EFBFBD><E0B5B1><EFBFBD><EFBFBD><EFBFBD>ˡ<EFBFBD>
|
||
///<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>ı<EFBFBD><C4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>OverlayImageʹ<65>õİ<C3B5><EFBFBD><CDB8><EFBFBD><EFBFBD><EFBFBD>ǡ<EFBFBD>
|
||
///<2F>븲<EFBFBD><EBB8B2><EFBFBD><EFBFBD><EFBFBD>ȣ<EFBFBD><C8A3><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD><EFBFBD>Ե<EFBFBD><D4B5><EFBFBD><EFBFBD>ƣ<EFBFBD><C6A3><EFBFBD>Ϊ<EFBFBD><CEAA>ʹ<EFBFBD><CAB9>MDIӦ<49>ó<EFBFBD><C3B3><EFBFBD><EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </para>
|
||
/// <para><3E><><EFBFBD>ô<EFBFBD>ѡ<EFBFBD><EFBFBD><EEBDAB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD></para>
|
||
/// </remarks>
|
||
/// <param name="image">The image to be drawn. If null, any existing image will be removed.</param>
|
||
public void SetNativeBackgroundWatermark(Image image) {
|
||
NativeMethods.SetBackgroundImage(this, image, true, false, 0, 0);
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ΪListView<65>ı<EFBFBD><C4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD>Ը<EFBFBD><D4B8><EFBFBD><EFBFBD>İٷֱ<D9B7>ƫ<EFBFBD><C6AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <see cref="SetNativeBackgroundWatermark"/><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD>.
|
||
/// <20><>ʹ<EFBFBD>ø÷<C3B8><C3B7><EFBFBD>֮ǰ<D6AE><C7B0><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD>˽<EFBFBD><CBBD><EFBFBD>Щ<EFBFBD><D0A9><EFBFBD>ơ<EFBFBD></para>
|
||
/// <para><3E><><EFBFBD>dz<EFBFBD><C7B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <see cref="System.Windows.Forms.Control.BackgroundImage"/> <20><><EFBFBD>ԣ<EFBFBD>
|
||
/// <20><><EFBFBD><EFBFBD>Backround Image<67><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><CDB8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC>--<2D><><EFBFBD><EFBFBD><EFBFBD><CDB8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>⡣</para>
|
||
/// <para><3E><><EFBFBD>ô<EFBFBD>ѡ<EFBFBD><EFBFBD><EEBDAB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ˮӡ<CBAE><D3A1></para>
|
||
/// </remarks>
|
||
/// <param name="image">The image to be drawn. If null, any existing image will be removed.</param>
|
||
/// <param name="xOffset">The horizontal percentage where the image will be placed. 0 is absolute left, 100 is absolute right.</param>
|
||
/// <param name="yOffset">The vertical percentage where the image will be placed.</param>
|
||
public void SetNativeBackgroundImage(Image image, int xOffset, int yOffset) {
|
||
NativeMethods.SetBackgroundImage(this, image, false, false, xOffset, yOffset);
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ΪListView<65><77>ƽ<EFBFBD>̱<EFBFBD><CCB1><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <see cref="SetNativeBackgroundWatermark"/> <20><> <see cref="SetNativeBackgroundImage"/> <20><>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
|
||
/// <20><>ʹ<EFBFBD>ø÷<C3B8><C3B7><EFBFBD>֮ǰ<D6AE><C7B0><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD>˽<EFBFBD><CBBD><EFBFBD>Щ<EFBFBD><D0A9><EFBFBD>ơ<EFBFBD></para>
|
||
/// </remarks>
|
||
/// <param name="image">Ҫ<><D2AA><EFBFBD>Ƶ<EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊnull<6C><6C><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɾ<EFBFBD><C9BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD></param>
|
||
public void SetNativeBackgroundTiledImage(Image image) {
|
||
NativeMethods.SetBackgroundImage(this, image, false, true, 0, 0);
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD>ý<EFBFBD><C3BD>ڴ<EFBFBD><DAB4>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD>ʾ<EFBFBD>Ķ<EFBFBD><C4B6>ϡ<F3BCAFBA>
|
||
/// </summary>
|
||
/// <remark><3E><><EFBFBD>ԴӺ<D4B4>̨<EFBFBD>̰߳<DFB3>ȫ<EFBFBD>ص<EFBFBD><D8B5>ô˷<C3B4><CBB7><EFBFBD><EFBFBD><EFBFBD></remark>
|
||
/// <remarks><3E><><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></remarks>
|
||
/// <param name="collection">The objects to be displayed</param>
|
||
public virtual void SetObjects(IEnumerable collection) {
|
||
this.SetObjects(collection, false);
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD>ý<EFBFBD><C3BD>ڴ<EFBFBD><DAB4>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD>ʾ<EFBFBD>Ķ<EFBFBD><C4B6>ϡ<F3BCAFBA>
|
||
/// </summary>
|
||
/// <remark><3E><><EFBFBD>ԴӺ<D4B4>̨<EFBFBD>̰߳<DFB3>ȫ<EFBFBD>ص<EFBFBD><D8B5>ô˷<C3B4><CBB7><EFBFBD>.</remark>
|
||
/// <remarks><3E><><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></remarks>
|
||
/// <param name="collection">The objects to be displayed</param>
|
||
/// <param name="preserveState"><3E>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD>ܱ<EFBFBD><DCB1><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>״̬<D7B4><CCAC></param>
|
||
public virtual void SetObjects(IEnumerable collection, bool preserveState) {
|
||
if (this.InvokeRequired) {
|
||
this.Invoke((MethodInvoker)delegate { this.SetObjects(collection, preserveState); });
|
||
return;
|
||
}
|
||
|
||
// Give the world a chance to cancel or change the assigned collection
|
||
ItemsChangingEventArgs args = new ItemsChangingEventArgs(this.objects, collection);
|
||
this.OnItemsChanging(args);
|
||
if (args.Canceled)
|
||
return;
|
||
collection = args.NewObjects;
|
||
|
||
// If we own the current list and they change to another list, we don't own it anymore
|
||
if (this.isOwnerOfObjects && !ReferenceEquals(this.objects, collection))
|
||
this.isOwnerOfObjects = false;
|
||
this.objects = collection;
|
||
this.BuildList(preserveState);
|
||
|
||
// Tell the world that the list has changed
|
||
this.UpdateNotificationSubscriptions(this.objects);
|
||
this.OnItemsChanged(new ItemsChangedEventArgs());
|
||
}
|
||
|
||
/// <summary>
|
||
///<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD>ListView<65>С<EFBFBD>
|
||
///<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD>в<EFBFBD><D0B2><EFBFBD><EFBFBD>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӹ<EFBFBD>ģ<EFBFBD>͡<EFBFBD>
|
||
/// </summary>
|
||
/// <param name="modelObject">The model to be updated</param>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// See <see cref="RemoveObjects(ICollection)"/> for more details
|
||
/// </para>
|
||
/// <para><3E>˷<EFBFBD><CBB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̰߳<DFB3>ȫ<EFBFBD>ġ<EFBFBD></para>
|
||
/// <para><3E>˷<EFBFBD><CBB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD></para>
|
||
/// <para><3E>˷<EFBFBD><CBB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ObjectListViews<77><73>FastObjectListViews<77><73></para>
|
||
/// </remarks>
|
||
public virtual void UpdateObject(object modelObject) {
|
||
if (this.InvokeRequired)
|
||
this.Invoke((MethodInvoker)delegate() { this.UpdateObject(modelObject); });
|
||
else
|
||
this.UpdateObjects(new object[] { modelObject });
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȵ<EFBFBD>Ԥ<EFBFBD>ȴ<EFBFBD><C8B4>ڵ<EFBFBD>ģ<EFBFBD>͡<EFBFBD>
|
||
///<2F><><EFBFBD><EFBFBD><EFBFBD>ؼ<EFBFBD><D8BC>в<EFBFBD><D0B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>κ<EFBFBD>ģ<EFBFBD>ͣ<EFBFBD><CDA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǡ<EFBFBD>
|
||
/// </summary>
|
||
/// <param name="modelObjects">Collection of objects to be updated/added</param>
|
||
/// <remarks>
|
||
/// <para><3E>˷<EFBFBD><CBB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD></para>
|
||
/// <para>nullֵ<6C><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><C4AC><EFBFBD>ԡ<EFBFBD></para>
|
||
/// <para><3E>˷<EFBFBD><CBB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̰߳<DFB3>ȫ<EFBFBD>ġ<EFBFBD></para>
|
||
/// <para><3E>˷<EFBFBD><CBB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ObjectListViews<77><73>FastObjectListViews<77><73></para>
|
||
/// </remarks>
|
||
public virtual void UpdateObjects(ICollection modelObjects) {
|
||
if (this.InvokeRequired) {
|
||
this.Invoke((MethodInvoker)delegate() { this.UpdateObjects(modelObjects); });
|
||
return;
|
||
}
|
||
if (modelObjects == null || modelObjects.Count == 0)
|
||
return;
|
||
|
||
this.BeginUpdate();
|
||
try {
|
||
this.UnsubscribeNotifications(modelObjects);
|
||
|
||
ArrayList objectsToAdd = new ArrayList();
|
||
|
||
this.TakeOwnershipOfObjects();
|
||
ArrayList ourObjects = ObjectListView.EnumerableToArray(this.Objects, false);
|
||
foreach (object modelObject in modelObjects) {
|
||
if (modelObject != null) {
|
||
int i = ourObjects.IndexOf(modelObject);
|
||
if (i < 0)
|
||
objectsToAdd.Add(modelObject);
|
||
else {
|
||
ourObjects[i] = modelObject;
|
||
OLVListItem olvi = this.ModelToItem(modelObject);
|
||
if (olvi != null) {
|
||
olvi.RowObject = modelObject;
|
||
this.RefreshItem(olvi);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
this.PostProcessRows();
|
||
|
||
this.AddObjects(objectsToAdd);
|
||
|
||
// Tell the world that the list has changed
|
||
this.SubscribeNotifications(modelObjects);
|
||
this.OnItemsChanged(new ItemsChangedEventArgs());
|
||
}
|
||
finally {
|
||
this.EndUpdate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD>ĵ<EFBFBD>ǰģ<C7B0>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD>϶<EFBFBD>INotifyPropertyChanged<65>¼<EFBFBD><C2BC><EFBFBD><EFBFBD>κζ<CEBA><CEB6>ģ<EFBFBD>
|
||
/// <20>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD>Dz<EFBFBD><C7B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD>ϵ<EFBFBD><CFB5>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5>¼<EFBFBD><C2BC><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>This does nothing if UseNotifyPropertyChanged is false.</remarks>
|
||
/// <param name="collection"></param>
|
||
protected virtual void UpdateNotificationSubscriptions(IEnumerable collection) {
|
||
if (!this.UseNotifyPropertyChanged)
|
||
return;
|
||
|
||
// We could calculate a symmetric difference between the old models and the new models
|
||
// except that we don't have the previous models at this point.
|
||
|
||
this.UnsubscribeNotifications(null);
|
||
this.SubscribeNotifications(collection ?? this.Objects);
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ObjectListView<65>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD>ϵ<EFBFBD>INotifyPropertyChanged<65>¼<EFBFBD><C2BC><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// <20><>Ӧ<EFBFBD><D3A6><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD>SetObjects()֮ǰ<D6AE><C7B0><EFBFBD>á<EFBFBD><C3A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ΪFalse<73><65>ObjectListView<65><77>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>ǰģ<C7B0>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </para>
|
||
/// <para><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1>Ͻ<EFBFBD><CFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊtrue<75><65>ObjectListView<65><77><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1>г<EFBFBD><D0B3>Զ<EFBFBD><D4B6>ĸ<EFBFBD><C4B8><EFBFBD>֪ͨ<CDA8><D6AA><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD>10,000,000<30><30><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҪһЩʱ<D0A9>䡣</para>
|
||
/// </remarks>
|
||
[Category("ObjectListView"),
|
||
Description("Should ObjectListView listen for property changed events on the model objects?"),
|
||
DefaultValue(false)]
|
||
public bool UseNotifyPropertyChanged {
|
||
get { return this.useNotifyPropertyChanged; }
|
||
set {
|
||
if (this.useNotifyPropertyChanged == value)
|
||
return;
|
||
this.useNotifyPropertyChanged = value;
|
||
if (value)
|
||
this.SubscribeNotifications(this.Objects);
|
||
else
|
||
this.UnsubscribeNotifications(null);
|
||
}
|
||
}
|
||
private bool useNotifyPropertyChanged;
|
||
|
||
/// <summary>
|
||
/// Subscribe to INotifyPropertyChanges on the given collection of objects.
|
||
/// </summary>
|
||
/// <param name="models"></param>
|
||
protected void SubscribeNotifications(IEnumerable models) {
|
||
if (!this.UseNotifyPropertyChanged || models == null)
|
||
return;
|
||
foreach (object x in models) {
|
||
INotifyPropertyChanged notifier = x as INotifyPropertyChanged;
|
||
if (notifier != null && !subscribedModels.ContainsKey(notifier)) {
|
||
notifier.PropertyChanged += HandleModelOnPropertyChanged;
|
||
subscribedModels[notifier] = notifier;
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Unsubscribe from INotifyPropertyChanges on the given collection of objects.
|
||
/// If the given collection is null, unsubscribe from all current subscriptions
|
||
/// </summary>
|
||
/// <param name="models"></param>
|
||
protected void UnsubscribeNotifications(IEnumerable models) {
|
||
if (models == null) {
|
||
foreach (INotifyPropertyChanged notifier in this.subscribedModels.Keys) {
|
||
notifier.PropertyChanged -= HandleModelOnPropertyChanged;
|
||
}
|
||
subscribedModels = new Hashtable();
|
||
} else {
|
||
foreach (object x in models) {
|
||
INotifyPropertyChanged notifier = x as INotifyPropertyChanged;
|
||
if (notifier != null) {
|
||
notifier.PropertyChanged -= HandleModelOnPropertyChanged;
|
||
subscribedModels.Remove(notifier);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private void HandleModelOnPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs) {
|
||
// System.Diagnostics.Debug.WriteLine(String.Format("PropertyChanged: '{0}' on '{1}", propertyChangedEventArgs.PropertyName, sender));
|
||
this.RefreshObject(sender);
|
||
}
|
||
|
||
private Hashtable subscribedModels = new Hashtable();
|
||
|
||
#endregion
|
||
|
||
#region Save/Restore State
|
||
|
||
/// <summary>
|
||
/// Return a byte array that represents the current state of the ObjectListView, such
|
||
/// that the state can be restored by RestoreState()
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>The state of an ObjectListView includes the attributes that the user can modify:
|
||
/// <list type="bullet">
|
||
/// <item><description>current view (i.e. Details, Tile, Large Icon...)</description></item>
|
||
/// <item><description>sort column and direction</description></item>
|
||
/// <item><description>column order</description></item>
|
||
/// <item><description>column widths</description></item>
|
||
/// <item><description>column visibility</description></item>
|
||
/// </list>
|
||
/// </para>
|
||
/// <para>
|
||
/// It does not include selection or the scroll position.
|
||
/// </para>
|
||
/// </remarks>
|
||
/// <returns>A byte array representing the state of the ObjectListView</returns>
|
||
public virtual byte[] SaveState() {
|
||
ObjectListViewState olvState = new ObjectListViewState();
|
||
olvState.VersionNumber = 1;
|
||
olvState.NumberOfColumns = this.AllColumns.Count;
|
||
olvState.CurrentView = this.View;
|
||
|
||
// If we have a sort column, it is possible that it is not currently being shown, in which
|
||
// case, it's Index will be -1. So we calculate its index directly. Technically, the sort
|
||
// column does not even have to a member of AllColumns, in which case IndexOf will return -1,
|
||
// which is works fine since we have no way of restoring such a column anyway.
|
||
if (this.PrimarySortColumn != null)
|
||
olvState.SortColumn = this.AllColumns.IndexOf(this.PrimarySortColumn);
|
||
olvState.LastSortOrder = this.PrimarySortOrder;
|
||
olvState.IsShowingGroups = this.ShowGroups;
|
||
|
||
if (this.AllColumns.Count > 0 && this.AllColumns[0].LastDisplayIndex == -1)
|
||
this.RememberDisplayIndicies();
|
||
|
||
foreach (OLVColumn column in this.AllColumns) {
|
||
olvState.ColumnIsVisible.Add(column.IsVisible);
|
||
olvState.ColumnDisplayIndicies.Add(column.LastDisplayIndex);
|
||
olvState.ColumnWidths.Add(column.Width);
|
||
}
|
||
|
||
// Now that we have stored our state, convert it to a byte array
|
||
using (MemoryStream ms = new MemoryStream()) {
|
||
BinaryFormatter serializer = new BinaryFormatter();
|
||
serializer.AssemblyFormat = FormatterAssemblyStyle.Simple;
|
||
serializer.Serialize(ms, olvState);
|
||
return ms.ToArray();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Restore the state of the control from the given string, which must have been
|
||
/// produced by SaveState()
|
||
/// </summary>
|
||
/// <param name="state">A byte array returned from SaveState()</param>
|
||
/// <returns>Returns true if the state was restored</returns>
|
||
public virtual bool RestoreState(byte[] state) {
|
||
using (MemoryStream ms = new MemoryStream(state)) {
|
||
BinaryFormatter deserializer = new BinaryFormatter();
|
||
ObjectListViewState olvState;
|
||
try {
|
||
olvState = deserializer.Deserialize(ms) as ObjectListViewState;
|
||
} catch (System.Runtime.Serialization.SerializationException) {
|
||
return false;
|
||
}
|
||
// The number of columns has changed. We have no way to match old
|
||
// columns to the new ones, so we just give up.
|
||
if (olvState == null || olvState.NumberOfColumns != this.AllColumns.Count)
|
||
return false;
|
||
if (olvState.SortColumn == -1) {
|
||
this.PrimarySortColumn = null;
|
||
this.PrimarySortOrder = SortOrder.None;
|
||
} else {
|
||
this.PrimarySortColumn = this.AllColumns[olvState.SortColumn];
|
||
this.PrimarySortOrder = olvState.LastSortOrder;
|
||
}
|
||
for (int i = 0; i < olvState.NumberOfColumns; i++) {
|
||
OLVColumn column = this.AllColumns[i];
|
||
column.Width = (int)olvState.ColumnWidths[i];
|
||
column.IsVisible = (bool)olvState.ColumnIsVisible[i];
|
||
column.LastDisplayIndex = (int)olvState.ColumnDisplayIndicies[i];
|
||
}
|
||
// ReSharper disable RedundantCheckBeforeAssignment
|
||
if (olvState.IsShowingGroups != this.ShowGroups)
|
||
// ReSharper restore RedundantCheckBeforeAssignment
|
||
this.ShowGroups = olvState.IsShowingGroups;
|
||
if (this.View == olvState.CurrentView)
|
||
this.RebuildColumns();
|
||
else
|
||
this.View = olvState.CurrentView;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Instances of this class are used to store the state of an ObjectListView.
|
||
/// </summary>
|
||
[Serializable]
|
||
internal class ObjectListViewState
|
||
{
|
||
// ReSharper disable NotAccessedField.Global
|
||
public int VersionNumber = 1;
|
||
// ReSharper restore NotAccessedField.Global
|
||
public int NumberOfColumns = 1;
|
||
public View CurrentView;
|
||
public int SortColumn = -1;
|
||
public bool IsShowingGroups;
|
||
public SortOrder LastSortOrder = SortOrder.None;
|
||
// ReSharper disable FieldCanBeMadeReadOnly.Global
|
||
public ArrayList ColumnIsVisible = new ArrayList();
|
||
public ArrayList ColumnDisplayIndicies = new ArrayList();
|
||
public ArrayList ColumnWidths = new ArrayList();
|
||
// ReSharper restore FieldCanBeMadeReadOnly.Global
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Event handlers
|
||
|
||
/// <summary>
|
||
/// The application is idle. Trigger a SelectionChanged event.
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
protected virtual void HandleApplicationIdle(object sender, EventArgs e) {
|
||
// Remove the handler before triggering the event
|
||
Application.Idle -= new EventHandler(HandleApplicationIdle);
|
||
this.hasIdleHandler = false;
|
||
|
||
this.OnSelectionChanged(new EventArgs());
|
||
}
|
||
|
||
/// <summary>
|
||
/// The application is idle. Handle the column resizing event.
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
protected virtual void HandleApplicationIdleResizeColumns(object sender, EventArgs e) {
|
||
// Remove the handler before triggering the event
|
||
Application.Idle -= new EventHandler(this.HandleApplicationIdleResizeColumns);
|
||
this.hasResizeColumnsHandler = false;
|
||
|
||
this.ResizeFreeSpaceFillingColumns();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handle the BeginScroll listview notification
|
||
/// </summary>
|
||
/// <param name="m"></param>
|
||
/// <returns>True if the event was completely handled</returns>
|
||
protected virtual bool HandleBeginScroll(ref Message m) {
|
||
//System.Diagnostics.Debug.WriteLine("LVN_BEGINSCROLL");
|
||
|
||
NativeMethods.NMLVSCROLL nmlvscroll = (NativeMethods.NMLVSCROLL)m.GetLParam(typeof(NativeMethods.NMLVSCROLL));
|
||
if (nmlvscroll.dx != 0) {
|
||
int scrollPositionH = NativeMethods.GetScrollPosition(this, true);
|
||
ScrollEventArgs args = new ScrollEventArgs(ScrollEventType.EndScroll, scrollPositionH - nmlvscroll.dx, scrollPositionH, ScrollOrientation.HorizontalScroll);
|
||
this.OnScroll(args);
|
||
|
||
// Force any empty list msg to redraw when the list is scrolled horizontally
|
||
if (this.GetItemCount() == 0)
|
||
this.Invalidate();
|
||
}
|
||
if (nmlvscroll.dy != 0) {
|
||
int scrollPositionV = NativeMethods.GetScrollPosition(this, false);
|
||
ScrollEventArgs args = new ScrollEventArgs(ScrollEventType.EndScroll, scrollPositionV - nmlvscroll.dy, scrollPositionV, ScrollOrientation.VerticalScroll);
|
||
this.OnScroll(args);
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handle the EndScroll listview notification
|
||
/// </summary>
|
||
/// <param name="m"></param>
|
||
/// <returns>True if the event was completely handled</returns>
|
||
protected virtual bool HandleEndScroll(ref Message m) {
|
||
//System.Diagnostics.Debug.WriteLine("LVN_BEGINSCROLL");
|
||
|
||
// There is a bug in ListView under XP that causes the gridlines to be incorrectly scrolled
|
||
// when the left button is clicked to scroll. This is supposedly documented at
|
||
// KB 813791, but I couldn't find it anywhere. You can follow this thread to see the discussion
|
||
// http://www.ureader.com/msg/1484143.aspx
|
||
|
||
if (!ObjectListView.IsVistaOrLater && ObjectListView.IsLeftMouseDown && this.GridLines) {
|
||
this.Invalidate();
|
||
this.Update();
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handle the LinkClick listview notification
|
||
/// </summary>
|
||
/// <param name="m"></param>
|
||
/// <returns>True if the event was completely handled</returns>
|
||
protected virtual bool HandleLinkClick(ref Message m) {
|
||
//System.Diagnostics.Debug.WriteLine("HandleLinkClick");
|
||
|
||
NativeMethods.NMLVLINK nmlvlink = (NativeMethods.NMLVLINK)m.GetLParam(typeof(NativeMethods.NMLVLINK));
|
||
|
||
// Find the group that was clicked and trigger an event
|
||
foreach (OLVGroup x in this.OLVGroups) {
|
||
if (x.GroupId == nmlvlink.iSubItem) {
|
||
this.OnGroupTaskClicked(new GroupTaskClickedEventArgs(x));
|
||
return true;
|
||
}
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// The cell tooltip control wants information about the tool tip that it should show.
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
protected virtual void HandleCellToolTipShowing(object sender, ToolTipShowingEventArgs e) {
|
||
this.BuildCellEvent(e, this.PointToClient(Cursor.Position));
|
||
if (e.Item != null) {
|
||
e.Text = this.GetCellToolTip(e.ColumnIndex, e.RowIndex);
|
||
this.OnCellToolTip(e);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Allow the HeaderControl to call back into HandleHeaderToolTipShowing without making that method public
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
internal void HeaderToolTipShowingCallback(object sender, ToolTipShowingEventArgs e) {
|
||
this.HandleHeaderToolTipShowing(sender, e);
|
||
}
|
||
|
||
/// <summary>
|
||
/// The header tooltip control wants information about the tool tip that it should show.
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
protected virtual void HandleHeaderToolTipShowing(object sender, ToolTipShowingEventArgs e) {
|
||
e.ColumnIndex = this.HeaderControl.ColumnIndexUnderCursor;
|
||
if (e.ColumnIndex < 0)
|
||
return;
|
||
|
||
e.RowIndex = -1;
|
||
e.Model = null;
|
||
e.Column = this.GetColumn(e.ColumnIndex);
|
||
e.Text = this.GetHeaderToolTip(e.ColumnIndex);
|
||
e.ListView = this;
|
||
this.OnHeaderToolTip(e);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Event handler for the column click event
|
||
/// </summary>
|
||
protected virtual void HandleColumnClick(object sender, ColumnClickEventArgs e) {
|
||
if (!this.PossibleFinishCellEditing())
|
||
return;
|
||
|
||
// Toggle the sorting direction on successive clicks on the same column
|
||
if (this.PrimarySortColumn != null && e.Column == this.PrimarySortColumn.Index)
|
||
this.PrimarySortOrder = (this.PrimarySortOrder == SortOrder.Descending ? SortOrder.Ascending : SortOrder.Descending);
|
||
else
|
||
this.PrimarySortOrder = SortOrder.Ascending;
|
||
|
||
this.BeginUpdate();
|
||
try {
|
||
this.Sort(e.Column);
|
||
} finally {
|
||
this.EndUpdate();
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Low level Windows Message handling
|
||
|
||
/// <summary>
|
||
/// Override the basic message pump for this control
|
||
/// </summary>
|
||
/// <param name="m"></param>
|
||
protected override void WndProc(ref Message m)
|
||
{
|
||
|
||
// System.Diagnostics.Debug.WriteLine(m.Msg);
|
||
switch (m.Msg) {
|
||
case 2: // WM_DESTROY
|
||
if (!this.HandleDestroy(ref m))
|
||
base.WndProc(ref m);
|
||
break;
|
||
//case 0x14: // WM_ERASEBKGND
|
||
// Can't do anything here since, when the control is double buffered, anything
|
||
// done here is immediately over-drawn
|
||
// break;
|
||
case 0x0F: // WM_PAINT
|
||
if (!this.HandlePaint(ref m))
|
||
base.WndProc(ref m);
|
||
break;
|
||
case 0x46: // WM_WINDOWPOSCHANGING
|
||
if (this.PossibleFinishCellEditing() && !this.HandleWindowPosChanging(ref m))
|
||
base.WndProc(ref m);
|
||
break;
|
||
case 0x4E: // WM_NOTIFY
|
||
if (!this.HandleNotify(ref m))
|
||
base.WndProc(ref m);
|
||
break;
|
||
case 0x0100: // WM_KEY_DOWN
|
||
if (!this.HandleKeyDown(ref m))
|
||
base.WndProc(ref m);
|
||
break;
|
||
case 0x0102: // WM_CHAR
|
||
if (!this.HandleChar(ref m))
|
||
base.WndProc(ref m);
|
||
break;
|
||
case 0x0200: // WM_MOUSEMOVE
|
||
if (!this.HandleMouseMove(ref m))
|
||
base.WndProc(ref m);
|
||
break;
|
||
case 0x0201: // WM_LBUTTONDOWN
|
||
if (this.PossibleFinishCellEditing() && !this.HandleLButtonDown(ref m))
|
||
base.WndProc(ref m);
|
||
break;
|
||
case 0x202: // WM_LBUTTONUP
|
||
if (this.PossibleFinishCellEditing() && !this.HandleLButtonUp(ref m))
|
||
base.WndProc(ref m);
|
||
break;
|
||
case 0x0203: // WM_LBUTTONDBLCLK
|
||
if (this.PossibleFinishCellEditing() && !this.HandleLButtonDoubleClick(ref m))
|
||
base.WndProc(ref m);
|
||
break;
|
||
case 0x0204: // WM_RBUTTONDOWN
|
||
if (this.PossibleFinishCellEditing() && !this.HandleRButtonDown(ref m))
|
||
base.WndProc(ref m);
|
||
break;
|
||
case 0x0206: // WM_RBUTTONDBLCLK
|
||
if (this.PossibleFinishCellEditing() && !this.HandleRButtonDoubleClick(ref m))
|
||
base.WndProc(ref m);
|
||
break;
|
||
case 0x204E: // WM_REFLECT_NOTIFY
|
||
if (!this.HandleReflectNotify(ref m))
|
||
base.WndProc(ref m);
|
||
break;
|
||
case 0x114: // WM_HSCROLL:
|
||
case 0x115: // WM_VSCROLL:
|
||
//System.Diagnostics.Debug.WriteLine("WM_VSCROLL");
|
||
if (this.PossibleFinishCellEditing())
|
||
base.WndProc(ref m);
|
||
break;
|
||
case 0x20A: // WM_MOUSEWHEEL:
|
||
case 0x20E: // WM_MOUSEHWHEEL:
|
||
if (this.PossibleFinishCellEditing())
|
||
base.WndProc(ref m);
|
||
break;
|
||
case 0x7B: // WM_CONTEXTMENU
|
||
if (!this.HandleContextMenu(ref m))
|
||
base.WndProc(ref m);
|
||
break;
|
||
case 0x1000 + 18: // LVM_HITTEST:
|
||
//System.Diagnostics.Debug.WriteLine("LVM_HITTEST");
|
||
if (this.skipNextHitTest) {
|
||
//System.Diagnostics.Debug.WriteLine("SKIPPING LVM_HITTEST");
|
||
this.skipNextHitTest = false;
|
||
} else {
|
||
base.WndProc(ref m);
|
||
}
|
||
break;
|
||
default:
|
||
base.WndProc(ref m);
|
||
break;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handle the search for item m if possible.
|
||
/// </summary>
|
||
/// <param name="m">The m to be processed</param>
|
||
/// <returns>bool to indicate if the msg has been handled</returns>
|
||
protected virtual bool HandleChar(ref Message m) {
|
||
|
||
// Trigger a normal KeyPress event, which listeners can handle if they want.
|
||
// Handling the event stops ObjectListView's fancy search-by-typing.
|
||
if (this.ProcessKeyEventArgs(ref m))
|
||
return true;
|
||
|
||
const int MILLISECONDS_BETWEEN_KEYPRESSES = 1000;
|
||
|
||
// What character did the user type and was it part of a longer string?
|
||
char character = (char)m.WParam.ToInt32(); //TODO: Will this work on 64 bit or MBCS?
|
||
if (character == (char)Keys.Back) {
|
||
// Backspace forces the next key to be considered the start of a new search
|
||
this.timeLastCharEvent = 0;
|
||
return true;
|
||
}
|
||
|
||
if (System.Environment.TickCount < (this.timeLastCharEvent + MILLISECONDS_BETWEEN_KEYPRESSES))
|
||
this.lastSearchString += character;
|
||
else
|
||
this.lastSearchString = character.ToString(CultureInfo.InvariantCulture);
|
||
|
||
// If this control is showing checkboxes, we want to ignore single space presses,
|
||
// since they are used to toggle the selected checkboxes.
|
||
if (this.CheckBoxes && this.lastSearchString == " ") {
|
||
this.timeLastCharEvent = 0;
|
||
return true;
|
||
}
|
||
|
||
// Where should the search start?
|
||
int start = 0;
|
||
ListViewItem focused = this.FocusedItem;
|
||
if (focused != null) {
|
||
start = this.GetDisplayOrderOfItemIndex(focused.Index);
|
||
|
||
// If the user presses a single key, we search from after the focused item,
|
||
// being careful not to march past the end of the list
|
||
if (this.lastSearchString.Length == 1) {
|
||
start += 1;
|
||
if (start == this.GetItemCount())
|
||
start = 0;
|
||
}
|
||
}
|
||
|
||
// Give the world a chance to fiddle with or completely avoid the searching process
|
||
BeforeSearchingEventArgs args = new BeforeSearchingEventArgs(this.lastSearchString, start);
|
||
this.OnBeforeSearching(args);
|
||
if (args.Canceled)
|
||
return true;
|
||
|
||
// The parameters of the search may have been changed
|
||
string searchString = args.StringToFind;
|
||
start = args.StartSearchFrom;
|
||
|
||
// Do the actual search
|
||
int found = this.FindMatchingRow(searchString, start, SearchDirectionHint.Down);
|
||
if (found >= 0) {
|
||
// Select and focus on the found item
|
||
this.BeginUpdate();
|
||
try {
|
||
this.SelectedIndices.Clear();
|
||
OLVListItem lvi = this.GetNthItemInDisplayOrder(found);
|
||
if (lvi != null) {
|
||
if (lvi.Enabled)
|
||
lvi.Selected = true;
|
||
lvi.Focused = true;
|
||
this.EnsureVisible(lvi.Index);
|
||
}
|
||
} finally {
|
||
this.EndUpdate();
|
||
}
|
||
}
|
||
|
||
// Tell the world that a search has occurred
|
||
AfterSearchingEventArgs args2 = new AfterSearchingEventArgs(searchString, found);
|
||
this.OnAfterSearching(args2);
|
||
if (!args2.Handled) {
|
||
if (found < 0)
|
||
System.Media.SystemSounds.Beep.Play();
|
||
}
|
||
|
||
// When did this event occur?
|
||
this.timeLastCharEvent = System.Environment.TickCount;
|
||
return true;
|
||
}
|
||
private int timeLastCharEvent;
|
||
private string lastSearchString;
|
||
|
||
/// <summary>
|
||
/// The user wants to see the context menu.
|
||
/// </summary>
|
||
/// <param name="m">The windows m</param>
|
||
/// <returns>A bool indicating if this m has been handled</returns>
|
||
/// <remarks>
|
||
/// We want to ignore context menu requests that are triggered by right clicks on the header
|
||
/// </remarks>
|
||
protected virtual bool HandleContextMenu(ref Message m) {
|
||
// Don't try to handle context menu commands at design time.
|
||
if (this.DesignMode)
|
||
return false;
|
||
|
||
// If the context menu command was generated by the keyboard, LParam will be -1.
|
||
// We don't want to process these.
|
||
if (m.LParam == this.minusOne)
|
||
return false;
|
||
|
||
// If the context menu came from somewhere other than the header control,
|
||
// we also don't want to ignore it
|
||
if (m.WParam != this.HeaderControl.Handle)
|
||
return false;
|
||
|
||
// OK. Looks like a right click in the header
|
||
if (!this.PossibleFinishCellEditing())
|
||
return true;
|
||
|
||
int columnIndex = this.HeaderControl.ColumnIndexUnderCursor;
|
||
return this.HandleHeaderRightClick(columnIndex);
|
||
}
|
||
readonly IntPtr minusOne = new IntPtr(-1);
|
||
|
||
/// <summary>
|
||
/// Handle the Custom draw series of notifications
|
||
/// </summary>
|
||
/// <param name="m">The message</param>
|
||
/// <returns>True if the message has been handled</returns>
|
||
protected virtual bool HandleCustomDraw(ref Message m) {
|
||
const int CDDS_PREPAINT = 1;
|
||
const int CDDS_POSTPAINT = 2;
|
||
const int CDDS_PREERASE = 3;
|
||
const int CDDS_POSTERASE = 4;
|
||
//const int CDRF_NEWFONT = 2;
|
||
//const int CDRF_SKIPDEFAULT = 4;
|
||
const int CDDS_ITEM = 0x00010000;
|
||
const int CDDS_SUBITEM = 0x00020000;
|
||
const int CDDS_ITEMPREPAINT = (CDDS_ITEM | CDDS_PREPAINT);
|
||
const int CDDS_ITEMPOSTPAINT = (CDDS_ITEM | CDDS_POSTPAINT);
|
||
const int CDDS_ITEMPREERASE = (CDDS_ITEM | CDDS_PREERASE);
|
||
const int CDDS_ITEMPOSTERASE = (CDDS_ITEM | CDDS_POSTERASE);
|
||
const int CDDS_SUBITEMPREPAINT = (CDDS_SUBITEM | CDDS_ITEMPREPAINT);
|
||
const int CDDS_SUBITEMPOSTPAINT = (CDDS_SUBITEM | CDDS_ITEMPOSTPAINT);
|
||
const int CDRF_NOTIFYPOSTPAINT = 0x10;
|
||
//const int CDRF_NOTIFYITEMDRAW = 0x20;
|
||
//const int CDRF_NOTIFYSUBITEMDRAW = 0x20; // same value as above!
|
||
const int CDRF_NOTIFYPOSTERASE = 0x40;
|
||
|
||
// There is a bug in owner drawn virtual lists which causes lots of custom draw messages
|
||
// to be sent to the control *outside* of a WmPaint event. AFAIK, these custom draw events
|
||
// are spurious and only serve to make the control flicker annoyingly.
|
||
// So, we ignore messages that are outside of a paint event.
|
||
if (!this.isInWmPaintEvent)
|
||
return true;
|
||
|
||
// One more complication! Sometimes with owner drawn virtual lists, the act of drawing
|
||
// the overlays triggers a second attempt to paint the control -- which makes an annoying
|
||
// flicker. So, we only do the custom drawing once per WmPaint event.
|
||
if (!this.shouldDoCustomDrawing)
|
||
return true;
|
||
|
||
NativeMethods.NMLVCUSTOMDRAW nmcustomdraw = (NativeMethods.NMLVCUSTOMDRAW)m.GetLParam(typeof(NativeMethods.NMLVCUSTOMDRAW));
|
||
//System.Diagnostics.Debug.WriteLine(String.Format("cd: {0:x}, {1}, {2}", nmcustomdraw.nmcd.dwDrawStage, nmcustomdraw.dwItemType, nmcustomdraw.nmcd.dwItemSpec));
|
||
|
||
// Ignore drawing of group items
|
||
if (nmcustomdraw.dwItemType == 1) {
|
||
// This is the basis of an idea about how to owner draw group headers
|
||
|
||
//nmcustomdraw.clrText = ColorTranslator.ToWin32(Color.DeepPink);
|
||
//nmcustomdraw.clrFace = ColorTranslator.ToWin32(Color.DeepPink);
|
||
//nmcustomdraw.clrTextBk = ColorTranslator.ToWin32(Color.DeepPink);
|
||
//Marshal.StructureToPtr(nmcustomdraw, m.LParam, false);
|
||
//using (Graphics g = Graphics.FromHdc(nmcustomdraw.nmcd.hdc)) {
|
||
// g.DrawRectangle(Pens.Red, Rectangle.FromLTRB(nmcustomdraw.rcText.left, nmcustomdraw.rcText.top, nmcustomdraw.rcText.right, nmcustomdraw.rcText.bottom));
|
||
//}
|
||
//m.Result = (IntPtr)((int)m.Result | CDRF_SKIPDEFAULT);
|
||
return true;
|
||
}
|
||
|
||
switch (nmcustomdraw.nmcd.dwDrawStage) {
|
||
case CDDS_PREPAINT:
|
||
//System.Diagnostics.Debug.WriteLine("CDDS_PREPAINT");
|
||
// Remember which items were drawn during this paint cycle
|
||
if (this.prePaintLevel == 0)
|
||
this.drawnItems = new List<OLVListItem>();
|
||
|
||
// If there are any items, we have to wait until at least one has been painted
|
||
// before we draw the overlays. If there aren't any items, there will never be any
|
||
// item paint events, so we can draw the overlays whenever
|
||
this.isAfterItemPaint = (this.GetItemCount() == 0);
|
||
this.prePaintLevel++;
|
||
base.WndProc(ref m);
|
||
|
||
// Make sure that we get postpaint notifications
|
||
m.Result = (IntPtr)((int)m.Result | CDRF_NOTIFYPOSTPAINT | CDRF_NOTIFYPOSTERASE);
|
||
return true;
|
||
|
||
case CDDS_POSTPAINT:
|
||
//System.Diagnostics.Debug.WriteLine("CDDS_POSTPAINT");
|
||
this.prePaintLevel--;
|
||
|
||
// When in group view, we have two problems. On XP, the control sends
|
||
// a whole heap of PREPAINT/POSTPAINT messages before drawing any items.
|
||
// We have to wait until after the first item paint before we draw overlays.
|
||
// On Vista, we have a different problem. On Vista, the control nests calls
|
||
// to PREPAINT and POSTPAINT. We only want to draw overlays on the outermost
|
||
// POSTPAINT.
|
||
if (this.prePaintLevel == 0 && (this.isMarqueSelecting || this.isAfterItemPaint)) {
|
||
this.shouldDoCustomDrawing = false;
|
||
|
||
// Draw our overlays after everything has been drawn
|
||
using (Graphics g = Graphics.FromHdc(nmcustomdraw.nmcd.hdc)) {
|
||
this.DrawAllDecorations(g, this.drawnItems);
|
||
}
|
||
}
|
||
break;
|
||
|
||
case CDDS_ITEMPREPAINT:
|
||
//System.Diagnostics.Debug.WriteLine("CDDS_ITEMPREPAINT");
|
||
|
||
// When in group view on XP, the control send a whole heap of PREPAINT/POSTPAINT
|
||
// messages before drawing any items.
|
||
// We have to wait until after the first item paint before we draw overlays
|
||
this.isAfterItemPaint = true;
|
||
|
||
// This scheme of catching custom draw msgs works fine, except
|
||
// for Tile view. Something in .NET's handling of Tile view causes lots
|
||
// of invalidates and erases. So, we just ignore completely
|
||
// .NET's handling of Tile view and let the underlying control
|
||
// do its stuff. Strangely, if the Tile view is
|
||
// completely owner drawn, those erasures don't happen.
|
||
if (this.View == View.Tile) {
|
||
if (this.OwnerDraw && this.ItemRenderer != null)
|
||
base.WndProc(ref m);
|
||
} else {
|
||
base.WndProc(ref m);
|
||
}
|
||
|
||
m.Result = (IntPtr)((int)m.Result | CDRF_NOTIFYPOSTPAINT | CDRF_NOTIFYPOSTERASE);
|
||
return true;
|
||
|
||
case CDDS_ITEMPOSTPAINT:
|
||
//System.Diagnostics.Debug.WriteLine("CDDS_ITEMPOSTPAINT");
|
||
// Remember which items have been drawn so we can draw any decorations for them
|
||
// once all other painting is finished
|
||
if (this.Columns.Count > 0) {
|
||
OLVListItem olvi = this.GetItem((int)nmcustomdraw.nmcd.dwItemSpec);
|
||
if (olvi != null)
|
||
this.drawnItems.Add(olvi);
|
||
}
|
||
break;
|
||
|
||
case CDDS_SUBITEMPREPAINT:
|
||
//System.Diagnostics.Debug.WriteLine(String.Format("CDDS_SUBITEMPREPAINT ({0},{1})", (int)nmcustomdraw.nmcd.dwItemSpec, nmcustomdraw.iSubItem));
|
||
|
||
// There is a bug in the .NET framework which appears when column 0 of an owner drawn listview
|
||
// is dragged to another column position.
|
||
// The bounds calculation always returns the left edge of column 0 as being 0.
|
||
// The effects of this bug become apparent
|
||
// when the listview is scrolled horizontally: the control can think that column 0
|
||
// is no longer visible (the horizontal scroll position is subtracted from the bounds, giving a
|
||
// rectangle that is offscreen). In those circumstances, column 0 is not redraw because
|
||
// the control thinks it is not visible and so does not trigger a DrawSubItem event.
|
||
|
||
// To fix this problem, we have to detected the situation -- owner drawing column 0 in any column except 0 --
|
||
// trigger our own DrawSubItem, and then prevent the default processing from occuring.
|
||
|
||
// Are we owner drawing column 0 when it's in any column except 0?
|
||
if (!this.OwnerDraw)
|
||
return false;
|
||
|
||
int columnIndex = nmcustomdraw.iSubItem;
|
||
if (columnIndex != 0)
|
||
return false;
|
||
|
||
int displayIndex = this.Columns[0].DisplayIndex;
|
||
if (displayIndex == 0)
|
||
return false;
|
||
|
||
int rowIndex = (int)nmcustomdraw.nmcd.dwItemSpec;
|
||
OLVListItem item = this.GetItem(rowIndex);
|
||
if (item == null)
|
||
return false;
|
||
|
||
// OK. We have the error condition, so lets do what the .NET framework should do.
|
||
// Trigger an event to draw column 0 when it is not at display index 0
|
||
using (Graphics g = Graphics.FromHdc(nmcustomdraw.nmcd.hdc)) {
|
||
|
||
// Correctly calculate the bounds of cell 0
|
||
Rectangle r = item.GetSubItemBounds(0);
|
||
|
||
// We can hardcode "0" here since we know we are only doing this for column 0
|
||
DrawListViewSubItemEventArgs args = new DrawListViewSubItemEventArgs(g, r, item, item.SubItems[0], rowIndex, 0,
|
||
this.Columns[0], (ListViewItemStates)nmcustomdraw.nmcd.uItemState);
|
||
this.OnDrawSubItem(args);
|
||
|
||
// If the event handler wants to do the default processing (i.e. DrawDefault = true), we are stuck.
|
||
// There is no way we can force the default drawing because of the bug in .NET we are trying to get around.
|
||
System.Diagnostics.Trace.Assert(!args.DrawDefault, "Default drawing is impossible in this situation");
|
||
}
|
||
m.Result = (IntPtr)4;
|
||
|
||
return true;
|
||
|
||
case CDDS_SUBITEMPOSTPAINT:
|
||
//System.Diagnostics.Debug.WriteLine("CDDS_SUBITEMPOSTPAINT");
|
||
break;
|
||
|
||
// I have included these stages, but it doesn't seem that they are sent for ListViews.
|
||
// http://www.tech-archive.net/Archive/VC/microsoft.public.vc.mfc/2006-08/msg00220.html
|
||
|
||
case CDDS_PREERASE:
|
||
//System.Diagnostics.Debug.WriteLine("CDDS_PREERASE");
|
||
break;
|
||
|
||
case CDDS_POSTERASE:
|
||
//System.Diagnostics.Debug.WriteLine("CDDS_POSTERASE");
|
||
break;
|
||
|
||
case CDDS_ITEMPREERASE:
|
||
//System.Diagnostics.Debug.WriteLine("CDDS_ITEMPREERASE");
|
||
break;
|
||
|
||
case CDDS_ITEMPOSTERASE:
|
||
//System.Diagnostics.Debug.WriteLine("CDDS_ITEMPOSTERASE");
|
||
break;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
bool isAfterItemPaint;
|
||
List<OLVListItem> drawnItems;
|
||
|
||
/// <summary>
|
||
/// Handle the underlying control being destroyed
|
||
/// </summary>
|
||
/// <param name="m"></param>
|
||
/// <returns></returns>
|
||
protected virtual bool HandleDestroy(ref Message m) {
|
||
//System.Diagnostics.Debug.WriteLine(String.Format("WM_DESTROY: Disposing={0}, IsDisposed={1}, VirtualMode={2}", Disposing, IsDisposed, VirtualMode));
|
||
|
||
// Recreate the header control when the listview control is destroyed
|
||
this.headerControl = null;
|
||
|
||
// When the underlying control is destroyed, we need to recreate and reconfigure its tooltip
|
||
if (this.cellToolTip != null) {
|
||
this.cellToolTip.PushSettings();
|
||
this.BeginInvoke((MethodInvoker)delegate {
|
||
this.UpdateCellToolTipHandle();
|
||
this.cellToolTip.PopSettings();
|
||
});
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handle the search for item m if possible.
|
||
/// </summary>
|
||
/// <param name="m">The m to be processed</param>
|
||
/// <returns>bool to indicate if the msg has been handled</returns>
|
||
protected virtual bool HandleFindItem(ref Message m) {
|
||
// NOTE: As far as I can see, this message is never actually sent to the control, making this
|
||
// method redundant!
|
||
|
||
const int LVFI_STRING = 0x0002;
|
||
|
||
NativeMethods.LVFINDINFO findInfo = (NativeMethods.LVFINDINFO)m.GetLParam(typeof(NativeMethods.LVFINDINFO));
|
||
|
||
// We can only handle string searches
|
||
if ((findInfo.flags & LVFI_STRING) != LVFI_STRING)
|
||
return false;
|
||
|
||
int start = m.WParam.ToInt32();
|
||
m.Result = (IntPtr)this.FindMatchingRow(findInfo.psz, start, SearchDirectionHint.Down);
|
||
return true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Find the first row after the given start in which the text value in the
|
||
/// comparison column begins with the given text. The comparison column is column 0,
|
||
/// unless IsSearchOnSortColumn is true, in which case the current sort column is used.
|
||
/// </summary>
|
||
/// <param name="text">The text to be prefix matched</param>
|
||
/// <param name="start">The index of the first row to consider</param>
|
||
/// <param name="direction">Which direction should be searched?</param>
|
||
/// <returns>The index of the first row that matched, or -1</returns>
|
||
/// <remarks>The text comparison is a case-insensitive, prefix match. The search will
|
||
/// search the every row until a match is found, wrapping at the end if needed.</remarks>
|
||
public virtual int FindMatchingRow(string text, int start, SearchDirectionHint direction) {
|
||
// We also can't do anything if we don't have data
|
||
int rowCount = this.GetItemCount();
|
||
if (rowCount == 0)
|
||
return -1;
|
||
|
||
// Which column are we going to use for our comparing?
|
||
OLVColumn column = this.GetColumn(0);
|
||
if (this.IsSearchOnSortColumn && this.View == View.Details && this.PrimarySortColumn != null)
|
||
column = this.PrimarySortColumn;
|
||
|
||
// Do two searches if necessary to find a match. The second search is the wrap-around part of searching
|
||
int i;
|
||
if (direction == SearchDirectionHint.Down) {
|
||
i = this.FindMatchInRange(text, start, rowCount - 1, column);
|
||
if (i == -1 && start > 0)
|
||
i = this.FindMatchInRange(text, 0, start - 1, column);
|
||
} else {
|
||
i = this.FindMatchInRange(text, start, 0, column);
|
||
if (i == -1 && start != rowCount)
|
||
i = this.FindMatchInRange(text, rowCount - 1, start + 1, column);
|
||
}
|
||
|
||
return i;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Find the first row in the given range of rows that prefix matches the string value of the given column.
|
||
/// </summary>
|
||
/// <param name="text"></param>
|
||
/// <param name="first"></param>
|
||
/// <param name="last"></param>
|
||
/// <param name="column"></param>
|
||
/// <returns>The index of the matched row, or -1</returns>
|
||
protected virtual int FindMatchInRange(string text, int first, int last, OLVColumn column) {
|
||
if (first <= last) {
|
||
for (int i = first; i <= last; i++) {
|
||
string data = column.GetStringValue(this.GetNthItemInDisplayOrder(i).RowObject);
|
||
if (data.IndexOf(text, StringComparison.CurrentCultureIgnoreCase)>=0)
|
||
return i;
|
||
}
|
||
} else {
|
||
for (int i = first; i >= last; i--) {
|
||
string data = column.GetStringValue(this.GetNthItemInDisplayOrder(i).RowObject);
|
||
if (data.IndexOf(text, StringComparison.CurrentCultureIgnoreCase)>=0)
|
||
return i;
|
||
}
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handle the Group Info series of notifications
|
||
/// </summary>
|
||
/// <param name="m">The message</param>
|
||
/// <returns>True if the message has been handled</returns>
|
||
protected virtual bool HandleGroupInfo(ref Message m)
|
||
{
|
||
NativeMethods.NMLVGROUP nmlvgroup = (NativeMethods.NMLVGROUP)m.GetLParam(typeof(NativeMethods.NMLVGROUP));
|
||
|
||
//System.Diagnostics.Debug.WriteLine(String.Format("group: {0}, old state: {1}, new state: {2}",
|
||
// nmlvgroup.iGroupId, OLVGroup.StateToString(nmlvgroup.uOldState), OLVGroup.StateToString(nmlvgroup.uNewState)));
|
||
|
||
// Ignore state changes that aren't related to selection, focus or collapsedness
|
||
const uint INTERESTING_STATES = (uint) (GroupState.LVGS_COLLAPSED | GroupState.LVGS_FOCUSED | GroupState.LVGS_SELECTED);
|
||
if ((nmlvgroup.uOldState & INTERESTING_STATES) == (nmlvgroup.uNewState & INTERESTING_STATES))
|
||
return false;
|
||
|
||
foreach (OLVGroup group in this.OLVGroups) {
|
||
if (group.GroupId == nmlvgroup.iGroupId) {
|
||
GroupStateChangedEventArgs args = new GroupStateChangedEventArgs(group, (GroupState)nmlvgroup.uOldState, (GroupState)nmlvgroup.uNewState);
|
||
this.OnGroupStateChanged(args);
|
||
break;
|
||
}
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
//private static string StateToString(uint state)
|
||
//{
|
||
// if (state == 0)
|
||
// return Enum.GetName(typeof(GroupState), 0);
|
||
|
||
// List<string> names = new List<string>();
|
||
// foreach (int value in Enum.GetValues(typeof(GroupState)))
|
||
// {
|
||
// if (value != 0 && (state & value) == value)
|
||
// {
|
||
// names.Add(Enum.GetName(typeof(GroupState), value));
|
||
// }
|
||
// }
|
||
// return names.Count == 0 ? state.ToString("x") : String.Join("|", names.ToArray());
|
||
//}
|
||
|
||
/// <summary>
|
||
/// Handle a key down message
|
||
/// </summary>
|
||
/// <param name="m"></param>
|
||
/// <returns>True if the msg has been handled</returns>
|
||
protected virtual bool HandleKeyDown(ref Message m) {
|
||
|
||
// If this is a checkbox list, toggle the selected rows when the user presses Space
|
||
if (this.CheckBoxes && m.WParam.ToInt32() == (int)Keys.Space && this.SelectedIndices.Count > 0) {
|
||
this.ToggleSelectedRowCheckBoxes();
|
||
return true;
|
||
}
|
||
|
||
// Remember the scroll position so we can decide if the listview has scrolled in the
|
||
// handling of the event.
|
||
int scrollPositionH = NativeMethods.GetScrollPosition(this, true);
|
||
int scrollPositionV = NativeMethods.GetScrollPosition(this, false);
|
||
|
||
base.WndProc(ref m);
|
||
|
||
// It's possible that the processing in base.WndProc has actually destroyed this control
|
||
if (this.IsDisposed)
|
||
return true;
|
||
|
||
// If the keydown processing changed the scroll position, trigger a Scroll event
|
||
int newScrollPositionH = NativeMethods.GetScrollPosition(this, true);
|
||
int newScrollPositionV = NativeMethods.GetScrollPosition(this, false);
|
||
|
||
if (scrollPositionH != newScrollPositionH) {
|
||
ScrollEventArgs args = new ScrollEventArgs(ScrollEventType.EndScroll,
|
||
scrollPositionH, newScrollPositionH, ScrollOrientation.HorizontalScroll);
|
||
this.OnScroll(args);
|
||
}
|
||
if (scrollPositionV != newScrollPositionV) {
|
||
ScrollEventArgs args = new ScrollEventArgs(ScrollEventType.EndScroll,
|
||
scrollPositionV, newScrollPositionV, ScrollOrientation.VerticalScroll);
|
||
this.OnScroll(args);
|
||
}
|
||
|
||
if (scrollPositionH != newScrollPositionH || scrollPositionV != newScrollPositionV)
|
||
this.RefreshHotItem();
|
||
|
||
return true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Toggle the checkedness of the selected rows
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// Actually, this doesn't actually toggle all rows. It toggles the first row, and
|
||
/// all other rows get the check state of that first row. This is actually a much
|
||
/// more useful behaviour.
|
||
/// </para>
|
||
/// <para>
|
||
/// If no rows are selected, this method does nothing.
|
||
/// </para>
|
||
/// </remarks>
|
||
public void ToggleSelectedRowCheckBoxes() {
|
||
if (this.SelectedIndices.Count == 0)
|
||
return;
|
||
Object primaryModel = this.GetItem(this.SelectedIndices[0]).RowObject;
|
||
this.ToggleCheckObject(primaryModel);
|
||
CheckState? state = this.GetCheckState(primaryModel);
|
||
if (state.HasValue) {
|
||
foreach (Object x in this.SelectedObjects)
|
||
this.SetObjectCheckedness(x, state.Value);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Catch the Left Button down event.
|
||
/// </summary>
|
||
/// <param name="m">The m to be processed</param>
|
||
/// <returns>bool to indicate if the msg has been handled</returns>
|
||
protected virtual bool HandleLButtonDown(ref Message m) {
|
||
// We have to intercept this low level message rather than the more natural
|
||
// overridding of OnMouseDown, since ListCtrl's internal mouse down behavior
|
||
// is to select (or deselect) rows when the mouse is released. We don't
|
||
// want the selection to change when the user checks or unchecks a checkbox, so if the
|
||
// mouse down event was to check/uncheck, we have to hide this mouse
|
||
// down event from the control.
|
||
|
||
int x = m.LParam.ToInt32() & 0xFFFF;
|
||
int y = (m.LParam.ToInt32() >> 16) & 0xFFFF;
|
||
|
||
return this.ProcessLButtonDown(this.OlvHitTest(x, y));
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handle a left mouse down at the given hit test location
|
||
/// </summary>
|
||
/// <remarks>Subclasses can override this to do something unique</remarks>
|
||
/// <param name="hti"></param>
|
||
/// <returns>True if the message has been handled</returns>
|
||
protected virtual bool ProcessLButtonDown(OlvListViewHitTestInfo hti) {
|
||
|
||
if (hti.Item == null)
|
||
return false;
|
||
|
||
// If the click occurs on a button, ignore it so the row isn't selected
|
||
if (hti.HitTestLocation == HitTestLocation.Button) {
|
||
this.Invalidate();
|
||
|
||
return true;
|
||
}
|
||
|
||
// If they didn't click checkbox, we can just return
|
||
if (hti.HitTestLocation != HitTestLocation.CheckBox)
|
||
return false;
|
||
|
||
// Disabled rows cannot change checkboxes
|
||
if (!hti.Item.Enabled)
|
||
return true;
|
||
|
||
// Did they click a sub item checkbox?
|
||
if (hti.Column != null && hti.Column.Index > 0) {
|
||
if (hti.Column.IsEditable && hti.Item.Enabled)
|
||
this.ToggleSubItemCheckBox(hti.RowObject, hti.Column);
|
||
return true;
|
||
}
|
||
|
||
// They must have clicked the primary checkbox
|
||
this.ToggleCheckObject(hti.RowObject);
|
||
|
||
// If they change the checkbox of a selected row, all the rows in the selection
|
||
// should be given the same state
|
||
if (hti.Item.Selected) {
|
||
CheckState? state = this.GetCheckState(hti.RowObject);
|
||
if (state.HasValue) {
|
||
foreach (Object x in this.SelectedObjects)
|
||
this.SetObjectCheckedness(x, state.Value);
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Catch the Left Button up event.
|
||
/// </summary>
|
||
/// <param name="m">The m to be processed</param>
|
||
/// <returns>bool to indicate if the msg has been handled</returns>
|
||
protected virtual bool HandleLButtonUp(ref Message m) {
|
||
if (this.MouseMoveHitTest == null)
|
||
return false;
|
||
|
||
int x = m.LParam.ToInt32() & 0xFFFF;
|
||
int y = (m.LParam.ToInt32() >> 16) & 0xFFFF;
|
||
|
||
// Did they click an enabled, non-empty button?
|
||
if (this.MouseMoveHitTest.HitTestLocation == HitTestLocation.Button) {
|
||
// If a button was hit, Item and Column must be non-null
|
||
if (this.MouseMoveHitTest.Item.Enabled || this.MouseMoveHitTest.Column.EnableButtonWhenItemIsDisabled) {
|
||
string buttonText = this.MouseMoveHitTest.Column.GetStringValue(this.MouseMoveHitTest.RowObject);
|
||
if (!String.IsNullOrEmpty(buttonText)) {
|
||
this.Invalidate();
|
||
CellClickEventArgs args = new CellClickEventArgs();
|
||
this.BuildCellEvent(args, new Point(x, y), this.MouseMoveHitTest);
|
||
this.OnButtonClick(args);
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Are they trying to expand/collapse a group?
|
||
if (this.MouseMoveHitTest.HitTestLocation == HitTestLocation.GroupExpander) {
|
||
if (this.TriggerGroupExpandCollapse(this.MouseMoveHitTest.Group))
|
||
return true;
|
||
}
|
||
|
||
if (ObjectListView.IsVistaOrLater && this.HasCollapsibleGroups)
|
||
base.DefWndProc(ref m);
|
||
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Trigger a GroupExpandCollapse event and return true if the action was cancelled
|
||
/// </summary>
|
||
/// <param name="group"></param>
|
||
/// <returns></returns>
|
||
protected virtual bool TriggerGroupExpandCollapse(OLVGroup group)
|
||
{
|
||
GroupExpandingCollapsingEventArgs args = new GroupExpandingCollapsingEventArgs(group);
|
||
this.OnGroupExpandingCollapsing(args);
|
||
return args.Canceled;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Catch the Right Button down event.
|
||
/// </summary>
|
||
/// <param name="m">The m to be processed</param>
|
||
/// <returns>bool to indicate if the msg has been handled</returns>
|
||
protected virtual bool HandleRButtonDown(ref Message m) {
|
||
int x = m.LParam.ToInt32() & 0xFFFF;
|
||
int y = (m.LParam.ToInt32() >> 16) & 0xFFFF;
|
||
|
||
return this.ProcessRButtonDown(this.OlvHitTest(x, y));
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handle a left mouse down at the given hit test location
|
||
/// </summary>
|
||
/// <remarks>Subclasses can override this to do something unique</remarks>
|
||
/// <param name="hti"></param>
|
||
/// <returns>True if the message has been handled</returns>
|
||
protected virtual bool ProcessRButtonDown(OlvListViewHitTestInfo hti) {
|
||
if (hti.Item == null)
|
||
return false;
|
||
|
||
// Ignore clicks on checkboxes
|
||
return (hti.HitTestLocation == HitTestLocation.CheckBox);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Catch the Left Button double click event.
|
||
/// </summary>
|
||
/// <param name="m">The m to be processed</param>
|
||
/// <returns>bool to indicate if the msg has been handled</returns>
|
||
protected virtual bool HandleLButtonDoubleClick(ref Message m) {
|
||
int x = m.LParam.ToInt32() & 0xFFFF;
|
||
int y = (m.LParam.ToInt32() >> 16) & 0xFFFF;
|
||
|
||
return this.ProcessLButtonDoubleClick(this.OlvHitTest(x, y));
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handle a mouse double click at the given hit test location
|
||
/// </summary>
|
||
/// <remarks>Subclasses can override this to do something unique</remarks>
|
||
/// <param name="hti"></param>
|
||
/// <returns>True if the message has been handled</returns>
|
||
protected virtual bool ProcessLButtonDoubleClick(OlvListViewHitTestInfo hti) {
|
||
|
||
// If the user double clicked on a checkbox, ignore it
|
||
return (hti.HitTestLocation == HitTestLocation.CheckBox);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Catch the right Button double click event.
|
||
/// </summary>
|
||
/// <param name="m">The m to be processed</param>
|
||
/// <returns>bool to indicate if the msg has been handled</returns>
|
||
protected virtual bool HandleRButtonDoubleClick(ref Message m) {
|
||
int x = m.LParam.ToInt32() & 0xFFFF;
|
||
int y = (m.LParam.ToInt32() >> 16) & 0xFFFF;
|
||
|
||
return this.ProcessRButtonDoubleClick(this.OlvHitTest(x, y));
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handle a right mouse double click at the given hit test location
|
||
/// </summary>
|
||
/// <remarks>Subclasses can override this to do something unique</remarks>
|
||
/// <param name="hti"></param>
|
||
/// <returns>True if the message has been handled</returns>
|
||
protected virtual bool ProcessRButtonDoubleClick(OlvListViewHitTestInfo hti) {
|
||
|
||
// If the user double clicked on a checkbox, ignore it
|
||
return (hti.HitTestLocation == HitTestLocation.CheckBox);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Catch the MouseMove event.
|
||
/// </summary>
|
||
/// <param name="m">The m to be processed</param>
|
||
/// <returns>bool to indicate if the msg has been handled</returns>
|
||
protected virtual bool HandleMouseMove(ref Message m)
|
||
{
|
||
//int x = m.LParam.ToInt32() & 0xFFFF;
|
||
//int y = (m.LParam.ToInt32() >> 16) & 0xFFFF;
|
||
|
||
//this.lastMouseMoveX = x;
|
||
//this.lastMouseMoveY = y;
|
||
|
||
return false;
|
||
}
|
||
//private int lastMouseMoveX = -1;
|
||
//private int lastMouseMoveY = -1;
|
||
|
||
/// <summary>
|
||
/// Handle notifications that have been reflected back from the parent window
|
||
/// </summary>
|
||
/// <param name="m">The m to be processed</param>
|
||
/// <returns>bool to indicate if the msg has been handled</returns>
|
||
protected virtual bool HandleReflectNotify(ref Message m) {
|
||
const int NM_CLICK = -2;
|
||
const int NM_DBLCLK = -3;
|
||
const int NM_RDBLCLK = -6;
|
||
const int NM_CUSTOMDRAW = -12;
|
||
const int NM_RELEASEDCAPTURE = -16;
|
||
const int LVN_FIRST = -100;
|
||
const int LVN_ITEMCHANGED = LVN_FIRST - 1;
|
||
const int LVN_ITEMCHANGING = LVN_FIRST - 0;
|
||
const int LVN_HOTTRACK = LVN_FIRST - 21;
|
||
const int LVN_MARQUEEBEGIN = LVN_FIRST - 56;
|
||
const int LVN_GETINFOTIP = LVN_FIRST - 58;
|
||
const int LVN_GETDISPINFO = LVN_FIRST - 77;
|
||
const int LVN_BEGINSCROLL = LVN_FIRST - 80;
|
||
const int LVN_ENDSCROLL = LVN_FIRST - 81;
|
||
const int LVN_LINKCLICK = LVN_FIRST - 84;
|
||
const int LVN_GROUPINFO = LVN_FIRST - 88; // undocumented
|
||
const int LVIF_STATE = 8;
|
||
//const int LVIS_FOCUSED = 1;
|
||
const int LVIS_SELECTED = 2;
|
||
|
||
bool isMsgHandled = false;
|
||
|
||
// TODO: Don't do any logic in this method. Create separate methods for each message
|
||
|
||
NativeMethods.NMHDR nmhdr = (NativeMethods.NMHDR)m.GetLParam(typeof(NativeMethods.NMHDR));
|
||
//System.Diagnostics.Debug.WriteLine(String.Format("rn: {0}", nmhdr->code));
|
||
|
||
switch (nmhdr.code) {
|
||
case NM_CLICK:
|
||
// The standard ListView does some strange stuff here when the list has checkboxes.
|
||
// If you shift click on non-primary columns when FullRowSelect is true, the
|
||
// checkedness of the selected rows changes.
|
||
// We can't just not do the base class stuff because it sets up state that is used to
|
||
// determine mouse up events later on.
|
||
// So, we sabotage the base class's process of the click event. The base class does a HITTEST
|
||
// in order to determine which row was clicked -- if that fails, the base class does nothing.
|
||
// So when we get a CLICK, we know that the base class is going to send a HITTEST very soon,
|
||
// so we ignore the next HITTEST message, which will cause the click processing to fail.
|
||
//System.Diagnostics.Debug.WriteLine("NM_CLICK");
|
||
this.skipNextHitTest = true;
|
||
break;
|
||
|
||
case LVN_BEGINSCROLL:
|
||
//System.Diagnostics.Debug.WriteLine("LVN_BEGINSCROLL");
|
||
isMsgHandled = this.HandleBeginScroll(ref m);
|
||
break;
|
||
|
||
case LVN_ENDSCROLL:
|
||
isMsgHandled = this.HandleEndScroll(ref m);
|
||
break;
|
||
|
||
case LVN_LINKCLICK:
|
||
isMsgHandled = this.HandleLinkClick(ref m);
|
||
break;
|
||
|
||
case LVN_MARQUEEBEGIN:
|
||
//System.Diagnostics.Debug.WriteLine("LVN_MARQUEEBEGIN");
|
||
this.isMarqueSelecting = true;
|
||
break;
|
||
|
||
case LVN_GETINFOTIP:
|
||
//System.Diagnostics.Debug.WriteLine("LVN_GETINFOTIP");
|
||
// When virtual lists are in SmallIcon view, they generates tooltip message with invalid item indicies.
|
||
try
|
||
{
|
||
|
||
var lparam = m.GetLParam(typeof(NativeMethods.NMLVGETINFOTIP));
|
||
NativeMethods.NMLVGETINFOTIP nmGetInfoTip = (NativeMethods.NMLVGETINFOTIP)lparam;
|
||
isMsgHandled = nmGetInfoTip.iItem >= this.GetItemCount();
|
||
}
|
||
catch { isMsgHandled= false; }
|
||
break;
|
||
|
||
case NM_RELEASEDCAPTURE:
|
||
//System.Diagnostics.Debug.WriteLine("NM_RELEASEDCAPTURE");
|
||
this.isMarqueSelecting = false;
|
||
this.Invalidate();
|
||
break;
|
||
|
||
case NM_CUSTOMDRAW:
|
||
//System.Diagnostics.Debug.WriteLine("NM_CUSTOMDRAW");
|
||
isMsgHandled = this.HandleCustomDraw(ref m);
|
||
break;
|
||
|
||
case NM_DBLCLK:
|
||
// The default behavior of a .NET ListView with checkboxes is to toggle the checkbox on
|
||
// double-click. That's just silly, if you ask me :)
|
||
if (this.CheckBoxes) {
|
||
// How do we make ListView not do that silliness? We could just ignore the message
|
||
// but the last part of the base code sets up state information, and without that
|
||
// state, the ListView doesn't trigger MouseDoubleClick events. So we fake a
|
||
// right button double click event, which sets up the same state, but without
|
||
// toggling the checkbox.
|
||
nmhdr.code = NM_RDBLCLK;
|
||
Marshal.StructureToPtr(nmhdr, m.LParam, false);
|
||
}
|
||
break;
|
||
|
||
case LVN_ITEMCHANGED:
|
||
//System.Diagnostics.Debug.WriteLine("LVN_ITEMCHANGED");
|
||
NativeMethods.NMLISTVIEW nmlistviewPtr2 = (NativeMethods.NMLISTVIEW)m.GetLParam(typeof(NativeMethods.NMLISTVIEW));
|
||
if ((nmlistviewPtr2.uChanged & LVIF_STATE) != 0) {
|
||
CheckState currentValue = this.CalculateCheckState(nmlistviewPtr2.uOldState);
|
||
CheckState newCheckValue = this.CalculateCheckState(nmlistviewPtr2.uNewState);
|
||
if (currentValue != newCheckValue)
|
||
{
|
||
// Remove the state indicies so that we don't trigger the OnItemChecked method
|
||
// when we call our base method after exiting this method
|
||
nmlistviewPtr2.uOldState = (nmlistviewPtr2.uOldState & 0x0FFF);
|
||
nmlistviewPtr2.uNewState = (nmlistviewPtr2.uNewState & 0x0FFF);
|
||
Marshal.StructureToPtr(nmlistviewPtr2, m.LParam, false);
|
||
}
|
||
else
|
||
{
|
||
bool isSelected = (nmlistviewPtr2.uNewState & LVIS_SELECTED) == LVIS_SELECTED;
|
||
|
||
if (isSelected)
|
||
{
|
||
// System.Diagnostics.Debug.WriteLine(String.Format("Selected: {0}", nmlistviewPtr2.iItem));
|
||
bool isShiftDown = (Control.ModifierKeys & Keys.Shift) == Keys.Shift;
|
||
|
||
// -1 indicates that all rows are to be selected -- in fact, they already have been.
|
||
// We now have to deselect all the disabled objects.
|
||
if (nmlistviewPtr2.iItem == -1 || isShiftDown) {
|
||
Stopwatch sw = Stopwatch.StartNew();
|
||
foreach (object disabledModel in this.DisabledObjects)
|
||
{
|
||
int modelIndex = this.IndexOf(disabledModel);
|
||
if (modelIndex >= 0)
|
||
NativeMethods.DeselectOneItem(this, modelIndex);
|
||
}
|
||
System.Diagnostics.Debug.WriteLine(String.Format("PERF - Deselecting took {0}ms / {1} ticks", sw.ElapsedMilliseconds, sw.ElapsedTicks));
|
||
}
|
||
else
|
||
{
|
||
// If the object just selected is disabled, explicitly de-select it
|
||
OLVListItem olvi = this.GetItem(nmlistviewPtr2.iItem);
|
||
if (olvi != null && !olvi.Enabled)
|
||
NativeMethods.DeselectOneItem(this, nmlistviewPtr2.iItem);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
|
||
case LVN_ITEMCHANGING:
|
||
//System.Diagnostics.Debug.WriteLine("LVN_ITEMCHANGING");
|
||
NativeMethods.NMLISTVIEW nmlistviewPtr = (NativeMethods.NMLISTVIEW)m.GetLParam(typeof(NativeMethods.NMLISTVIEW));
|
||
if ((nmlistviewPtr.uChanged & LVIF_STATE) != 0) {
|
||
CheckState currentValue = this.CalculateCheckState(nmlistviewPtr.uOldState);
|
||
CheckState newCheckValue = this.CalculateCheckState(nmlistviewPtr.uNewState);
|
||
|
||
if (currentValue != newCheckValue) {
|
||
// Prevent the base method from seeing the state change,
|
||
// since we handled it elsewhere
|
||
nmlistviewPtr.uChanged &= ~LVIF_STATE;
|
||
Marshal.StructureToPtr(nmlistviewPtr, m.LParam, false);
|
||
}
|
||
}
|
||
break;
|
||
|
||
case LVN_HOTTRACK:
|
||
break;
|
||
|
||
case LVN_GETDISPINFO:
|
||
break;
|
||
|
||
case LVN_GROUPINFO:
|
||
//System.Diagnostics.Debug.WriteLine("reflect notify: GROUP INFO");
|
||
isMsgHandled = this.HandleGroupInfo(ref m);
|
||
break;
|
||
|
||
//default:
|
||
//System.Diagnostics.Debug.WriteLine(String.Format("reflect notify: {0}", nmhdr.code));
|
||
//break;
|
||
}
|
||
|
||
return isMsgHandled;
|
||
}
|
||
private bool skipNextHitTest;
|
||
|
||
private CheckState CalculateCheckState(int state) {
|
||
switch ((state & 0xf000) >> 12) {
|
||
case 1:
|
||
return CheckState.Unchecked;
|
||
case 2:
|
||
return CheckState.Checked;
|
||
case 3:
|
||
return CheckState.Indeterminate;
|
||
default:
|
||
return CheckState.Checked;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// In the notification messages, we handle attempts to change the width of our columns
|
||
/// </summary>
|
||
/// <param name="m">The m to be processed</param>
|
||
/// <returns>bool to indicate if the msg has been handled</returns>
|
||
protected bool HandleNotify(ref Message m) {
|
||
bool isMsgHandled = false;
|
||
|
||
const int NM_CUSTOMDRAW = -12;
|
||
|
||
const int HDN_FIRST = (0 - 300);
|
||
const int HDN_ITEMCHANGINGA = (HDN_FIRST - 0);
|
||
const int HDN_ITEMCHANGINGW = (HDN_FIRST - 20);
|
||
const int HDN_ITEMCLICKA = (HDN_FIRST - 2);
|
||
const int HDN_ITEMCLICKW = (HDN_FIRST - 22);
|
||
const int HDN_DIVIDERDBLCLICKA = (HDN_FIRST - 5);
|
||
const int HDN_DIVIDERDBLCLICKW = (HDN_FIRST - 25);
|
||
const int HDN_BEGINTRACKA = (HDN_FIRST - 6);
|
||
const int HDN_BEGINTRACKW = (HDN_FIRST - 26);
|
||
const int HDN_ENDTRACKA = (HDN_FIRST - 7);
|
||
const int HDN_ENDTRACKW = (HDN_FIRST - 27);
|
||
const int HDN_TRACKA = (HDN_FIRST - 8);
|
||
const int HDN_TRACKW = (HDN_FIRST - 28);
|
||
|
||
// Handle the notification, remembering to handle both ANSI and Unicode versions
|
||
NativeMethods.NMHEADER nmheader = (NativeMethods.NMHEADER)m.GetLParam(typeof(NativeMethods.NMHEADER));
|
||
//System.Diagnostics.Debug.WriteLine(String.Format("not: {0}", nmhdr->code));
|
||
|
||
//if (nmhdr.code < HDN_FIRST)
|
||
// System.Diagnostics.Debug.WriteLine(nmhdr.code);
|
||
|
||
// In KB Article #183258, MS states that when a header control has the HDS_FULLDRAG style, it will receive
|
||
// ITEMCHANGING events rather than TRACK events. Under XP SP2 (at least) this is not always true, which may be
|
||
// why MS has withdrawn that particular KB article. It is true that the header is always given the HDS_FULLDRAG
|
||
// style. But even while window style set, the control doesn't always received ITEMCHANGING events.
|
||
// The controlling setting seems to be the Explorer option "Show Window Contents While Dragging"!
|
||
// In the category of "truly bizarre side effects", if the this option is turned on, we will receive
|
||
// ITEMCHANGING events instead of TRACK events. But if it is turned off, we receive lots of TRACK events and
|
||
// only one ITEMCHANGING event at the very end of the process.
|
||
// If we receive HDN_TRACK messages, it's harder to control the resizing process. If we return a result of 1, we
|
||
// cancel the whole drag operation, not just that particular track event, which is clearly not what we want.
|
||
// If we are willing to compile with unsafe code enabled, we can modify the size of the column in place, using the
|
||
// commented out code below. But without unsafe code, the best we can do is allow the user to drag the column to
|
||
// any width, and then spring it back to within bounds once they release the mouse button. UI-wise it's very ugly.
|
||
switch (nmheader.nhdr.code) {
|
||
|
||
case NM_CUSTOMDRAW:
|
||
if (!this.OwnerDrawnHeader)
|
||
isMsgHandled = this.HeaderControl.HandleHeaderCustomDraw(ref m);
|
||
break;
|
||
|
||
case HDN_ITEMCLICKA:
|
||
case HDN_ITEMCLICKW:
|
||
if (!this.PossibleFinishCellEditing())
|
||
{
|
||
m.Result = (IntPtr)1; // prevent the change from happening
|
||
isMsgHandled = true;
|
||
}
|
||
break;
|
||
|
||
case HDN_DIVIDERDBLCLICKA:
|
||
case HDN_DIVIDERDBLCLICKW:
|
||
case HDN_BEGINTRACKA:
|
||
case HDN_BEGINTRACKW:
|
||
if (!this.PossibleFinishCellEditing()) {
|
||
m.Result = (IntPtr)1; // prevent the change from happening
|
||
isMsgHandled = true;
|
||
break;
|
||
}
|
||
if (nmheader.iItem >= 0 && nmheader.iItem < this.Columns.Count) {
|
||
OLVColumn column = this.GetColumn(nmheader.iItem);
|
||
// Space filling columns can't be dragged or double-click resized
|
||
if (column.FillsFreeSpace) {
|
||
m.Result = (IntPtr)1; // prevent the change from happening
|
||
isMsgHandled = true;
|
||
}
|
||
}
|
||
break;
|
||
case HDN_ENDTRACKA:
|
||
case HDN_ENDTRACKW:
|
||
//if (this.ShowGroups)
|
||
// this.ResizeLastGroup();
|
||
break;
|
||
case HDN_TRACKA:
|
||
case HDN_TRACKW:
|
||
if (nmheader.iItem >= 0 && nmheader.iItem < this.Columns.Count) {
|
||
NativeMethods.HDITEM hditem = (NativeMethods.HDITEM)Marshal.PtrToStructure(nmheader.pHDITEM, typeof(NativeMethods.HDITEM));
|
||
OLVColumn column = this.GetColumn(nmheader.iItem);
|
||
if (hditem.cxy < column.MinimumWidth)
|
||
hditem.cxy = column.MinimumWidth;
|
||
else if (column.MaximumWidth != -1 && hditem.cxy > column.MaximumWidth)
|
||
hditem.cxy = column.MaximumWidth;
|
||
Marshal.StructureToPtr(hditem, nmheader.pHDITEM, false);
|
||
}
|
||
break;
|
||
|
||
case HDN_ITEMCHANGINGA:
|
||
case HDN_ITEMCHANGINGW:
|
||
nmheader = (NativeMethods.NMHEADER)m.GetLParam(typeof(NativeMethods.NMHEADER));
|
||
if (nmheader.iItem >= 0 && nmheader.iItem < this.Columns.Count) {
|
||
NativeMethods.HDITEM hditem = (NativeMethods.HDITEM)Marshal.PtrToStructure(nmheader.pHDITEM, typeof(NativeMethods.HDITEM));
|
||
OLVColumn column = this.GetColumn(nmheader.iItem);
|
||
// Check the mask to see if the width field is valid, and if it is, make sure it's within range
|
||
if ((hditem.mask & 1) == 1) {
|
||
if (hditem.cxy < column.MinimumWidth ||
|
||
(column.MaximumWidth != -1 && hditem.cxy > column.MaximumWidth)) {
|
||
m.Result = (IntPtr)1; // prevent the change from happening
|
||
isMsgHandled = true;
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
|
||
case ToolTipControl.TTN_SHOW:
|
||
//System.Diagnostics.Debug.WriteLine("olv TTN_SHOW");
|
||
if (this.CellToolTip.Handle == nmheader.nhdr.hwndFrom)
|
||
isMsgHandled = this.CellToolTip.HandleShow(ref m);
|
||
break;
|
||
|
||
case ToolTipControl.TTN_POP:
|
||
//System.Diagnostics.Debug.WriteLine("olv TTN_POP");
|
||
if (this.CellToolTip.Handle == nmheader.nhdr.hwndFrom)
|
||
isMsgHandled = this.CellToolTip.HandlePop(ref m);
|
||
break;
|
||
|
||
case ToolTipControl.TTN_GETDISPINFO:
|
||
//System.Diagnostics.Debug.WriteLine("olv TTN_GETDISPINFO");
|
||
if (this.CellToolTip.Handle == nmheader.nhdr.hwndFrom)
|
||
isMsgHandled = this.CellToolTip.HandleGetDispInfo(ref m);
|
||
break;
|
||
|
||
// default:
|
||
// System.Diagnostics.Debug.WriteLine(String.Format("notify: {0}", nmheader.nhdr.code));
|
||
// break;
|
||
}
|
||
|
||
return isMsgHandled;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Create a ToolTipControl to manage the tooltip control used by the listview control
|
||
/// </summary>
|
||
protected virtual void CreateCellToolTip() {
|
||
this.cellToolTip = new ToolTipControl();
|
||
this.cellToolTip.AssignHandle(NativeMethods.GetTooltipControl(this));
|
||
this.cellToolTip.Showing += new EventHandler<ToolTipShowingEventArgs>(HandleCellToolTipShowing);
|
||
this.cellToolTip.SetMaxWidth();
|
||
NativeMethods.MakeTopMost(this.cellToolTip);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Update the handle used by our cell tooltip to be the tooltip used by
|
||
/// the underlying Windows listview control.
|
||
/// </summary>
|
||
protected virtual void UpdateCellToolTipHandle() {
|
||
if (this.cellToolTip != null && this.cellToolTip.Handle == IntPtr.Zero)
|
||
this.cellToolTip.AssignHandle(NativeMethods.GetTooltipControl(this));
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handle the WM_PAINT event
|
||
/// </summary>
|
||
/// <param name="m"></param>
|
||
/// <returns>Return true if the msg has been handled and nothing further should be done</returns>
|
||
protected virtual bool HandlePaint(ref Message m) {
|
||
//System.Diagnostics.Debug.WriteLine("> WMPAINT");
|
||
|
||
// We only want to custom draw the control within WmPaint message and only
|
||
// once per paint event. We use these bools to insure this.
|
||
this.isInWmPaintEvent = true;
|
||
this.shouldDoCustomDrawing = true;
|
||
this.prePaintLevel = 0;
|
||
|
||
this.ShowOverlays();
|
||
|
||
this.HandlePrePaint();
|
||
base.WndProc(ref m);
|
||
this.HandlePostPaint();
|
||
this.isInWmPaintEvent = false;
|
||
//System.Diagnostics.Debug.WriteLine("< WMPAINT");
|
||
return true;
|
||
}
|
||
private int prePaintLevel;
|
||
|
||
/// <summary>
|
||
/// Perform any steps needed before painting the control
|
||
/// </summary>
|
||
protected virtual void HandlePrePaint() {
|
||
// When we get a WM_PAINT msg, remember the rectangle that is being updated.
|
||
// We can't get this information later, since the BeginPaint call wipes it out.
|
||
// this.lastUpdateRectangle = NativeMethods.GetUpdateRect(this); // we no longer need this, but keep the code so we can see it later
|
||
|
||
//// When the list is empty, we want to handle the drawing of the control by ourselves.
|
||
//// Unfortunately, there is no easy way to tell our superclass that we want to do this.
|
||
//// So we resort to guile and deception. We validate the list area of the control, which
|
||
//// effectively tells our superclass that this area does not need to be painted.
|
||
//// Our superclass will then not paint the control, leaving us free to do so ourselves.
|
||
//// Without doing this trickery, the superclass will draw the list as empty,
|
||
//// and then moments later, we will draw the empty list msg, giving a nasty flicker
|
||
//if (this.GetItemCount() == 0 && this.HasEmptyListMsg)
|
||
// NativeMethods.ValidateRect(this, this.ClientRectangle);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Perform any steps needed after painting the control
|
||
/// </summary>
|
||
protected virtual void HandlePostPaint() {
|
||
// This message is no longer necessary, but we keep it for compatibility
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handle the window position changing.
|
||
/// </summary>
|
||
/// <param name="m">The m to be processed</param>
|
||
/// <returns>bool to indicate if the msg has been handled</returns>
|
||
protected virtual bool HandleWindowPosChanging(ref Message m) {
|
||
const int SWP_NOSIZE = 1;
|
||
|
||
NativeMethods.WINDOWPOS pos = (NativeMethods.WINDOWPOS)m.GetLParam(typeof(NativeMethods.WINDOWPOS));
|
||
if ((pos.flags & SWP_NOSIZE) == 0) {
|
||
if (pos.cx < this.Bounds.Width) // only when shrinking
|
||
// pos.cx is the window width, not the client area width, so we have to subtract the border widths
|
||
this.ResizeFreeSpaceFillingColumns(pos.cx - (this.Bounds.Width - this.ClientSize.Width));
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Column header clicking, column hiding and resizing
|
||
|
||
/// <summary>
|
||
/// The user has right clicked on the column headers. Do whatever is required
|
||
/// </summary>
|
||
/// <returns>Return true if this event has been handle</returns>
|
||
protected virtual bool HandleHeaderRightClick(int columnIndex) {
|
||
ColumnClickEventArgs eventArgs = new ColumnClickEventArgs(columnIndex);
|
||
this.OnColumnRightClick(eventArgs);
|
||
|
||
// TODO: Allow users to say they have handled this event
|
||
|
||
return this.ShowHeaderRightClickMenu(columnIndex, Cursor.Position);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Show a menu that is appropriate when the given column header is clicked.
|
||
/// </summary>
|
||
/// <param name="columnIndex">The index of the header that was clicked. This
|
||
/// can be -1, indicating that the header was clicked outside of a column</param>
|
||
/// <param name="pt">Where should the menu be shown</param>
|
||
/// <returns>True if a menu was displayed</returns>
|
||
protected virtual bool ShowHeaderRightClickMenu(int columnIndex, Point pt) {
|
||
ToolStripDropDown m = this.MakeHeaderRightClickMenu(columnIndex);
|
||
if (m.Items.Count > 0) {
|
||
m.Show(pt);
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Create the menu that should be displayed when the user right clicks
|
||
/// on the given column header.
|
||
/// </summary>
|
||
/// <param name="columnIndex">Index of the column that was right clicked.
|
||
/// This can be negative, which indicates a click outside of any header.</param>
|
||
/// <returns>The toolstrip that should be displayed</returns>
|
||
protected virtual ToolStripDropDown MakeHeaderRightClickMenu(int columnIndex) {
|
||
ToolStripDropDown m = new ContextMenuStrip();
|
||
|
||
if (columnIndex >= 0 && this.UseFiltering && this.ShowFilterMenuOnRightClick)
|
||
m = this.MakeFilteringMenu(m, columnIndex);
|
||
|
||
if (columnIndex >= 0 && this.ShowCommandMenuOnRightClick)
|
||
m = this.MakeColumnCommandMenu(m, columnIndex);
|
||
|
||
if (this.SelectColumnsOnRightClickBehaviour != ColumnSelectBehaviour.None) {
|
||
m = this.MakeColumnSelectMenu(m);
|
||
}
|
||
|
||
return m;
|
||
}
|
||
|
||
/// <summary>
|
||
/// The user has right clicked on the column headers. Do whatever is required
|
||
/// </summary>
|
||
/// <returns>Return true if this event has been handle</returns>
|
||
[Obsolete("Use HandleHeaderRightClick(int) instead")]
|
||
protected virtual bool HandleHeaderRightClick() {
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Show a popup menu at the given point which will allow the user to choose which columns
|
||
/// are visible on this listview
|
||
/// </summary>
|
||
/// <param name="pt">Where should the menu be placed</param>
|
||
[Obsolete("Use ShowHeaderRightClickMenu instead")]
|
||
protected virtual void ShowColumnSelectMenu(Point pt) {
|
||
ToolStripDropDown m = this.MakeColumnSelectMenu(new ContextMenuStrip());
|
||
m.Show(pt);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Show a popup menu at the given point which will allow the user to choose which columns
|
||
/// are visible on this listview
|
||
/// </summary>
|
||
/// <param name="columnIndex"></param>
|
||
/// <param name="pt">Where should the menu be placed</param>
|
||
[Obsolete("Use ShowHeaderRightClickMenu instead")]
|
||
protected virtual void ShowColumnCommandMenu(int columnIndex, Point pt) {
|
||
ToolStripDropDown m = this.MakeColumnCommandMenu(new ContextMenuStrip(), columnIndex);
|
||
if (this.SelectColumnsOnRightClick) {
|
||
if (m.Items.Count > 0)
|
||
m.Items.Add(new ToolStripSeparator());
|
||
this.MakeColumnSelectMenu(m);
|
||
}
|
||
m.Show(pt);
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD>
|
||
/// </summary>
|
||
[Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD>")]
|
||
[Category("<22><>ǩ - ObjectListView"), DefaultValue("<22><><EFBFBD><EFBFBD>{0}<7D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), Localizable(true)]
|
||
public string MenuLabelSortAscending {
|
||
get { return this.menuLabelSortAscending; }
|
||
set { this.menuLabelSortAscending = value; }
|
||
}
|
||
private string menuLabelSortAscending = "<22><><EFBFBD><EFBFBD>{0}<7D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>";
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>ڽ<EFBFBD><DABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD>
|
||
/// </summary>
|
||
[Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>ڽ<EFBFBD><DABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD>")]
|
||
[Category("<22><>ǩ - ObjectListView"), DefaultValue("<22><><EFBFBD><EFBFBD>{0}<7D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), Localizable(true)]
|
||
public string MenuLabelSortDescending {
|
||
get { return this.menuLabelSortDescending; }
|
||
set { this.menuLabelSortDescending = value; }
|
||
}
|
||
private string menuLabelSortDescending = "<22><><EFBFBD><EFBFBD>{0}<7D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>";
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>ڷ<EFBFBD><DAB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD>
|
||
/// </summary>
|
||
[Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>ڷ<EFBFBD><DAB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD>")]
|
||
[Category("<22><>ǩ - ObjectListView"), DefaultValue("<22><><EFBFBD><EFBFBD>{0}<7D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), Localizable(true)]
|
||
public string MenuLabelGroupBy {
|
||
get { return this.menuLabelGroupBy; }
|
||
set { this.menuLabelGroupBy = value; }
|
||
}
|
||
private string menuLabelGroupBy = "<22><><EFBFBD><EFBFBD>{0}<7D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>";
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD>
|
||
/// </summary>
|
||
[Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD>")]
|
||
[Category("<22><>ǩ - ObjectListView"), DefaultValue("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>{0}<7D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), Localizable(true)]
|
||
public string MenuLabelLockGroupingOn {
|
||
get { return this.menuLabelLockGroupingOn; }
|
||
set { this.menuLabelLockGroupingOn = value; }
|
||
}
|
||
private string menuLabelLockGroupingOn = "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>{0}<7D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>";
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD>
|
||
/// </summary>
|
||
[Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD>")]
|
||
[Category("<22><>ǩ - ObjectListView"), DefaultValue("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>{0}<7D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), Localizable(true)]
|
||
public string MenuLabelUnlockGroupingOn {
|
||
get { return this.menuLabelUnlockGroupingOn; }
|
||
set { this.menuLabelUnlockGroupingOn = value; }
|
||
}
|
||
private string menuLabelUnlockGroupingOn = "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>{0}<7D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>";
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>ڹرշ<D8B1><D5B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD>
|
||
/// </summary>
|
||
[Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>ڹرշ<D8B1><D5B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD>")]
|
||
[Category("<22><>ǩ - ObjectListView"), DefaultValue("<22>رշ<D8B1><D5B7><EFBFBD>"), Localizable(true)]
|
||
public string MenuLabelTurnOffGroups {
|
||
get { return this.menuLabelTurnOffGroups; }
|
||
set { this.menuLabelTurnOffGroups = value; }
|
||
}
|
||
private string menuLabelTurnOffGroups = "<22>رշ<D8B1><D5B7><EFBFBD>";
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD>
|
||
/// </summary>
|
||
[Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD>")]
|
||
[Category("<22><>ǩ - ObjectListView"), DefaultValue("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), Localizable(true)]
|
||
public string MenuLabelUnsort {
|
||
get { return this.menuLabelUnsort; }
|
||
set { this.menuLabelUnsort = value; }
|
||
}
|
||
private string menuLabelUnsort = "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>";
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD>
|
||
/// </summary>
|
||
[Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD>")]
|
||
[Category("<22><>ǩ - ObjectListView"), DefaultValue("<22><>"), Localizable(true)]
|
||
public string MenuLabelColumns {
|
||
get { return this.menuLabelColumns; }
|
||
set { this.menuLabelColumns = value; }
|
||
}
|
||
private string menuLabelColumns = "<22><>";
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD>
|
||
/// </summary>
|
||
[Description("<22><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD>")]
|
||
[Category("<22><>ǩ - ObjectListView"), DefaultValue("ѡ<><D1A1><EFBFBD><EFBFBD>..."), Localizable(true)]
|
||
public string MenuLabelSelectColumns {
|
||
get { return this.menuLabelSelectColumns; }
|
||
set { this.menuLabelSelectColumns = value; }
|
||
}
|
||
private string menuLabelSelectColumns = "ѡ<><D1A1><EFBFBD><EFBFBD>...";
|
||
|
||
/// <summary>
|
||
/// Gets or sets the image that will be place next to the Sort Ascending command
|
||
/// </summary>
|
||
static public Bitmap SortAscendingImage = ryControls.Properties.Resources.SortAscending;
|
||
|
||
/// <summary>
|
||
/// Gets or sets the image that will be placed next to the Sort Descending command
|
||
/// </summary>
|
||
static public Bitmap SortDescendingImage = ryControls.Properties.Resources.SortDescending;
|
||
|
||
/// <summary>
|
||
/// Append the column selection menu items to the given menu strip.
|
||
/// </summary>
|
||
/// <param name="strip">The menu to which the items will be added.</param>
|
||
/// <param name="columnIndex"></param>
|
||
/// <returns>Return the menu to which the items were added</returns>
|
||
public virtual ToolStripDropDown MakeColumnCommandMenu(ToolStripDropDown strip, int columnIndex) {
|
||
OLVColumn column = this.GetColumn(columnIndex);
|
||
if (column == null)
|
||
return strip;
|
||
|
||
if (strip.Items.Count > 0)
|
||
strip.Items.Add(new ToolStripSeparator());
|
||
|
||
string label = String.Format(this.MenuLabelSortAscending, column.Text);
|
||
if (column.Sortable && !String.IsNullOrEmpty(label)) {
|
||
strip.Items.Add(label, ObjectListView.SortAscendingImage, (EventHandler)delegate(object sender, EventArgs args) {
|
||
this.Sort(column, SortOrder.Ascending);
|
||
});
|
||
}
|
||
label = String.Format(this.MenuLabelSortDescending, column.Text);
|
||
if (column.Sortable && !String.IsNullOrEmpty(label)) {
|
||
strip.Items.Add(label, ObjectListView.SortDescendingImage, (EventHandler)delegate(object sender, EventArgs args) {
|
||
this.Sort(column, SortOrder.Descending);
|
||
});
|
||
}
|
||
if (this.CanShowGroups) {
|
||
label = String.Format(this.MenuLabelGroupBy, column.Text);
|
||
if (column.Groupable && !String.IsNullOrEmpty(label)) {
|
||
strip.Items.Add(label, null, (EventHandler)delegate(object sender, EventArgs args) {
|
||
this.ShowGroups = true;
|
||
this.PrimarySortColumn = column;
|
||
this.PrimarySortOrder = SortOrder.Ascending;
|
||
this.BuildList();
|
||
});
|
||
}
|
||
}
|
||
if (this.ShowGroups) {
|
||
if (this.AlwaysGroupByColumn == column) {
|
||
label = String.Format(this.MenuLabelUnlockGroupingOn, column.Text);
|
||
if (!String.IsNullOrEmpty(label)) {
|
||
strip.Items.Add(label, null, (EventHandler)delegate(object sender, EventArgs args) {
|
||
this.AlwaysGroupByColumn = null;
|
||
this.AlwaysGroupBySortOrder = SortOrder.None;
|
||
this.BuildList();
|
||
});
|
||
}
|
||
} else {
|
||
label = String.Format(this.MenuLabelLockGroupingOn, column.Text);
|
||
if (column.Groupable && !String.IsNullOrEmpty(label)) {
|
||
strip.Items.Add(label, null, (EventHandler)delegate(object sender, EventArgs args) {
|
||
this.ShowGroups = true;
|
||
this.AlwaysGroupByColumn = column;
|
||
this.AlwaysGroupBySortOrder = SortOrder.Ascending;
|
||
this.BuildList();
|
||
});
|
||
}
|
||
}
|
||
label = String.Format(this.MenuLabelTurnOffGroups, column.Text);
|
||
if (!String.IsNullOrEmpty(label)) {
|
||
strip.Items.Add(label, null, (EventHandler)delegate(object sender, EventArgs args) {
|
||
this.ShowGroups = false;
|
||
this.BuildList();
|
||
});
|
||
}
|
||
} else {
|
||
label = String.Format(this.MenuLabelUnsort, column.Text);
|
||
if (column.Sortable && !String.IsNullOrEmpty(label) && this.PrimarySortOrder != SortOrder.None) {
|
||
strip.Items.Add(label, null, (EventHandler)delegate(object sender, EventArgs args) {
|
||
this.Unsort();
|
||
});
|
||
}
|
||
}
|
||
|
||
return strip;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Append the column selection menu items to the given menu strip.
|
||
/// </summary>
|
||
/// <param name="strip">The menu to which the items will be added.</param>
|
||
/// <returns>Return the menu to which the items were added</returns>
|
||
public virtual ToolStripDropDown MakeColumnSelectMenu(ToolStripDropDown strip) {
|
||
|
||
System.Diagnostics.Debug.Assert(this.SelectColumnsOnRightClickBehaviour != ColumnSelectBehaviour.None);
|
||
|
||
// Append a separator if the menu isn't empty and the last item isn't already a separator
|
||
if (strip.Items.Count > 0 && (!(strip.Items[strip.Items.Count-1] is ToolStripSeparator)))
|
||
strip.Items.Add(new ToolStripSeparator());
|
||
|
||
if (this.AllColumns.Count > 0 && this.AllColumns[0].LastDisplayIndex == -1)
|
||
this.RememberDisplayIndicies();
|
||
|
||
if (this.SelectColumnsOnRightClickBehaviour == ColumnSelectBehaviour.ModelDialog) {
|
||
strip.Items.Add(this.MenuLabelSelectColumns, null, delegate(object sender, EventArgs args) {
|
||
(new ColumnSelectionForm()).OpenOn(this);
|
||
});
|
||
}
|
||
|
||
if (this.SelectColumnsOnRightClickBehaviour == ColumnSelectBehaviour.Submenu) {
|
||
ToolStripMenuItem menu = new ToolStripMenuItem(this.MenuLabelColumns);
|
||
menu.DropDownItemClicked += new ToolStripItemClickedEventHandler(this.ColumnSelectMenuItemClicked);
|
||
strip.Items.Add(menu);
|
||
this.AddItemsToColumnSelectMenu(menu.DropDownItems);
|
||
}
|
||
|
||
if (this.SelectColumnsOnRightClickBehaviour == ColumnSelectBehaviour.InlineMenu) {
|
||
strip.ItemClicked += new ToolStripItemClickedEventHandler(this.ColumnSelectMenuItemClicked);
|
||
strip.Closing += new ToolStripDropDownClosingEventHandler(this.ColumnSelectMenuClosing);
|
||
this.AddItemsToColumnSelectMenu(strip.Items);
|
||
}
|
||
|
||
return strip;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Create the menu items that will allow columns to be choosen and add them to the
|
||
/// given collection
|
||
/// </summary>
|
||
/// <param name="items"></param>
|
||
protected void AddItemsToColumnSelectMenu(ToolStripItemCollection items) {
|
||
|
||
// Sort columns by display order
|
||
List<OLVColumn> columns = new List<OLVColumn>(this.AllColumns);
|
||
columns.Sort(delegate(OLVColumn x, OLVColumn y) { return (x.LastDisplayIndex - y.LastDisplayIndex); });
|
||
|
||
// Build menu from sorted columns
|
||
foreach (OLVColumn col in columns) {
|
||
ToolStripMenuItem mi = new ToolStripMenuItem(col.Text);
|
||
mi.Checked = col.IsVisible;
|
||
mi.Tag = col;
|
||
|
||
// The 'Index' property returns -1 when the column is not visible, so if the
|
||
// column isn't visible we have to enable the item. Also the first column can't be turned off
|
||
mi.Enabled = !col.IsVisible || col.CanBeHidden;
|
||
items.Add(mi);
|
||
}
|
||
}
|
||
|
||
private void ColumnSelectMenuItemClicked(object sender, ToolStripItemClickedEventArgs e) {
|
||
this.contextMenuStaysOpen = false;
|
||
ToolStripMenuItem menuItemClicked = e.ClickedItem as ToolStripMenuItem;
|
||
if (menuItemClicked == null)
|
||
return;
|
||
OLVColumn col = menuItemClicked.Tag as OLVColumn;
|
||
if (col == null)
|
||
return;
|
||
menuItemClicked.Checked = !menuItemClicked.Checked;
|
||
col.IsVisible = menuItemClicked.Checked;
|
||
this.contextMenuStaysOpen = this.SelectColumnsMenuStaysOpen;
|
||
this.BeginInvoke(new MethodInvoker(this.RebuildColumns));
|
||
}
|
||
private bool contextMenuStaysOpen;
|
||
|
||
private void ColumnSelectMenuClosing(object sender, ToolStripDropDownClosingEventArgs e) {
|
||
e.Cancel = this.contextMenuStaysOpen && e.CloseReason == ToolStripDropDownCloseReason.ItemClicked;
|
||
this.contextMenuStaysOpen = false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Create a Filtering menu
|
||
/// </summary>
|
||
/// <param name="strip"></param>
|
||
/// <param name="columnIndex"></param>
|
||
/// <returns></returns>
|
||
public virtual ToolStripDropDown MakeFilteringMenu(ToolStripDropDown strip, int columnIndex) {
|
||
OLVColumn column = this.GetColumn(columnIndex);
|
||
if (column == null)
|
||
return strip;
|
||
|
||
FilterMenuBuilder strategy = this.FilterMenuBuildStrategy;
|
||
if (strategy == null)
|
||
return strip;
|
||
|
||
return strategy.MakeFilterMenu(strip, this, column);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Override the OnColumnReordered method to do what we want
|
||
/// </summary>
|
||
/// <param name="e"></param>
|
||
protected override void OnColumnReordered(ColumnReorderedEventArgs e) {
|
||
base.OnColumnReordered(e);
|
||
|
||
// The internal logic of the .NET code behind a ENDDRAG event means that,
|
||
// at this point, the DisplayIndex's of the columns are not yet as they are
|
||
// going to be. So we have to invoke a method to run later that will remember
|
||
// what the real DisplayIndex's are.
|
||
this.BeginInvoke(new MethodInvoker(this.RememberDisplayIndicies));
|
||
}
|
||
|
||
private void RememberDisplayIndicies() {
|
||
// Remember the display indexes so we can put them back at a later date
|
||
foreach (OLVColumn x in this.AllColumns)
|
||
x.LastDisplayIndex = x.DisplayIndex;
|
||
}
|
||
|
||
/// <summary>
|
||
/// When the column widths are changing, resize the space filling columns
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
protected virtual void HandleColumnWidthChanging(object sender, ColumnWidthChangingEventArgs e) {
|
||
if (this.UpdateSpaceFillingColumnsWhenDraggingColumnDivider && !this.GetColumn(e.ColumnIndex).FillsFreeSpace) {
|
||
// If the width of a column is increasing, resize any space filling columns allowing the extra
|
||
// space that the new column width is going to consume
|
||
int oldWidth = this.GetColumn(e.ColumnIndex).Width;
|
||
if (e.NewWidth > oldWidth)
|
||
this.ResizeFreeSpaceFillingColumns(this.ClientSize.Width - (e.NewWidth - oldWidth));
|
||
else
|
||
this.ResizeFreeSpaceFillingColumns();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// When the column widths change, resize the space filling columns
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
protected virtual void HandleColumnWidthChanged(object sender, ColumnWidthChangedEventArgs e) {
|
||
if (!this.GetColumn(e.ColumnIndex).FillsFreeSpace)
|
||
this.ResizeFreeSpaceFillingColumns();
|
||
}
|
||
|
||
/// <summary>
|
||
/// When the size of the control changes, we have to resize our space filling columns.
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
protected virtual void HandleLayout(object sender, LayoutEventArgs e) {
|
||
// We have to delay executing the recalculation of the columns, since virtual lists
|
||
// get terribly confused if we resize the column widths during this event.
|
||
if (!this.hasResizeColumnsHandler) {
|
||
this.hasResizeColumnsHandler = true;
|
||
this.RunWhenIdle(this.HandleApplicationIdleResizeColumns);
|
||
}
|
||
}
|
||
|
||
private void RunWhenIdle(EventHandler eventHandler) {
|
||
Application.Idle += eventHandler;
|
||
if (!this.CanUseApplicationIdle) {
|
||
SynchronizationContext.Current.Post(delegate(object x) { Application.RaiseIdle(EventArgs.Empty); }, null);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Resize our space filling columns so they fill any unoccupied width in the control
|
||
/// </summary>
|
||
protected virtual void ResizeFreeSpaceFillingColumns() {
|
||
this.ResizeFreeSpaceFillingColumns(this.ClientSize.Width);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Resize our space filling columns so they fill any unoccupied width in the control
|
||
/// </summary>
|
||
protected virtual void ResizeFreeSpaceFillingColumns(int freeSpace) {
|
||
// It's too confusing to dynamically resize columns at design time.
|
||
if (this.DesignMode)
|
||
return;
|
||
|
||
if (this.Frozen)
|
||
return;
|
||
|
||
// Calculate the free space available
|
||
int totalProportion = 0;
|
||
List<OLVColumn> spaceFillingColumns = new List<OLVColumn>();
|
||
for (int i = 0; i < this.Columns.Count; i++) {
|
||
OLVColumn col = this.GetColumn(i);
|
||
if (col.FillsFreeSpace) {
|
||
spaceFillingColumns.Add(col);
|
||
totalProportion += col.FreeSpaceProportion;
|
||
} else
|
||
freeSpace -= col.Width;
|
||
}
|
||
freeSpace = Math.Max(0, freeSpace);
|
||
|
||
// Any space filling column that would hit it's Minimum or Maximum
|
||
// width must be treated as a fixed column.
|
||
foreach (OLVColumn col in spaceFillingColumns.ToArray()) {
|
||
int newWidth = (freeSpace * col.FreeSpaceProportion) / totalProportion;
|
||
|
||
if (col.MinimumWidth != -1 && newWidth < col.MinimumWidth)
|
||
newWidth = col.MinimumWidth;
|
||
else if (col.MaximumWidth != -1 && newWidth > col.MaximumWidth)
|
||
newWidth = col.MaximumWidth;
|
||
else
|
||
newWidth = 0;
|
||
|
||
if (newWidth > 0) {
|
||
col.Width = newWidth;
|
||
freeSpace -= newWidth;
|
||
totalProportion -= col.FreeSpaceProportion;
|
||
spaceFillingColumns.Remove(col);
|
||
}
|
||
}
|
||
|
||
// Distribute the free space between the columns
|
||
foreach (OLVColumn col in spaceFillingColumns) {
|
||
col.Width = (freeSpace*col.FreeSpaceProportion)/totalProportion;
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Checkboxes
|
||
|
||
/// <summary>
|
||
/// Check all rows
|
||
/// </summary>
|
||
public virtual void CheckAll()
|
||
{
|
||
this.CheckedObjects = EnumerableToArray(this.Objects, false);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Check the checkbox in the given column header
|
||
/// </summary>
|
||
/// <remarks>If the given columns header check box is linked to the cell check boxes,
|
||
/// then checkboxes in all cells will also be checked.</remarks>
|
||
/// <param name="column"></param>
|
||
public virtual void CheckHeaderCheckBox(OLVColumn column)
|
||
{
|
||
if (column == null)
|
||
return;
|
||
|
||
ChangeHeaderCheckBoxState(column, CheckState.Checked);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Mark the checkbox in the given column header as having an indeterminate value
|
||
/// </summary>
|
||
/// <param name="column"></param>
|
||
public virtual void CheckIndeterminateHeaderCheckBox(OLVColumn column)
|
||
{
|
||
if (column == null)
|
||
return;
|
||
|
||
ChangeHeaderCheckBoxState(column, CheckState.Indeterminate);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Mark the given object as indeterminate check state
|
||
/// </summary>
|
||
/// <param name="modelObject">The model object to be marked indeterminate</param>
|
||
public virtual void CheckIndeterminateObject(object modelObject) {
|
||
this.SetObjectCheckedness(modelObject, CheckState.Indeterminate);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Mark the given object as checked in the list
|
||
/// </summary>
|
||
/// <param name="modelObject">The model object to be checked</param>
|
||
public virtual void CheckObject(object modelObject) {
|
||
this.SetObjectCheckedness(modelObject, CheckState.Checked);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Mark the given objects as checked in the list
|
||
/// </summary>
|
||
/// <param name="modelObjects">The model object to be checked</param>
|
||
public virtual void CheckObjects(IEnumerable modelObjects) {
|
||
foreach (object model in modelObjects)
|
||
this.CheckObject(model);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Put a check into the check box at the given cell
|
||
/// </summary>
|
||
/// <param name="rowObject"></param>
|
||
/// <param name="column"></param>
|
||
public virtual void CheckSubItem(object rowObject, OLVColumn column) {
|
||
if (column == null || rowObject == null || !column.CheckBoxes)
|
||
return;
|
||
|
||
column.PutCheckState(rowObject, CheckState.Checked);
|
||
this.RefreshObject(rowObject);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Put an indeterminate check into the check box at the given cell
|
||
/// </summary>
|
||
/// <param name="rowObject"></param>
|
||
/// <param name="column"></param>
|
||
public virtual void CheckIndeterminateSubItem(object rowObject, OLVColumn column) {
|
||
if (column == null || rowObject == null || !column.CheckBoxes)
|
||
return;
|
||
|
||
column.PutCheckState(rowObject, CheckState.Indeterminate);
|
||
this.RefreshObject(rowObject);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Return true of the given object is checked
|
||
/// </summary>
|
||
/// <param name="modelObject">The model object whose checkedness is returned</param>
|
||
/// <returns>Is the given object checked?</returns>
|
||
/// <remarks>If the given object is not in the list, this method returns false.</remarks>
|
||
public virtual bool IsChecked(object modelObject) {
|
||
return this.GetCheckState(modelObject) == CheckState.Checked;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Return true of the given object is indeterminately checked
|
||
/// </summary>
|
||
/// <param name="modelObject">The model object whose checkedness is returned</param>
|
||
/// <returns>Is the given object indeterminately checked?</returns>
|
||
/// <remarks>If the given object is not in the list, this method returns false.</remarks>
|
||
public virtual bool IsCheckedIndeterminate(object modelObject) {
|
||
return this.GetCheckState(modelObject) == CheckState.Indeterminate;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Is there a check at the check box at the given cell
|
||
/// </summary>
|
||
/// <param name="rowObject"></param>
|
||
/// <param name="column"></param>
|
||
public virtual bool IsSubItemChecked(object rowObject, OLVColumn column) {
|
||
if (column == null || rowObject == null || !column.CheckBoxes)
|
||
return false;
|
||
return (column.GetCheckState(rowObject) == CheckState.Checked);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Get the checkedness of an object from the model. Returning null means the
|
||
/// model does not know and the value from the control will be used.
|
||
/// </summary>
|
||
/// <param name="modelObject"></param>
|
||
/// <returns></returns>
|
||
protected virtual CheckState? GetCheckState(Object modelObject) {
|
||
if (this.CheckStateGetter != null)
|
||
return this.CheckStateGetter(modelObject);
|
||
return this.PersistentCheckBoxes ? this.GetPersistentCheckState(modelObject) : (CheckState?)null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Record the change of checkstate for the given object in the model.
|
||
/// This does not update the UI -- only the model
|
||
/// </summary>
|
||
/// <param name="modelObject"></param>
|
||
/// <param name="state"></param>
|
||
/// <returns>The check state that was recorded and that should be used to update
|
||
/// the control.</returns>
|
||
protected virtual CheckState PutCheckState(Object modelObject, CheckState state) {
|
||
if (this.CheckStatePutter != null)
|
||
return this.CheckStatePutter(modelObject, state);
|
||
return this.PersistentCheckBoxes ? this.SetPersistentCheckState(modelObject, state) : state;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Change the check state of the given object to be the given state.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// If the given model object isn't in the list, we still try to remember
|
||
/// its state, in case it is referenced in the future.</remarks>
|
||
/// <param name="modelObject"></param>
|
||
/// <param name="state"></param>
|
||
/// <returns>True if the checkedness of the model changed</returns>
|
||
protected virtual bool SetObjectCheckedness(object modelObject, CheckState state) {
|
||
|
||
if (GetCheckState(modelObject) == state)
|
||
return false;
|
||
|
||
OLVListItem olvi = this.ModelToItem(modelObject);
|
||
|
||
// If we didn't find the given, we still try to record the check state.
|
||
if (olvi == null) {
|
||
this.PutCheckState(modelObject, state);
|
||
return true;
|
||
}
|
||
|
||
// Trigger checkbox changing event
|
||
ItemCheckEventArgs ice = new ItemCheckEventArgs(olvi.Index, state, olvi.CheckState);
|
||
this.OnItemCheck(ice);
|
||
if (ice.NewValue == olvi.CheckState)
|
||
return false;
|
||
|
||
olvi.CheckState = this.PutCheckState(modelObject, state);
|
||
this.RefreshItem(olvi);
|
||
|
||
// Trigger check changed event
|
||
this.OnItemChecked(new ItemCheckedEventArgs(olvi));
|
||
return true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Toggle the checkedness of the given object. A checked object becomes
|
||
/// unchecked; an unchecked or indeterminate object becomes checked.
|
||
/// If the list has tristate checkboxes, the order is:
|
||
/// unchecked -> checked -> indeterminate -> unchecked ...
|
||
/// </summary>
|
||
/// <param name="modelObject">The model object to be checked</param>
|
||
public virtual void ToggleCheckObject(object modelObject) {
|
||
OLVListItem olvi = this.ModelToItem(modelObject);
|
||
if (olvi == null)
|
||
return;
|
||
|
||
CheckState newState = CheckState.Checked;
|
||
|
||
if (olvi.CheckState == CheckState.Checked) {
|
||
newState = this.TriStateCheckBoxes ? CheckState.Indeterminate : CheckState.Unchecked;
|
||
} else {
|
||
if (olvi.CheckState == CheckState.Indeterminate && this.TriStateCheckBoxes)
|
||
newState = CheckState.Unchecked;
|
||
}
|
||
this.SetObjectCheckedness(modelObject, newState);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Toggle the checkbox in the header of the given column
|
||
/// </summary>
|
||
/// <remarks>Obviously, this is only useful if the column actually has a header checkbox.</remarks>
|
||
/// <param name="column"></param>
|
||
public virtual void ToggleHeaderCheckBox(OLVColumn column) {
|
||
if (column == null)
|
||
return;
|
||
|
||
CheckState newState = CalculateToggledCheckState(column.HeaderCheckState, column.HeaderTriStateCheckBox, column.HeaderCheckBoxDisabled);
|
||
ChangeHeaderCheckBoxState(column, newState);
|
||
}
|
||
|
||
private void ChangeHeaderCheckBoxState(OLVColumn column, CheckState newState) {
|
||
// Tell the world the checkbox was clicked
|
||
HeaderCheckBoxChangingEventArgs args = new HeaderCheckBoxChangingEventArgs();
|
||
args.Column = column;
|
||
args.NewCheckState = newState;
|
||
|
||
this.OnHeaderCheckBoxChanging(args);
|
||
if (args.Cancel || column.HeaderCheckState == args.NewCheckState)
|
||
return;
|
||
|
||
Stopwatch sw = Stopwatch.StartNew();
|
||
|
||
column.HeaderCheckState = args.NewCheckState;
|
||
this.HeaderControl.Invalidate(column);
|
||
|
||
if (column.HeaderCheckBoxUpdatesRowCheckBoxes) {
|
||
if (column.Index == 0)
|
||
this.UpdateAllPrimaryCheckBoxes(column);
|
||
else
|
||
this.UpdateAllSubItemCheckBoxes(column);
|
||
}
|
||
|
||
Debug.WriteLine(String.Format("PERF - Changing row checkboxes on {2} objects took {0}ms / {1} ticks", sw.ElapsedMilliseconds, sw.ElapsedTicks, this.GetItemCount()));
|
||
}
|
||
|
||
private void UpdateAllPrimaryCheckBoxes(OLVColumn column) {
|
||
if (!this.CheckBoxes || column.HeaderCheckState == CheckState.Indeterminate)
|
||
return;
|
||
|
||
if (column.HeaderCheckState == CheckState.Checked)
|
||
CheckAll();
|
||
else
|
||
UncheckAll();
|
||
}
|
||
|
||
private void UpdateAllSubItemCheckBoxes(OLVColumn column) {
|
||
if (!column.CheckBoxes || column.HeaderCheckState == CheckState.Indeterminate)
|
||
return;
|
||
|
||
foreach (object model in this.Objects)
|
||
column.PutCheckState(model, column.HeaderCheckState);
|
||
this.BuildList(true);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Toggle the check at the check box of the given cell
|
||
/// </summary>
|
||
/// <param name="rowObject"></param>
|
||
/// <param name="column"></param>
|
||
public virtual void ToggleSubItemCheckBox(object rowObject, OLVColumn column) {
|
||
CheckState currentState = column.GetCheckState(rowObject);
|
||
CheckState newState = CalculateToggledCheckState(currentState, column.TriStateCheckBoxes, false);
|
||
|
||
SubItemCheckingEventArgs args = new SubItemCheckingEventArgs(column, this.ModelToItem(rowObject), column.Index, currentState, newState);
|
||
this.OnSubItemChecking(args);
|
||
if (args.Canceled)
|
||
return;
|
||
|
||
switch (args.NewValue) {
|
||
case CheckState.Checked:
|
||
this.CheckSubItem(rowObject, column);
|
||
break;
|
||
case CheckState.Indeterminate:
|
||
this.CheckIndeterminateSubItem(rowObject, column);
|
||
break;
|
||
case CheckState.Unchecked:
|
||
this.UncheckSubItem(rowObject, column);
|
||
break;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Uncheck all rows
|
||
/// </summary>
|
||
public virtual void UncheckAll()
|
||
{
|
||
this.CheckedObjects = null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Mark the given object as unchecked in the list
|
||
/// </summary>
|
||
/// <param name="modelObject">The model object to be unchecked</param>
|
||
public virtual void UncheckObject(object modelObject) {
|
||
this.SetObjectCheckedness(modelObject, CheckState.Unchecked);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Mark the given objects as unchecked in the list
|
||
/// </summary>
|
||
/// <param name="modelObjects">The model object to be checked</param>
|
||
public virtual void UncheckObjects(IEnumerable modelObjects) {
|
||
foreach (object model in modelObjects)
|
||
this.UncheckObject(model);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Uncheck the checkbox in the given column header
|
||
/// </summary>
|
||
/// <param name="column"></param>
|
||
public virtual void UncheckHeaderCheckBox(OLVColumn column)
|
||
{
|
||
if (column == null)
|
||
return;
|
||
|
||
ChangeHeaderCheckBoxState(column, CheckState.Unchecked);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Uncheck the check at the given cell
|
||
/// </summary>
|
||
/// <param name="rowObject"></param>
|
||
/// <param name="column"></param>
|
||
public virtual void UncheckSubItem(object rowObject, OLVColumn column)
|
||
{
|
||
if (column == null || rowObject == null || !column.CheckBoxes)
|
||
return;
|
||
|
||
column.PutCheckState(rowObject, CheckState.Unchecked);
|
||
this.RefreshObject(rowObject);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region OLV accessing
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <param name="index">Index of the column to be returned</param>
|
||
/// <returns>An OLVColumn</returns>
|
||
public virtual OLVColumn GetColumn(int index) {
|
||
return (OLVColumn)this.Columns[index];
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E2B4A6><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>ı<EFBFBD><C4B1><EFBFBD>,<2C><>Ĭ<EFBFBD><C4AC>ֻ<EFBFBD><D6BB><EFBFBD>ص<EFBFBD>һ<EFBFBD><D2BB>
|
||
/// </summary>
|
||
/// <param name="name">Ҫ<><D2AA><EFBFBD>ص<EFBFBD><D8B5>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD></param>
|
||
/// <returns>An OLVColumn</returns>
|
||
public virtual OLVColumn GetColumn(string name) {
|
||
foreach (ColumnHeader column in this.Columns) {
|
||
if (column.Text == name)
|
||
return (OLVColumn)column;
|
||
}
|
||
return null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD>ɼ<EFBFBD><C9BC><EFBFBD><EFBFBD>еļ<D0B5><C4BC>ϡ<EFBFBD>ֻ<EFBFBD><D6BB>Tile<6C><65>Details<6C><73><EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD>0<EFBFBD>С<EFBFBD>
|
||
/// </summary>
|
||
/// <param name="view"><3E><><EFBFBD><EFBFBD>Ϊ<EFBFBD>ĸ<EFBFBD><C4B8><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD></param>
|
||
/// <returns>A list of columns</returns>
|
||
public virtual List<OLVColumn> GetFilteredColumns(View view) {
|
||
// For both detail and tile view, the first column must be included. Normally, we would
|
||
// use the ColumnHeader.Index property, but if the header is not currently part of a ListView
|
||
// that property returns -1. So, we track the index of
|
||
// the column header, and always include the first header.
|
||
|
||
int index = 0;
|
||
return this.AllColumns.FindAll(delegate(OLVColumn x) {
|
||
return (index++ == 0) || x.IsVisible;
|
||
});
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1>е<EFBFBD><D0B5><EFBFBD>Ŀ<EFBFBD><C4BF>
|
||
/// </summary>
|
||
/// <returns><3E>б<EFBFBD><D0B1>е<EFBFBD><D0B5><EFBFBD>Ŀ<EFBFBD><C4BF></returns>
|
||
/// <remarks><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ<EFBFBD><D7B0>ɸѡ<C9B8><D1A1><EFBFBD><EFBFBD><EFBFBD>⽫<EFBFBD><E2BDAB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɸѡ<C9B8><D1A1>ƥ<EFBFBD><C6A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD></remarks>
|
||
public virtual int GetItemCount() {
|
||
return this.Items.Count;
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <param name="index">Index of the item to be returned</param>
|
||
/// <returns>An OLVListItem</returns>
|
||
public virtual OLVListItem GetItem(int index) {
|
||
if (index < 0 || index >= this.GetItemCount())
|
||
return null;
|
||
|
||
return (OLVListItem)this.Items[index];
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD>
|
||
/// </summary>
|
||
/// <param name="index">Index of the model object to be returned</param>
|
||
/// <returns>A model object</returns>
|
||
public virtual object GetModelObject(int index) {
|
||
OLVListItem item = this.GetItem(index);
|
||
return item == null ? null : item.RowObject;
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20>ҳ<EFBFBD><D2B3>ڸ<EFBFBD><DAB8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD><C2B5>к<EFBFBD><D0BA><EFBFBD></summary>
|
||
/// <param name="x">X <20><><EFBFBD><EFBFBD></param>
|
||
/// <param name="y">Y <20><><EFBFBD><EFBFBD></param>
|
||
/// <param name="hitColumn"><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD><C2B5><EFBFBD><EFBFBD><EFBFBD></param>
|
||
/// <returns><3E>ڸ<EFBFBD><DAB8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD><C2B5><EFBFBD><EFBFBD><EFBFBD><EEA1A3><EFBFBD><EFBFBD>Ϊnull<6C><6C></returns>
|
||
public virtual OLVListItem GetItemAt(int x, int y, out OLVColumn hitColumn) {
|
||
hitColumn = null;
|
||
ListViewHitTestInfo info = this.HitTest(x, y);
|
||
if (info.Item == null)
|
||
return null;
|
||
|
||
if (info.SubItem != null) {
|
||
int subItemIndex = info.Item.SubItems.IndexOf(info.SubItem);
|
||
hitColumn = this.GetColumn(subItemIndex);
|
||
}
|
||
|
||
return (OLVListItem)info.Item;
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<2F>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <param name="index">Index of the item to be returned</param>
|
||
/// <param name="columnIndex">Index of the subitem to be returned</param>
|
||
/// <returns>An OLVListSubItem</returns>
|
||
public virtual OLVListSubItem GetSubItem(int index, int columnIndex) {
|
||
OLVListItem olvi = this.GetItem(index);
|
||
return olvi == null ? null : olvi.GetSubItem(columnIndex);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Object manipulation
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD><CDBC>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD>ڶ<EFBFBD><DAB6><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <param name="lvg">The group to be revealed</param>
|
||
/// <remarks><para>
|
||
///<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɼ<EFBFBD><C9BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܣ<EFBFBD><DCA3>б<EFBFBD><D0B1>Խ<EFBFBD><D4BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD><D4BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </para>
|
||
/// <para><3E><>ֻ<EFBFBD><D6BB><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>Ч(<28><>Ȼ)<29><></para>
|
||
/// <para><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1>ϲ<EFBFBD><CFB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD><C3A3><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ʹ<EFBFBD><CAB9>ListViewGroups<70><73><EFBFBD>з<EFBFBD><D0B7>顣ʹ<E9A1A3><CAB9> <see cref="VirtualObjectListView.EnsureNthGroupVisible"/> <20><><EFBFBD><EFBFBD>.</para>
|
||
/// </remarks>
|
||
public virtual void EnsureGroupVisible(ListViewGroup lvg) {
|
||
if (!this.ShowGroups || lvg == null)
|
||
return;
|
||
|
||
int groupIndex = this.Groups.IndexOf(lvg);
|
||
if (groupIndex <= 0) {
|
||
// There is no easy way to scroll back to the beginning of the list
|
||
int delta = 0 - NativeMethods.GetScrollPosition(this, false);
|
||
NativeMethods.Scroll(this, 0, delta);
|
||
} else {
|
||
// Find the display rectangle of the last item in the previous group
|
||
ListViewGroup previousGroup = this.Groups[groupIndex - 1];
|
||
ListViewItem lastItemInGroup = previousGroup.Items[previousGroup.Items.Count - 1];
|
||
Rectangle r = this.GetItemRect(lastItemInGroup.Index);
|
||
|
||
// Scroll so that the last item of the previous group is just out of sight,
|
||
// which will make the desired group header visible.
|
||
int delta = r.Y + r.Height / 2;
|
||
NativeMethods.Scroll(this, 0, delta);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// ʹ<><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD>ɼ<EFBFBD>
|
||
/// </summary>
|
||
/// <param name="modelObject">The model object to be revealed</param>
|
||
public virtual void EnsureModelVisible(Object modelObject) {
|
||
int index = this.IndexOf(modelObject);
|
||
if (index >= 0)
|
||
this.EnsureVisible(index);
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD>е<EFBFBD>ģ<EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><D0B6><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>null
|
||
/// </summary>
|
||
/// <returns>Model object or null</returns>
|
||
[Obsolete("ʹ<><CAB9> SelectedObject <20><><EFBFBD>Դ<EFBFBD><D4B4>汾<EFBFBD><E6B1BE><EFBFBD><EFBFBD>")]
|
||
public virtual object GetSelectedObject() {
|
||
return this.SelectedObject;
|
||
}
|
||
|
||
/// <summary>
|
||
///<2F><><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD>е<EFBFBD>ģ<EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD>ؿռ<D8BF><D5BC><EFBFBD>
|
||
/// </summary>
|
||
/// <returns>ArrayList</returns>
|
||
[Obsolete("ʹ<><CAB9> SelectedObjects <20><><EFBFBD>Դ<EFBFBD><D4B4>汾<EFBFBD><E6B1BE><EFBFBD><EFBFBD>")]
|
||
public virtual ArrayList GetSelectedObjects() {
|
||
return ObjectListView.EnumerableToArray(this.SelectedObjects, false);
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD>е<EFBFBD>ģ<EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δѡ<CEB4><D1A1><EFBFBD>л<EFBFBD>ѡ<EFBFBD>ж<EFBFBD><D0B6>У<EFBFBD><D0A3><EFBFBD>NULL
|
||
/// </summary>
|
||
/// <returns>Model object or null</returns>
|
||
/// <remarks>ʹ<><CAB9> CheckedObject <20><><EFBFBD>Դ<EFBFBD><D4B4>汾<EFBFBD><E6B1BE><EFBFBD><EFBFBD></remarks>
|
||
[Obsolete("ʹ<><CAB9> CheckedObject <20><><EFBFBD>Դ<EFBFBD><D4B4>汾<EFBFBD><E6B1BE><EFBFBD><EFBFBD>")]
|
||
public virtual object GetCheckedObject() {
|
||
return this.CheckedObject;
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><>ȡѡ<C8A1>е<EFBFBD>ģ<EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC>ϡ<EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>ʹ<><CAB9> CheckedObjects <20><><EFBFBD>Դ<EFBFBD><D4B4>汾<EFBFBD><E6B1BE><EFBFBD><EFBFBD></remarks>
|
||
[Obsolete("ʹ<><CAB9> CheckedObjects <20><><EFBFBD>Դ<EFBFBD><D4B4>汾<EFBFBD><E6B1BE><EFBFBD><EFBFBD>")]
|
||
public virtual ArrayList GetCheckedObjects() {
|
||
return ObjectListView.EnumerableToArray(this.CheckedObjects, false);
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD>в<EFBFBD><D0B2>Ҹ<EFBFBD><D2B8><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD><F3B2A2B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <param name="modelObject">The model object to be found</param>
|
||
/// <returns>The index of the object. -1 means the object was not present</returns>
|
||
public virtual int IndexOf(Object modelObject) {
|
||
for (int i = 0; i < this.GetItemCount(); i++) {
|
||
if (this.GetModelObject(i).Equals(modelObject))
|
||
return i;
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Rebuild the given ListViewItem with the data from its associated model.
|
||
/// </summary>
|
||
/// <remarks>This method does not resort or regroup the view. It simply updates
|
||
/// the displayed data of the given item</remarks>
|
||
public virtual void RefreshItem(OLVListItem olvi) {
|
||
olvi.UseItemStyleForSubItems = true;
|
||
olvi.SubItems.Clear();
|
||
this.FillInValues(olvi, olvi.RowObject);
|
||
this.PostProcessOneRow(olvi.Index, this.GetDisplayOrderOfItemIndex(olvi.Index), olvi);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Rebuild the data on the row that is showing the given object.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// This method does not resort or regroup the view.
|
||
/// </para>
|
||
/// <para>
|
||
/// The given object is *not* used as the source of data for the rebuild.
|
||
/// It is only used to locate the matching model in the <see cref="Objects"/> collection,
|
||
/// then that matching model is used as the data source. This distinction is
|
||
/// only important in model classes that have overridden the Equals() method.
|
||
/// </para>
|
||
/// <para>
|
||
/// If you want the given model object to replace the pre-existing model,
|
||
/// use <see cref="UpdateObject"/>.
|
||
/// </para>
|
||
/// </remarks>
|
||
public virtual void RefreshObject(object modelObject) {
|
||
this.RefreshObjects(new object[] { modelObject });
|
||
}
|
||
|
||
/// <summary>
|
||
/// Update the rows that are showing the given objects
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>This method does not resort or regroup the view.</para>
|
||
/// <para>This method can safely be called from background threads.</para>
|
||
/// </remarks>
|
||
public virtual void RefreshObjects(IList modelObjects) {
|
||
if (this.InvokeRequired) {
|
||
this.Invoke((MethodInvoker)delegate { this.RefreshObjects(modelObjects); });
|
||
return;
|
||
}
|
||
foreach (object modelObject in modelObjects) {
|
||
OLVListItem olvi = this.ModelToItem(modelObject);
|
||
if (olvi != null) {
|
||
this.ReplaceModel(olvi, modelObject);
|
||
this.RefreshItem(olvi);
|
||
}
|
||
}
|
||
}
|
||
|
||
private void ReplaceModel(OLVListItem olvi, object newModel) {
|
||
if (ReferenceEquals(olvi.RowObject, newModel))
|
||
return;
|
||
|
||
this.TakeOwnershipOfObjects();
|
||
ArrayList array = ObjectListView.EnumerableToArray(this.Objects, false);
|
||
int i = array.IndexOf(olvi.RowObject);
|
||
if (i >= 0)
|
||
array[i] = newModel;
|
||
|
||
olvi.RowObject = newModel;
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>This method does not resort or regroup the view.</remarks>
|
||
public virtual void RefreshSelectedObjects() {
|
||
foreach (ListViewItem lvi in this.SelectedItems)
|
||
this.RefreshItem((OLVListItem)lvi);
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD>κε<CEBA>ǰѡ<C7B0><D1A1><EFBFBD>⣬<EFBFBD><E2A3AC>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD>ģ<EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>
|
||
/// </summary>
|
||
/// <param name="modelObject">The object to be selected</param>
|
||
/// <remarks>Use the <see cref="SelectedObject"/> property to deselect all other rows</remarks>
|
||
public virtual void SelectObject(object modelObject) {
|
||
this.SelectObject(modelObject, false);
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD>κε<CEBA>ǰѡ<C7B0><D1A1><EFBFBD>⣬<EFBFBD><E2A3AC>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD>ģ<EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>
|
||
/// </summary>
|
||
/// <param name="modelObject">The object to be selected</param>
|
||
/// <param name="setFocus"><3E><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD>ҲӦ<D2B2>ñ<EFBFBD><C3B1>۽<EFBFBD></param>
|
||
/// <remarks>Use the <see cref="SelectedObject"/> property to deselect all other rows</remarks>
|
||
public virtual void SelectObject(object modelObject, bool setFocus) {
|
||
OLVListItem olvi = this.ModelToItem(modelObject);
|
||
if (olvi != null && olvi.Enabled) {
|
||
olvi.Selected = true;
|
||
if (setFocus)
|
||
olvi.Focused = true;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// ѡ<><D1A1><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>ȡ<EFBFBD><C8A1>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>
|
||
/// </summary>
|
||
/// <param name="modelObjects">A collection of model objects</param>
|
||
public virtual void SelectObjects(IList modelObjects) {
|
||
this.SelectedIndices.Clear();
|
||
|
||
if (modelObjects == null)
|
||
return;
|
||
|
||
foreach (object modelObject in modelObjects) {
|
||
OLVListItem olvi = this.ModelToItem(modelObject);
|
||
if (olvi != null && olvi.Enabled)
|
||
olvi.Selected = true;
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Freezing/Suspending
|
||
|
||
/// <summary>
|
||
///<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<C7B7><F1B6B3BD>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҹ<EFBFBD><D2B8>¡<EFBFBD>
|
||
/// </summary>
|
||
/// <remarks><para>Frozen<65><6E><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Freeze()/UnFreeze()<29><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD>
|
||
/// <20><>֮ͬ<CDAC><D6AE><EFBFBD><EFBFBD><EFBFBD>ڽ<EFBFBD>Frozen<65><6E><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ΪFalse<73><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ⶳ<EFBFBD>ؼ<EFBFBD><D8BC><EFBFBD>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><D0B6><EFBFBD>δ<EFBFBD><CEB4><EFBFBD>ɵ<EFBFBD>Freeze()<29><><EFBFBD>á<EFBFBD></para></remarks>
|
||
/// <example>objectListView1.Frozen = false; // unfreeze the control now!
|
||
/// </example>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
public virtual bool Frozen {
|
||
get { return freezeCount > 0; }
|
||
set {
|
||
if (value)
|
||
Freeze();
|
||
else if (freezeCount > 0) {
|
||
freezeCount = 1;
|
||
Unfreeze();
|
||
}
|
||
}
|
||
}
|
||
private int freezeCount;
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD><CDBC>ʹ<EFBFBD>䲻<EFBFBD><E4B2BB><EFBFBD><EFBFBD><EFBFBD>Ҹ<EFBFBD><D2B8>¡<EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>Freeze()/Unfreeze() calls nest correctly</remarks>
|
||
public virtual void Freeze() {
|
||
if (freezeCount == 0)
|
||
DoFreeze();
|
||
|
||
freezeCount++;
|
||
this.OnFreezing(new FreezeEventArgs(freezeCount));
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20>ⶳ<EFBFBD>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><CBB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>unFreeze()<29><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¹<EFBFBD><C2B9><EFBFBD>listview<65><77><EFBFBD><EFBFBD><EFBFBD>ݡ<EFBFBD>
|
||
/// </summary>
|
||
/// <remarks>Freeze()/Unfreeze() calls nest correctly</remarks>
|
||
public virtual void Unfreeze() {
|
||
if (freezeCount <= 0)
|
||
return;
|
||
|
||
freezeCount--;
|
||
if (freezeCount == 0)
|
||
DoUnfreeze();
|
||
|
||
this.OnFreezing(new FreezeEventArgs(freezeCount));
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20>ڶ<EFBFBD><DAB6><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ͼʱִ<CAB1><D6B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD>
|
||
/// </summary>
|
||
protected virtual void DoFreeze() {
|
||
this.BeginUpdate();
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20>ⶳ<EFBFBD>б<EFBFBD><D0B1><EFBFBD>ͼʱִ<CAB1><D6B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD>
|
||
/// </summary>
|
||
protected virtual void DoUnfreeze()
|
||
{
|
||
this.EndUpdate();
|
||
this.ResizeFreeSpaceFillingColumns();
|
||
this.BuildList();
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD>¼<EFBFBD><C2BC><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>TRUE<55><45><EFBFBD>ڹ<EFBFBD><DAB9><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD>¼<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>SelectedIndexChanged<65><64>SelectionChanged<65>¼<EFBFBD><C2BC><EFBFBD>
|
||
/// </summary>
|
||
[Browsable(false),
|
||
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||
protected bool SelectionEventsSuspended {
|
||
get { return this.suspendSelectionEventCount > 0; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Suspend selection events until a matching ResumeSelectionEvents()
|
||
/// is called.
|
||
/// </summary>
|
||
/// <remarks>Calls to this method nest correctly. Every call to SuspendSelectionEvents()
|
||
/// must have a matching ResumeSelectionEvents().</remarks>
|
||
protected void SuspendSelectionEvents() {
|
||
this.suspendSelectionEventCount++;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Resume raising selection events.
|
||
/// </summary>
|
||
protected void ResumeSelectionEvents() {
|
||
Debug.Assert(this.SelectionEventsSuspended, "Mismatched called to ResumeSelectionEvents()");
|
||
this.suspendSelectionEventCount--;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Returns a disposable that will disable selection events
|
||
/// during a using() block.
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
protected IDisposable SuspendSelectionEventsDuring() {
|
||
return new SuspendSelectionDisposable(this);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Implementation only class that suspends and resumes selection
|
||
/// events on instance creation and disposal.
|
||
/// </summary>
|
||
private class SuspendSelectionDisposable : IDisposable {
|
||
public SuspendSelectionDisposable(ObjectListView objectListView) {
|
||
this.objectListView = objectListView;
|
||
this.objectListView.SuspendSelectionEvents();
|
||
}
|
||
|
||
public void Dispose() {
|
||
this.objectListView.ResumeSelectionEvents();
|
||
}
|
||
|
||
private readonly ObjectListView objectListView;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Column sorting
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>к<EFBFBD>˳<EFBFBD><CBB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
new public void Sort() {
|
||
this.Sort(this.PrimarySortColumn, this.PrimarySortOrder);
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD>ϴ<EFBFBD><CFB4><EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD><CBB3><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <param name="columnToSortName"><3E><>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD></param>
|
||
public virtual void Sort(string columnToSortName) {
|
||
this.Sort(this.GetColumn(columnToSortName), this.PrimarySortOrder);
|
||
}
|
||
|
||
/// <summary>
|
||
///<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD>ϴ<EFBFBD><CFB4><EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD><CBB3><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <param name="columnToSortIndex"><3E><>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD></param>
|
||
public virtual void Sort(int columnToSortIndex) {
|
||
if (columnToSortIndex >= 0 && columnToSortIndex < this.Columns.Count)
|
||
this.Sort(this.GetColumn(columnToSortIndex), this.PrimarySortOrder);
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD>ϴ<EFBFBD><CFB4><EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD><CBB3><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <param name="columnToSort"><3E><>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></param>
|
||
public virtual void Sort(OLVColumn columnToSort) {
|
||
if (this.InvokeRequired) {
|
||
this.Invoke((MethodInvoker)delegate { this.Sort(columnToSort); });
|
||
} else {
|
||
this.Sort(columnToSort, this.PrimarySortOrder);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD>ϴ<EFBFBD><CFB4><EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD><CBB3><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
/// </summary>
|
||
/// <param name="columnToSort">The column whose values will be used for the sorting.
|
||
/// If null, the first column will be used.</param>
|
||
/// <param name="order">The ordering to be used for sorting. If this is None,
|
||
/// this.Sorting and then SortOrder.Ascending will be used</param>
|
||
/// <remarks>If ShowGroups is true, the rows will be grouped by the given column.
|
||
/// If AlwaysGroupsByColumn is not null, the rows will be grouped by that column,
|
||
/// and the rows within each group will be sorted by the given column.</remarks>
|
||
public virtual void Sort(OLVColumn columnToSort, SortOrder order) {
|
||
if (this.InvokeRequired) {
|
||
this.Invoke((MethodInvoker)delegate { this.Sort(columnToSort, order); });
|
||
} else {
|
||
this.DoSort(columnToSort, order);
|
||
this.PostProcessRows();
|
||
}
|
||
}
|
||
|
||
private void DoSort(OLVColumn columnToSort, SortOrder order) {
|
||
// Sanity checks
|
||
if (this.GetItemCount() == 0 || this.Columns.Count == 0)
|
||
return;
|
||
|
||
// Fill in default values, if the parameters don't make sense
|
||
if (this.ShowGroups) {
|
||
columnToSort = columnToSort ?? this.GetColumn(0);
|
||
if (order == SortOrder.None) {
|
||
order = this.Sorting;
|
||
if (order == SortOrder.None)
|
||
order = SortOrder.Ascending;
|
||
}
|
||
}
|
||
|
||
// Give the world a chance to fiddle with or completely avoid the sorting process
|
||
BeforeSortingEventArgs args = this.BuildBeforeSortingEventArgs(columnToSort, order);
|
||
this.OnBeforeSorting(args);
|
||
if (args.Canceled)
|
||
return;
|
||
|
||
// Virtual lists don't preserve selection, so we have to do it specifically
|
||
// THINK: Do we need to preserve focus too?
|
||
IList selection = this.VirtualMode ? this.SelectedObjects : null;
|
||
this.SuspendSelectionEvents();
|
||
|
||
this.ClearHotItem();
|
||
|
||
// Finally, do the work of sorting, unless an event handler has already done the sorting for us
|
||
if (!args.Handled) {
|
||
// Sanity checks
|
||
if (args.ColumnToSort != null && args.SortOrder != SortOrder.None) {
|
||
if (this.ShowGroups)
|
||
this.BuildGroups(args.ColumnToGroupBy, args.GroupByOrder, args.ColumnToSort, args.SortOrder,
|
||
args.SecondaryColumnToSort, args.SecondarySortOrder);
|
||
else if (this.CustomSorter != null)
|
||
this.CustomSorter(args.ColumnToSort, args.SortOrder);
|
||
else
|
||
this.ListViewItemSorter = new ColumnComparer(args.ColumnToSort, args.SortOrder,
|
||
args.SecondaryColumnToSort, args.SecondarySortOrder);
|
||
}
|
||
}
|
||
|
||
if (this.ShowSortIndicators)
|
||
this.ShowSortIndicator(args.ColumnToSort, args.SortOrder);
|
||
|
||
this.PrimarySortColumn = args.ColumnToSort;
|
||
this.PrimarySortOrder = args.SortOrder;
|
||
|
||
if (selection != null && selection.Count > 0)
|
||
this.SelectedObjects = selection;
|
||
this.ResumeSelectionEvents();
|
||
|
||
this.RefreshHotItem();
|
||
|
||
this.OnAfterSorting(new AfterSortingEventArgs(args));
|
||
}
|
||
|
||
/// <summary>
|
||
/// Put a sort indicator next to the text of the sort column
|
||
/// </summary>
|
||
public virtual void ShowSortIndicator() {
|
||
if (this.ShowSortIndicators && this.PrimarySortOrder != SortOrder.None)
|
||
this.ShowSortIndicator(this.PrimarySortColumn, this.PrimarySortOrder);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Put a sort indicator next to the text of the given given column
|
||
/// </summary>
|
||
/// <param name="columnToSort">The column to be marked</param>
|
||
/// <param name="sortOrder">The sort order in effect on that column</param>
|
||
protected virtual void ShowSortIndicator(OLVColumn columnToSort, SortOrder sortOrder) {
|
||
int imageIndex = -1;
|
||
|
||
if (!NativeMethods.HasBuiltinSortIndicators()) {
|
||
// If we can't use builtin image, we have to make and then locate the index of the
|
||
// sort indicator we want to use. SortOrder.None doesn't show an image.
|
||
if (this.SmallImageList == null || !this.SmallImageList.Images.ContainsKey(SORT_INDICATOR_UP_KEY))
|
||
MakeSortIndicatorImages();
|
||
|
||
if (this.SmallImageList != null)
|
||
{
|
||
string key = sortOrder == SortOrder.Ascending ? SORT_INDICATOR_UP_KEY : SORT_INDICATOR_DOWN_KEY;
|
||
imageIndex = this.SmallImageList.Images.IndexOfKey(key);
|
||
}
|
||
}
|
||
|
||
// Set the image for each column
|
||
for (int i = 0; i < this.Columns.Count; i++) {
|
||
if (columnToSort != null && i == columnToSort.Index)
|
||
NativeMethods.SetColumnImage(this, i, sortOrder, imageIndex);
|
||
else
|
||
NativeMethods.SetColumnImage(this, i, SortOrder.None, -1);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// The name of the image used when a column is sorted ascending
|
||
/// </summary>
|
||
/// <remarks>This image is only used on pre-XP systems. System images are used for XP and later</remarks>
|
||
public const string SORT_INDICATOR_UP_KEY = "sort-indicator-up";
|
||
|
||
/// <summary>
|
||
/// The name of the image used when a column is sorted descending
|
||
/// </summary>
|
||
/// <remarks>This image is only used on pre-XP systems. System images are used for XP and later</remarks>
|
||
public const string SORT_INDICATOR_DOWN_KEY = "sort-indicator-down";
|
||
|
||
/// <summary>
|
||
/// If the sort indicator images don't already exist, this method will make and install them
|
||
/// </summary>
|
||
protected virtual void MakeSortIndicatorImages() {
|
||
// Don't mess with the image list in design mode
|
||
if (this.DesignMode)
|
||
return;
|
||
|
||
ImageList il = this.SmallImageList;
|
||
if (il == null) {
|
||
il = new ImageList();
|
||
il.ImageSize = new Size(16, 16);
|
||
il.ColorDepth = ColorDepth.Depth32Bit;
|
||
}
|
||
|
||
// This arrangement of points works well with (16,16) images, and OK with others
|
||
int midX = il.ImageSize.Width / 2;
|
||
int midY = (il.ImageSize.Height / 2) - 1;
|
||
int deltaX = midX - 2;
|
||
int deltaY = deltaX / 2;
|
||
|
||
if (il.Images.IndexOfKey(SORT_INDICATOR_UP_KEY) == -1) {
|
||
Point pt1 = new Point(midX - deltaX, midY + deltaY);
|
||
Point pt2 = new Point(midX, midY - deltaY - 1);
|
||
Point pt3 = new Point(midX + deltaX, midY + deltaY);
|
||
il.Images.Add(SORT_INDICATOR_UP_KEY, this.MakeTriangleBitmap(il.ImageSize, new Point[] { pt1, pt2, pt3 }));
|
||
}
|
||
|
||
if (il.Images.IndexOfKey(SORT_INDICATOR_DOWN_KEY) == -1) {
|
||
Point pt1 = new Point(midX - deltaX, midY - deltaY);
|
||
Point pt2 = new Point(midX, midY + deltaY);
|
||
Point pt3 = new Point(midX + deltaX, midY - deltaY);
|
||
il.Images.Add(SORT_INDICATOR_DOWN_KEY, this.MakeTriangleBitmap(il.ImageSize, new Point[] { pt1, pt2, pt3 }));
|
||
}
|
||
|
||
this.SmallImageList = il;
|
||
}
|
||
|
||
private Bitmap MakeTriangleBitmap(Size sz, Point[] pts) {
|
||
Bitmap bm = new Bitmap(sz.Width, sz.Height);
|
||
Graphics g = Graphics.FromImage(bm);
|
||
g.FillPolygon(new SolidBrush(Color.Gray), pts);
|
||
return bm;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Remove any sorting and revert to the given order of the model objects
|
||
/// </summary>
|
||
public virtual void Unsort() {
|
||
this.ShowGroups = false;
|
||
this.PrimarySortColumn = null;
|
||
this.PrimarySortOrder = SortOrder.None;
|
||
this.BuildList();
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Utilities
|
||
|
||
private static CheckState CalculateToggledCheckState(CheckState currentState, bool isTriState, bool isDisabled)
|
||
{
|
||
if (isDisabled)
|
||
return currentState;
|
||
switch (currentState)
|
||
{
|
||
case CheckState.Checked: return isTriState ? CheckState.Indeterminate : CheckState.Unchecked;
|
||
case CheckState.Indeterminate: return CheckState.Unchecked;
|
||
default: return CheckState.Checked;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Do the actual work of creating the given list of groups
|
||
/// </summary>
|
||
/// <param name="groups"></param>
|
||
protected virtual void CreateGroups(IEnumerable<OLVGroup> groups) {
|
||
this.Groups.Clear();
|
||
// The group must be added before it is given items, otherwise an exception is thrown (is this documented?)
|
||
foreach (OLVGroup group in groups) {
|
||
group.InsertGroupOldStyle(this);
|
||
group.SetItemsOldStyle();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// For some reason, UseItemStyleForSubItems doesn't work for the colors
|
||
/// when owner drawing the list, so we have to specifically give each subitem
|
||
/// the desired colors
|
||
/// </summary>
|
||
/// <param name="olvi">The item whose subitems are to be corrected</param>
|
||
/// <remarks>Cells drawn via BaseRenderer don't need this, but it is needed
|
||
/// when an owner drawn cell uses DrawDefault=true</remarks>
|
||
protected virtual void CorrectSubItemColors(ListViewItem olvi) {
|
||
}
|
||
|
||
/// <summary>
|
||
/// Fill in the given OLVListItem with values of the given row
|
||
/// </summary>
|
||
/// <param name="lvi">the OLVListItem that is to be stuff with values</param>
|
||
/// <param name="rowObject">the model object from which values will be taken</param>
|
||
protected virtual void FillInValues(OLVListItem lvi, object rowObject) {
|
||
if (this.Columns.Count == 0)
|
||
return;
|
||
|
||
OLVListSubItem subItem = this.MakeSubItem(rowObject, this.GetColumn(0));
|
||
lvi.SubItems[0] = subItem;
|
||
lvi.ImageSelector = subItem.ImageSelector;
|
||
|
||
// Give the item the same font/colors as the control
|
||
lvi.Font = this.Font;
|
||
lvi.BackColor = this.BackColor;
|
||
lvi.ForeColor = this.ForeColor;
|
||
|
||
// Should the row be selectable?
|
||
lvi.Enabled = !this.IsDisabled(rowObject);
|
||
|
||
// Only Details and Tile views have subitems
|
||
switch (this.View) {
|
||
case View.Details:
|
||
for (int i = 1; i < this.Columns.Count; i++) {
|
||
lvi.SubItems.Add(this.MakeSubItem(rowObject, this.GetColumn(i)));
|
||
}
|
||
break;
|
||
case View.Tile:
|
||
for (int i = 1; i < this.Columns.Count; i++) {
|
||
OLVColumn column = this.GetColumn(i);
|
||
if (column.IsTileViewColumn)
|
||
lvi.SubItems.Add(this.MakeSubItem(rowObject, column));
|
||
}
|
||
break;
|
||
}
|
||
|
||
// Should the row be selectable?
|
||
if (!lvi.Enabled) {
|
||
lvi.UseItemStyleForSubItems = false;
|
||
ApplyRowStyle(lvi, this.DisabledItemStyle ?? ObjectListView.DefaultDisabledItemStyle);
|
||
}
|
||
|
||
// Set the check state of the row, if we are showing check boxes
|
||
if (this.CheckBoxes) {
|
||
CheckState? state = this.GetCheckState(lvi.RowObject);
|
||
if (state.HasValue)
|
||
lvi.CheckState = state.Value;
|
||
}
|
||
|
||
// Give the RowFormatter a chance to mess with the item
|
||
if (this.RowFormatter != null) {
|
||
this.RowFormatter(lvi);
|
||
}
|
||
}
|
||
|
||
private OLVListSubItem MakeSubItem(object rowObject, OLVColumn column) {
|
||
object cellValue = column.GetValue(rowObject);
|
||
OLVListSubItem subItem = new OLVListSubItem(cellValue,
|
||
column.ValueToString(rowObject,cellValue),
|
||
column.GetImage(rowObject));
|
||
if (this.UseHyperlinks && column.Hyperlink) {
|
||
IsHyperlinkEventArgs args = new IsHyperlinkEventArgs();
|
||
args.ListView = this;
|
||
args.Model = rowObject;
|
||
args.Column = column;
|
||
args.Text = subItem.Text;
|
||
args.Url = subItem.Text;
|
||
args.IsHyperlink = !this.IsDisabled(rowObject);
|
||
this.OnIsHyperlink(args);
|
||
subItem.Url = args.IsHyperlink ? args.Url : null;
|
||
}
|
||
|
||
return subItem;
|
||
}
|
||
|
||
private void ApplyHyperlinkStyle(OLVListItem olvi) {
|
||
|
||
for (int i = 0; i < this.Columns.Count; i++) {
|
||
OLVListSubItem subItem = olvi.GetSubItem(i);
|
||
if (subItem == null)
|
||
continue;
|
||
OLVColumn column = this.GetColumn(i);
|
||
if (column.Hyperlink && !String.IsNullOrEmpty(subItem.Url))
|
||
this.ApplyCellStyle(olvi, i, this.IsUrlVisited(subItem.Url) ? this.HyperlinkStyle.Visited : this.HyperlinkStyle.Normal);
|
||
}
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// Make sure the ListView has the extended style that says to display subitem images.
|
||
/// </summary>
|
||
/// <remarks>This method must be called after any .NET call that update the extended styles
|
||
/// since they seem to erase this setting.</remarks>
|
||
protected virtual void ForceSubItemImagesExStyle() {
|
||
// Virtual lists can't show subitem images natively, so don't turn on this flag
|
||
if (!this.VirtualMode)
|
||
NativeMethods.ForceSubItemImagesExStyle(this);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Convert the given image selector to an index into our image list.
|
||
/// Return -1 if that's not possible
|
||
/// </summary>
|
||
/// <param name="imageSelector"></param>
|
||
/// <returns>Index of the image in the imageList, or -1</returns>
|
||
protected virtual int GetActualImageIndex(Object imageSelector) {
|
||
if (imageSelector == null)
|
||
return -1;
|
||
|
||
if (imageSelector is Int32)
|
||
return (int)imageSelector;
|
||
|
||
String imageSelectorAsString = imageSelector as String;
|
||
if (imageSelectorAsString != null && this.SmallImageList != null)
|
||
return this.SmallImageList.Images.IndexOfKey(imageSelectorAsString);
|
||
|
||
return -1;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Return the tooltip that should be shown when the mouse is hovered over the given column
|
||
/// </summary>
|
||
/// <param name="columnIndex">The column index whose tool tip is to be fetched</param>
|
||
/// <returns>A string or null if no tool tip is to be shown</returns>
|
||
public virtual String GetHeaderToolTip(int columnIndex) {
|
||
OLVColumn column = this.GetColumn(columnIndex);
|
||
if (column == null)
|
||
return null;
|
||
String tooltip = column.ToolTipText;
|
||
if (this.HeaderToolTipGetter != null)
|
||
tooltip = this.HeaderToolTipGetter(column);
|
||
return tooltip;
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD>ڸ<EFBFBD><DAB8><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD>ʱӦ<CAB1><D3A6>ʾ<EFBFBD>Ĺ<EFBFBD><C4B9><EFBFBD><EFBFBD><EFBFBD>ʾ
|
||
/// </summary>
|
||
/// <param name="columnIndex">The column index whose tool tip is to be fetched</param>
|
||
/// <param name="rowIndex">The row index whose tool tip is to be fetched</param>
|
||
/// <returns>A string or null if no tool tip is to be shown</returns>
|
||
public virtual String GetCellToolTip(int columnIndex, int rowIndex) {
|
||
if (this.CellToolTipGetter != null)
|
||
return this.CellToolTipGetter(this.GetColumn(columnIndex), this.GetModelObject(rowIndex));
|
||
|
||
// Show the URL in the tooltip if it's different to the text
|
||
if (columnIndex >= 0) {
|
||
OLVListSubItem subItem = this.GetSubItem(rowIndex, columnIndex);
|
||
if (subItem != null && !String.IsNullOrEmpty(subItem.Url) && subItem.Url != subItem.Text &&
|
||
this.HotCellHitLocation == HitTestLocation.Text)
|
||
return subItem.Url;
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD>ģ<EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD><EFBFBD>OLVListItem
|
||
/// </summary>
|
||
/// <param name="modelObject">The modelObject whose item is to be found</param>
|
||
/// <returns>The OLVListItem that displays the model, or null</returns>
|
||
/// <remarks>This method has O(n) performance.</remarks>
|
||
public virtual OLVListItem ModelToItem(object modelObject) {
|
||
if (modelObject == null)
|
||
return null;
|
||
|
||
foreach (OLVListItem olvi in this.Items) {
|
||
if (olvi.RowObject != null && olvi.RowObject.Equals(modelObject))
|
||
return olvi;
|
||
}
|
||
return null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Do the work required after the items in a listview have been created
|
||
/// </summary>
|
||
protected virtual void PostProcessRows() {
|
||
// If this method is called during a BeginUpdate/EndUpdate pair, changes to the
|
||
// Items collection are cached. Getting the Count flushes that cache.
|
||
#pragma warning disable 168
|
||
// ReSharper disable once UnusedVariable
|
||
int count = this.Items.Count;
|
||
#pragma warning restore 168
|
||
|
||
int i = 0;
|
||
if (this.ShowGroups) {
|
||
foreach (ListViewGroup group in this.Groups) {
|
||
foreach (OLVListItem olvi in group.Items) {
|
||
this.PostProcessOneRow(olvi.Index, i, olvi);
|
||
i++;
|
||
}
|
||
}
|
||
} else {
|
||
foreach (OLVListItem olvi in this.Items) {
|
||
this.PostProcessOneRow(olvi.Index, i, olvi);
|
||
i++;
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Do the work required after one item in a listview have been created
|
||
/// </summary>
|
||
protected virtual void PostProcessOneRow(int rowIndex, int displayIndex, OLVListItem olvi) {
|
||
if (this.UseAlternatingBackColors && this.View == View.Details && olvi.Enabled) {
|
||
olvi.UseItemStyleForSubItems = true;
|
||
olvi.BackColor = displayIndex % 2 == 1 ? this.AlternateRowBackColorOrDefault : this.BackColor;
|
||
}
|
||
if (this.ShowImagesOnSubItems && !this.VirtualMode)
|
||
this.SetSubItemImages(rowIndex, olvi);
|
||
|
||
bool needToTriggerFormatCellEvents = this.TriggerFormatRowEvent(rowIndex, displayIndex, olvi);
|
||
|
||
// We only need cell level events if we are in details view
|
||
if (this.View != View.Details)
|
||
return;
|
||
|
||
// If we're going to have per cell formatting, we need to copy the formatting
|
||
// of the item into each cell, before triggering the cell format events
|
||
if (needToTriggerFormatCellEvents) {
|
||
PropagateFormatFromRowToCells(olvi);
|
||
this.TriggerFormatCellEvents(rowIndex, displayIndex, olvi);
|
||
}
|
||
|
||
// Similarly, if any cell in the row has hyperlinks, we have to copy formatting
|
||
// from the item into each cell before applying the hyperlink style
|
||
if (this.UseHyperlinks && olvi.HasAnyHyperlinks) {
|
||
PropagateFormatFromRowToCells(olvi);
|
||
this.ApplyHyperlinkStyle(olvi);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// <><D7BC><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ɫ
|
||
/// </summary>
|
||
/// <remarks>We cannot rely on lvi.Index in this method.
|
||
/// In a straight list, lvi.Index is the display index, and can be used to determine
|
||
/// whether the row should be colored. But when organised by groups, lvi.Index is not
|
||
/// useable because it still refers to the position in the overall list, not the display order.
|
||
///</remarks>
|
||
[Obsolete("<22><><EFBFBD><EFBFBD>ʹ<EFBFBD>ô˷<C3B4><CBB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>дPostProcessOneRow()<29>Ի<EFBFBD><D4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƵĽ<C6B5><C4BD><EFBFBD>")]
|
||
protected virtual void PrepareAlternateBackColors() {
|
||
}
|
||
|
||
/// <summary>
|
||
/// Setup all subitem images on all rows
|
||
/// </summary>
|
||
[Obsolete("This method is not longer maintained and will be removed", false)]
|
||
protected virtual void SetAllSubItemImages() {
|
||
//if (!this.ShowImagesOnSubItems || this.OwnerDraw)
|
||
// return;
|
||
|
||
//this.ForceSubItemImagesExStyle();
|
||
|
||
//for (int rowIndex = 0; rowIndex < this.GetItemCount(); rowIndex++)
|
||
// SetSubItemImages(rowIndex, this.GetItem(rowIndex));
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><DFBB><EFBFBD><EFBFBD>б<EFBFBD><D0B1>ؼ<EFBFBD><D8BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE>Щͼ<D0A9><CDBC>
|
||
/// </summary>
|
||
/// <param name="rowIndex">the index at which the item occurs</param>
|
||
/// <param name="item">the item whose subitems are to be set</param>
|
||
protected virtual void SetSubItemImages(int rowIndex, OLVListItem item) {
|
||
this.SetSubItemImages(rowIndex, item, false);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Tell the underlying list control which images to show against the subitems
|
||
/// </summary>
|
||
/// <param name="rowIndex">the index at which the item occurs</param>
|
||
/// <param name="item">the item whose subitems are to be set</param>
|
||
/// <param name="shouldClearImages">will existing images be cleared if no new image is provided?</param>
|
||
protected virtual void SetSubItemImages(int rowIndex, OLVListItem item, bool shouldClearImages) {
|
||
if (!this.ShowImagesOnSubItems || this.OwnerDraw)
|
||
return;
|
||
|
||
for (int i = 1; i < item.SubItems.Count; i++) {
|
||
this.SetSubItemImage(rowIndex, i, item.GetSubItem(i), shouldClearImages);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Set the subitem image natively
|
||
/// </summary>
|
||
/// <param name="rowIndex"></param>
|
||
/// <param name="subItemIndex"></param>
|
||
/// <param name="subItem"></param>
|
||
/// <param name="shouldClearImages"></param>
|
||
public virtual void SetSubItemImage(int rowIndex, int subItemIndex, OLVListSubItem subItem, bool shouldClearImages) {
|
||
int imageIndex = this.GetActualImageIndex(subItem.ImageSelector);
|
||
if (shouldClearImages || imageIndex != -1)
|
||
NativeMethods.SetSubItemImage(this, rowIndex, subItemIndex, imageIndex);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Take ownership of the 'objects' collection. This separats our collection from the source.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// This method
|
||
/// separates the 'objects' instance variable from its source, so that any AddObject/RemoveObject
|
||
/// calls will modify our collection and not the original colleciton.
|
||
/// </para>
|
||
/// <para>
|
||
/// This method has the intentional side-effect of converting our list of objects to an ArrayList.
|
||
/// </para>
|
||
/// </remarks>
|
||
protected virtual void TakeOwnershipOfObjects() {
|
||
if (this.isOwnerOfObjects)
|
||
return;
|
||
|
||
this.isOwnerOfObjects = true;
|
||
|
||
this.objects = ObjectListView.EnumerableToArray(this.objects, true);
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF>FormatRow<6F>Ϳ<EFBFBD><CDBF>ܵ<EFBFBD>FormatCell<6C>¼<EFBFBD>
|
||
/// </summary>
|
||
/// <param name="rowIndex"></param>
|
||
/// <param name="displayIndex"></param>
|
||
/// <param name="olvi"></param>
|
||
protected virtual bool TriggerFormatRowEvent(int rowIndex, int displayIndex, OLVListItem olvi) {
|
||
FormatRowEventArgs args = new FormatRowEventArgs();
|
||
args.ListView = this;
|
||
args.RowIndex = rowIndex;
|
||
args.DisplayIndex = displayIndex;
|
||
args.Item = olvi;
|
||
args.UseCellFormatEvents = this.UseCellFormatEvents;
|
||
this.OnFormatRow(args);
|
||
return args.UseCellFormatEvents;
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF>FormatCell<6C>¼<EFBFBD>
|
||
/// </summary>
|
||
/// <param name="rowIndex"></param>
|
||
/// <param name="displayIndex"></param>
|
||
/// <param name="olvi"></param>
|
||
protected virtual void TriggerFormatCellEvents(int rowIndex, int displayIndex, OLVListItem olvi) {
|
||
|
||
PropagateFormatFromRowToCells(olvi);
|
||
|
||
// Fire one event per cell
|
||
FormatCellEventArgs args2 = new FormatCellEventArgs();
|
||
args2.ListView = this;
|
||
args2.RowIndex = rowIndex;
|
||
args2.DisplayIndex = displayIndex;
|
||
args2.Item = olvi;
|
||
for (int i = 0; i < this.Columns.Count; i++) {
|
||
args2.ColumnIndex = i;
|
||
args2.Column = this.GetColumn(i);
|
||
args2.SubItem = olvi.GetSubItem(i);
|
||
this.OnFormatCell(args2);
|
||
}
|
||
}
|
||
|
||
private static void PropagateFormatFromRowToCells(OLVListItem olvi) {
|
||
// If a cell isn't given its own colors, it *should* use the colors of the item.
|
||
// However, there is a bug in the .NET framework where the cell are given
|
||
// the colors of the ListView instead of the colors of the row.
|
||
|
||
// If we've already done this, don't do it again
|
||
if (olvi.UseItemStyleForSubItems == false)
|
||
return;
|
||
|
||
// So we have to explicitly give each cell the fore and back colors and the font that it should have.
|
||
olvi.UseItemStyleForSubItems = false;
|
||
Color backColor = olvi.BackColor;
|
||
Color foreColor = olvi.ForeColor;
|
||
Font font = olvi.Font;
|
||
foreach (OLVListSubItem subitem in olvi.SubItems) {
|
||
subitem.BackColor = backColor;
|
||
subitem.ForeColor = foreColor;
|
||
subitem.Font = font;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Make the list forget everything -- all rows and all columns
|
||
/// </summary>
|
||
/// <remarks>Use <see cref="ClearObjects"/> if you want to remove just the rows.</remarks>
|
||
public virtual void Reset() {
|
||
this.Clear();
|
||
this.AllColumns.Clear();
|
||
this.ClearObjects();
|
||
this.PrimarySortColumn = null;
|
||
this.SecondarySortColumn = null;
|
||
this.ClearDisabledObjects();
|
||
this.ClearPersistentCheckState();
|
||
this.ClearUrlVisited();
|
||
this.ClearHotItem();
|
||
}
|
||
|
||
|
||
#endregion
|
||
|
||
#region ISupportInitialize Members
|
||
|
||
void ISupportInitialize.BeginInit() {
|
||
this.Frozen = true;
|
||
}
|
||
|
||
void ISupportInitialize.EndInit() {
|
||
if (this.RowHeight != -1) {
|
||
this.SmallImageList = this.SmallImageList;
|
||
if (this.CheckBoxes)
|
||
this.InitializeStateImageList();
|
||
}
|
||
|
||
if (this.UseSubItemCheckBoxes || (this.VirtualMode && this.CheckBoxes))
|
||
this.SetupSubItemCheckBoxes();
|
||
|
||
this.Frozen = false;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Image list manipulation
|
||
|
||
/// <summary>
|
||
/// Update our externally visible image list so it holds the same images as our shadow list, but sized correctly
|
||
/// </summary>
|
||
private void SetupBaseImageList() {
|
||
// If a row height hasn't been set, or an image list has been give which is the required size, just assign it
|
||
if (rowHeight == -1 ||
|
||
this.View != View.Details ||
|
||
(this.shadowedImageList != null && this.shadowedImageList.ImageSize.Height == rowHeight))
|
||
this.BaseSmallImageList = this.shadowedImageList;
|
||
else {
|
||
int width = (this.shadowedImageList == null ? 16 : this.shadowedImageList.ImageSize.Width);
|
||
this.BaseSmallImageList = this.MakeResizedImageList(width, rowHeight, shadowedImageList);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Return a copy of the given source image list, where each image has been resized to be height x height in size.
|
||
/// If source is null, an empty image list of the given size is returned
|
||
/// </summary>
|
||
/// <param name="width">Height and width of the new images</param>
|
||
/// <param name="height">Height and width of the new images</param>
|
||
/// <param name="source">Source of the images (can be null)</param>
|
||
/// <returns>A new image list</returns>
|
||
private ImageList MakeResizedImageList(int width, int height, ImageList source) {
|
||
ImageList il = new ImageList();
|
||
il.ImageSize = new Size(width, height);
|
||
|
||
// If there's nothing to copy, just return the new list
|
||
if (source == null)
|
||
return il;
|
||
|
||
il.TransparentColor = source.TransparentColor;
|
||
il.ColorDepth = source.ColorDepth;
|
||
|
||
// Fill the imagelist with resized copies from the source
|
||
for (int i = 0; i < source.Images.Count; i++) {
|
||
Bitmap bm = this.MakeResizedImage(width, height, source.Images[i], source.TransparentColor);
|
||
il.Images.Add(bm);
|
||
}
|
||
|
||
// Give each image the same key it has in the original
|
||
foreach (String key in source.Images.Keys) {
|
||
il.Images.SetKeyName(source.Images.IndexOfKey(key), key);
|
||
}
|
||
|
||
return il;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Return a bitmap of the given height x height, which shows the given image, centred.
|
||
/// </summary>
|
||
/// <param name="width">Height and width of new bitmap</param>
|
||
/// <param name="height">Height and width of new bitmap</param>
|
||
/// <param name="image">Image to be centred</param>
|
||
/// <param name="transparent">The background color</param>
|
||
/// <returns>A new bitmap</returns>
|
||
private Bitmap MakeResizedImage(int width, int height, Image image, Color transparent) {
|
||
Bitmap bm = new Bitmap(width, height);
|
||
Graphics g = Graphics.FromImage(bm);
|
||
g.Clear(transparent);
|
||
int x = Math.Max(0, (bm.Size.Width - image.Size.Width) / 2);
|
||
int y = Math.Max(0, (bm.Size.Height - image.Size.Height) / 2);
|
||
g.DrawImage(image, x, y, image.Size.Width, image.Size.Height);
|
||
return bm;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Initialize the state image list with the required checkbox images
|
||
/// </summary>
|
||
protected virtual void InitializeStateImageList() {
|
||
if (this.DesignMode)
|
||
return;
|
||
|
||
if (!this.CheckBoxes)
|
||
return;
|
||
|
||
if (this.StateImageList == null) {
|
||
this.StateImageList = new ImageList();
|
||
this.StateImageList.ImageSize = new Size(16, this.RowHeight == -1 ? 25 : this.RowHeight);
|
||
this.StateImageList.ColorDepth = ColorDepth.Depth32Bit;
|
||
}
|
||
|
||
if (this.RowHeight != -1 &&
|
||
this.View == View.Details &&
|
||
this.StateImageList.ImageSize.Height != this.RowHeight) {
|
||
this.StateImageList = new ImageList();
|
||
this.StateImageList.ImageSize = new Size(16, this.RowHeight);
|
||
this.StateImageList.ColorDepth = ColorDepth.Depth32Bit;
|
||
}
|
||
|
||
// The internal logic of ListView cycles through the state images when the primary
|
||
// checkbox is clicked. So we have to get exactly the right number of images in the
|
||
// image list.
|
||
if (this.StateImageList.Images.Count == 0)
|
||
this.AddCheckStateBitmap(this.StateImageList, UNCHECKED_KEY, CheckBoxState.UncheckedNormal);
|
||
if (this.StateImageList.Images.Count <= 1)
|
||
this.AddCheckStateBitmap(this.StateImageList, CHECKED_KEY, CheckBoxState.CheckedNormal);
|
||
if (this.TriStateCheckBoxes && this.StateImageList.Images.Count <= 2)
|
||
this.AddCheckStateBitmap(this.StateImageList, INDETERMINATE_KEY, CheckBoxState.MixedNormal);
|
||
else {
|
||
if (this.StateImageList.Images.ContainsKey(INDETERMINATE_KEY))
|
||
this.StateImageList.Images.RemoveByKey(INDETERMINATE_KEY);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// The name of the image used when a check box is checked
|
||
/// </summary>
|
||
public const string CHECKED_KEY = "checkbox-checked";
|
||
|
||
/// <summary>
|
||
/// The name of the image used when a check box is unchecked
|
||
/// </summary>
|
||
public const string UNCHECKED_KEY = "checkbox-unchecked";
|
||
|
||
/// <summary>
|
||
/// The name of the image used when a check box is Indeterminate
|
||
/// </summary>
|
||
public const string INDETERMINATE_KEY = "checkbox-indeterminate";
|
||
|
||
/// <summary>
|
||
/// Setup this control so it can display check boxes on subitems
|
||
/// (or primary checkboxes in virtual mode)
|
||
/// </summary>
|
||
/// <remarks>This gives the ListView a small image list, if it doesn't already have one.</remarks>
|
||
public virtual void SetupSubItemCheckBoxes() {
|
||
this.ShowImagesOnSubItems = true;
|
||
if (this.SmallImageList == null || !this.SmallImageList.Images.ContainsKey(CHECKED_KEY))
|
||
this.InitializeSubItemCheckBoxImages();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Make sure the small image list for this control has checkbox images
|
||
/// (used for sub-item checkboxes).
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// This gives the ListView a small image list, if it doesn't already have one.
|
||
/// </para>
|
||
/// <para>
|
||
/// ObjectListView has to manage checkboxes on subitems separate from the checkboxes on each row.
|
||
/// The underlying ListView knows about the per-row checkboxes, and to make them work, OLV has to
|
||
/// correctly configure the StateImageList. However, the ListView cannot do checkboxes in subitems,
|
||
/// so ObjectListView has to handle them in a differnt fashion. So, per-row checkboxes are controlled
|
||
/// by images in the StateImageList, but per-cell checkboxes are handled by images in the SmallImageList.
|
||
/// </para>
|
||
/// </remarks>
|
||
protected virtual void InitializeSubItemCheckBoxImages() {
|
||
// Don't mess with the image list in design mode
|
||
if (this.DesignMode)
|
||
return;
|
||
|
||
ImageList il = this.SmallImageList;
|
||
if (il == null) {
|
||
il = new ImageList();
|
||
il.ImageSize = new Size(16, 16);
|
||
il.ColorDepth = ColorDepth.Depth32Bit;
|
||
}
|
||
|
||
this.AddCheckStateBitmap(il, CHECKED_KEY, CheckBoxState.CheckedNormal);
|
||
this.AddCheckStateBitmap(il, UNCHECKED_KEY, CheckBoxState.UncheckedNormal);
|
||
this.AddCheckStateBitmap(il, INDETERMINATE_KEY, CheckBoxState.MixedNormal);
|
||
|
||
this.SmallImageList = il;
|
||
}
|
||
|
||
private void AddCheckStateBitmap(ImageList il, string key, CheckBoxState boxState) {
|
||
Bitmap b = new Bitmap(il.ImageSize.Width, il.ImageSize.Height);
|
||
Graphics g = Graphics.FromImage(b);
|
||
g.Clear(il.TransparentColor);
|
||
Point location = new Point(b.Width / 2 - 5, b.Height / 2 - 6);
|
||
CheckBoxRenderer.DrawCheckBox(g, location, boxState);
|
||
il.Images.Add(key, b);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Owner drawing
|
||
|
||
/// <summary>
|
||
/// Owner draw the column header
|
||
/// </summary>
|
||
/// <param name="e"></param>
|
||
protected override void OnDrawColumnHeader(DrawListViewColumnHeaderEventArgs e) {
|
||
e.DrawDefault = true;
|
||
base.OnDrawColumnHeader(e);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Owner draw the item
|
||
/// </summary>
|
||
/// <param name="e"></param>
|
||
protected override void OnDrawItem(DrawListViewItemEventArgs e) {
|
||
if (this.View == View.Details)
|
||
e.DrawDefault = false;
|
||
else {
|
||
if (this.ItemRenderer == null)
|
||
e.DrawDefault = true;
|
||
else {
|
||
Object row = ((OLVListItem)e.Item).RowObject;
|
||
e.DrawDefault = !this.ItemRenderer.RenderItem(e, e.Graphics, e.Bounds, row);
|
||
}
|
||
}
|
||
|
||
if (e.DrawDefault)
|
||
base.OnDrawItem(e);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Owner draw a single subitem
|
||
/// </summary>
|
||
/// <param name="e"></param>
|
||
protected override void OnDrawSubItem(DrawListViewSubItemEventArgs e) {
|
||
//System.Diagnostics.Debug.WriteLine(String.Format("OnDrawSubItem ({0}, {1})", e.ItemIndex, e.ColumnIndex));
|
||
// Don't try to do owner drawing at design time
|
||
if (this.DesignMode) {
|
||
e.DrawDefault = true;
|
||
return;
|
||
}
|
||
|
||
object rowObject = ((OLVListItem)e.Item).RowObject;
|
||
|
||
// Calculate where the subitem should be drawn
|
||
Rectangle r = e.Bounds;
|
||
|
||
// Get the special renderer for this column. If there isn't one, use the default draw mechanism.
|
||
OLVColumn column = this.GetColumn(e.ColumnIndex);
|
||
IRenderer renderer = this.GetCellRenderer(rowObject, column);
|
||
|
||
// Get a graphics context for the renderer to use.
|
||
// But we have more complications. Virtual lists have a nasty habit of drawing column 0
|
||
// whenever there is any mouse move events over a row, and doing it in an un-double-buffered manner,
|
||
// which results in nasty flickers! There are also some unbuffered draw when a mouse is first
|
||
// hovered over column 0 of a normal row. So, to avoid all complications,
|
||
// we always manually double-buffer the drawing.
|
||
// Except with Mono, which doesn't seem to handle double buffering at all :-(
|
||
BufferedGraphics buffer = BufferedGraphicsManager.Current.Allocate(e.Graphics, r);
|
||
Graphics g = buffer.Graphics;
|
||
|
||
g.TextRenderingHint = ObjectListView.TextRenderingHint;
|
||
g.SmoothingMode = ObjectListView.SmoothingMode;
|
||
|
||
// Finally, give the renderer a chance to draw something
|
||
e.DrawDefault = !renderer.RenderSubItem(e, g, r, rowObject);
|
||
|
||
if (!e.DrawDefault)
|
||
buffer.Render();
|
||
buffer.Dispose();
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region OnEvent Handling
|
||
|
||
/// <summary>
|
||
/// We need the click count in the mouse up event, but that is always 1.
|
||
/// So we have to remember the click count from the preceding mouse down event.
|
||
/// </summary>
|
||
/// <param name="e"></param>
|
||
protected override void OnMouseDown(MouseEventArgs e) {
|
||
this.lastMouseDownClickCount = e.Clicks;
|
||
base.OnMouseDown(e);
|
||
}
|
||
private int lastMouseDownClickCount;
|
||
|
||
/// <summary>
|
||
/// When the mouse leaves the control, remove any hot item highlighting
|
||
/// </summary>
|
||
/// <param name="e"></param>
|
||
protected override void OnMouseLeave(EventArgs e) {
|
||
base.OnMouseLeave(e);
|
||
|
||
if (!this.Created)
|
||
return;
|
||
|
||
this.UpdateHotItem(new Point(-1,-1));
|
||
}
|
||
|
||
// We could change the hot item on the mouse hover event, but it looks wrong.
|
||
|
||
//protected override void OnMouseHover(EventArgs e) {
|
||
// System.Diagnostics.Debug.WriteLine(String.Format("OnMouseHover"));
|
||
// base.OnMouseHover(e);
|
||
// this.UpdateHotItem(this.PointToClient(Cursor.Position));
|
||
//}
|
||
|
||
/// <summary>
|
||
/// When the mouse moves, we might need to change the hot item.
|
||
/// </summary>
|
||
/// <param name="e"></param>
|
||
protected override void OnMouseMove(MouseEventArgs e) {
|
||
base.OnMouseMove(e);
|
||
|
||
if (this.Created)
|
||
HandleMouseMove(e.Location);
|
||
}
|
||
|
||
internal void HandleMouseMove(Point pt) {
|
||
|
||
//System.Diagnostics.Debug.WriteLine(String.Format("HandleMouseMove: {0}", pt));
|
||
|
||
CellOverEventArgs args = new CellOverEventArgs();
|
||
this.BuildCellEvent(args, pt);
|
||
this.OnCellOver(args);
|
||
this.MouseMoveHitTest = args.HitTest;
|
||
|
||
if (!args.Handled)
|
||
this.UpdateHotItem(args.HitTest);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Check to see if we need to start editing a cell
|
||
/// </summary>
|
||
/// <param name="e"></param>
|
||
protected override void OnMouseUp(MouseEventArgs e) {
|
||
|
||
//System.Diagnostics.Debug.WriteLine(String.Format("OnMouseUp"));
|
||
|
||
base.OnMouseUp(e);
|
||
|
||
if (!this.Created)
|
||
return;
|
||
|
||
if (e.Button == MouseButtons.Right) {
|
||
this.OnRightMouseUp(e);
|
||
return;
|
||
}
|
||
|
||
// What event should we listen for to start cell editing?
|
||
// ------------------------------------------------------
|
||
//
|
||
// We can't use OnMouseClick, OnMouseDoubleClick, OnClick, or OnDoubleClick
|
||
// since they are not triggered for clicks on subitems without Full Row Select.
|
||
//
|
||
// We could use OnMouseDown, but selecting rows is done in OnMouseUp. This means
|
||
// that if we start the editing during OnMouseDown, the editor will automatically
|
||
// lose focus when mouse up happens.
|
||
//
|
||
|
||
// Tell the world about a cell click. If someone handles it, don't do anything else
|
||
CellClickEventArgs args = new CellClickEventArgs();
|
||
this.BuildCellEvent(args, e.Location);
|
||
args.ClickCount = this.lastMouseDownClickCount;
|
||
this.OnCellClick(args);
|
||
if (args.Handled)
|
||
return;
|
||
|
||
// Did the user click a hyperlink?
|
||
if (this.UseHyperlinks &&
|
||
args.HitTest.HitTestLocation == HitTestLocation.Text &&
|
||
args.SubItem != null &&
|
||
!String.IsNullOrEmpty(args.SubItem.Url)) {
|
||
// We have to delay the running of this process otherwise we can generate
|
||
// a series of MouseUp events (don't ask me why)
|
||
this.BeginInvoke((MethodInvoker)delegate { this.ProcessHyperlinkClicked(args); });
|
||
}
|
||
|
||
// No one handled it so check to see if we should start editing.
|
||
if (!this.ShouldStartCellEdit(e))
|
||
return;
|
||
|
||
// We only start the edit if the user clicked on the image or text.
|
||
if (args.HitTest.HitTestLocation == HitTestLocation.Nothing)
|
||
return;
|
||
|
||
// We don't edit the primary column by single clicks -- only subitems.
|
||
if (this.CellEditActivation == CellEditActivateMode.SingleClick && args.ColumnIndex <= 0)
|
||
return;
|
||
|
||
// Don't start a cell edit operation when the user clicks on the background of a checkbox column -- it just looks wrong.
|
||
// If the user clicks on the actual checkbox, changing the checkbox state is handled elsewhere.
|
||
if (args.Column != null && args.Column.CheckBoxes)
|
||
return;
|
||
|
||
this.EditSubItem(args.Item, args.ColumnIndex);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Tell the world that a hyperlink was clicked and if the event isn't handled,
|
||
/// do the default processing.
|
||
/// </summary>
|
||
/// <param name="e"></param>
|
||
protected virtual void ProcessHyperlinkClicked(CellClickEventArgs e) {
|
||
HyperlinkClickedEventArgs args = new HyperlinkClickedEventArgs();
|
||
args.HitTest = e.HitTest;
|
||
args.ListView = this;
|
||
args.Location = new Point(-1, -1);
|
||
args.Item = e.Item;
|
||
args.SubItem = e.SubItem;
|
||
args.Model = e.Model;
|
||
args.ColumnIndex = e.ColumnIndex;
|
||
args.Column = e.Column;
|
||
args.RowIndex = e.RowIndex;
|
||
args.ModifierKeys = Control.ModifierKeys;
|
||
args.Url = e.SubItem.Url;
|
||
this.OnHyperlinkClicked(args);
|
||
if (!args.Handled) {
|
||
this.StandardHyperlinkClickedProcessing(args);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Do the default processing for a hyperlink clicked event, which
|
||
/// is to try and open the url.
|
||
/// </summary>
|
||
/// <param name="args"></param>
|
||
protected virtual void StandardHyperlinkClickedProcessing(HyperlinkClickedEventArgs args) {
|
||
Cursor originalCursor = this.Cursor;
|
||
try {
|
||
this.Cursor = Cursors.WaitCursor;
|
||
System.Diagnostics.Process.Start(args.Url);
|
||
} catch (Win32Exception) {
|
||
System.Media.SystemSounds.Beep.Play();
|
||
// ignore it
|
||
} finally {
|
||
this.Cursor = originalCursor;
|
||
}
|
||
this.MarkUrlVisited(args.Url);
|
||
this.RefreshHotItem();
|
||
}
|
||
|
||
/// <summary>
|
||
/// The user right clicked on the control
|
||
/// </summary>
|
||
/// <param name="e"></param>
|
||
protected virtual void OnRightMouseUp(MouseEventArgs e) {
|
||
CellRightClickEventArgs args = new CellRightClickEventArgs();
|
||
this.BuildCellEvent(args, e.Location);
|
||
this.OnCellRightClick(args);
|
||
if (!args.Handled) {
|
||
if (args.MenuStrip != null) {
|
||
args.MenuStrip.Show(this, args.Location);
|
||
}
|
||
}
|
||
}
|
||
|
||
internal void BuildCellEvent(CellEventArgs args, Point location) {
|
||
BuildCellEvent(args, location, this.OlvHitTest(location.X, location.Y));
|
||
}
|
||
|
||
internal void BuildCellEvent(CellEventArgs args, Point location, OlvListViewHitTestInfo hitTest) {
|
||
args.HitTest = hitTest;
|
||
args.ListView = this;
|
||
args.Location = location;
|
||
args.Item = hitTest.Item;
|
||
args.SubItem = hitTest.SubItem;
|
||
args.Model = hitTest.RowObject;
|
||
args.ColumnIndex = hitTest.ColumnIndex;
|
||
args.Column = hitTest.Column;
|
||
if (hitTest.Item != null)
|
||
args.RowIndex = hitTest.Item.Index;
|
||
args.ModifierKeys = Control.ModifierKeys;
|
||
|
||
// In non-details view, we want any hit on an item to act as if it was a hit
|
||
// on column 0 -- which, effectively, it was.
|
||
if (args.Item != null && args.ListView.View != View.Details) {
|
||
args.ColumnIndex = 0;
|
||
args.Column = args.ListView.GetColumn(0);
|
||
args.SubItem = args.Item.GetSubItem(0);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// This method is called every time a row is selected or deselected. This can be
|
||
/// a pain if the user shift-clicks 100 rows. We override this method so we can
|
||
/// trigger one event for any number of select/deselects that come from one user action
|
||
/// </summary>
|
||
/// <param name="e"></param>
|
||
protected override void OnSelectedIndexChanged(EventArgs e) {
|
||
if (this.SelectionEventsSuspended)
|
||
return;
|
||
|
||
base.OnSelectedIndexChanged(e);
|
||
|
||
// If we haven't already scheduled an event, schedule it to be triggered
|
||
// By using idle time, we will wait until all select events for the same
|
||
// user action have finished before triggering the event.
|
||
if (!this.hasIdleHandler) {
|
||
this.hasIdleHandler = true;
|
||
this.RunWhenIdle(HandleApplicationIdle);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Called when the handle of the underlying control is created
|
||
/// </summary>
|
||
/// <param name="e"></param>
|
||
protected override void OnHandleCreated(EventArgs e) {
|
||
//Debug.WriteLine("OnHandleCreated");
|
||
base.OnHandleCreated(e);
|
||
|
||
this.Invoke((MethodInvoker)this.OnControlCreated);
|
||
}
|
||
|
||
/// <summary>
|
||
/// This method is called after the control has been fully created.
|
||
/// </summary>
|
||
protected virtual void OnControlCreated() {
|
||
|
||
//Debug.WriteLine("OnControlCreated");
|
||
|
||
// Force the header control to be created when the listview handle is
|
||
HeaderControl hc = this.HeaderControl;
|
||
hc.WordWrap = this.HeaderWordWrap;
|
||
|
||
// Make sure any overlays that are set on the hot item style take effect
|
||
this.HotItemStyle = this.HotItemStyle;
|
||
|
||
// Arrange for any group images to be installed after the control is created
|
||
NativeMethods.SetGroupImageList(this, this.GroupImageList);
|
||
|
||
this.UseExplorerTheme = this.UseExplorerTheme;
|
||
|
||
this.RememberDisplayIndicies();
|
||
this.SetGroupSpacing();
|
||
|
||
if (this.VirtualMode)
|
||
this.ApplyExtendedStyles();
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Cell editing
|
||
|
||
/// <summary>
|
||
/// Should we start editing the cell in response to the given mouse button event?
|
||
/// </summary>
|
||
/// <param name="e"></param>
|
||
/// <returns></returns>
|
||
protected virtual bool ShouldStartCellEdit(MouseEventArgs e) {
|
||
if (this.IsCellEditing)
|
||
return false;
|
||
|
||
if (e.Button != MouseButtons.Left && e.Button != MouseButtons.Right)
|
||
return false;
|
||
|
||
if ((Control.ModifierKeys & (Keys.Shift | Keys.Control | Keys.Alt)) != 0)
|
||
return false;
|
||
|
||
if (this.lastMouseDownClickCount == 1 && (
|
||
this.CellEditActivation == CellEditActivateMode.SingleClick ||
|
||
this.CellEditActivation == CellEditActivateMode.SingleClickAlways))
|
||
return true;
|
||
|
||
return (this.lastMouseDownClickCount == 2 && this.CellEditActivation == CellEditActivateMode.DoubleClick);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handle a key press on this control. We specifically look for F2 which edits the primary column,
|
||
/// or a Tab character during an edit operation, which tries to start editing on the next (or previous) cell.
|
||
/// </summary>
|
||
/// <param name="keyData"></param>
|
||
/// <returns></returns>
|
||
protected override bool ProcessDialogKey(Keys keyData) {
|
||
|
||
if (this.IsCellEditing)
|
||
return this.CellEditKeyEngine.HandleKey(this, keyData);
|
||
|
||
// Treat F2 as a request to edit the primary column
|
||
if (keyData == Keys.F2) {
|
||
this.EditSubItem((OLVListItem)this.FocusedItem, 0);
|
||
return base.ProcessDialogKey(keyData);
|
||
}
|
||
|
||
// Treat Ctrl-C as Copy To Clipboard.
|
||
if (this.CopySelectionOnControlC && keyData == (Keys.C | Keys.Control)) {
|
||
this.CopySelectionToClipboard();
|
||
return true;
|
||
}
|
||
|
||
// Treat Ctrl-A as Select All.
|
||
if (this.SelectAllOnControlA && keyData == (Keys.A | Keys.Control)) {
|
||
this.SelectAll();
|
||
return true;
|
||
}
|
||
|
||
return base.ProcessDialogKey(keyData);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Start an editing operation on the first editable column of the given model.
|
||
/// </summary>
|
||
/// <param name="rowModel"></param>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// If the model doesn't exist, or there are no editable columns, this method
|
||
/// will do nothing.</para>
|
||
/// <para>
|
||
/// This will start an edit operation regardless of CellActivationMode.
|
||
/// </para>
|
||
/// </remarks>
|
||
public virtual void EditModel(object rowModel) {
|
||
OLVListItem olvItem = this.ModelToItem(rowModel);
|
||
if (olvItem == null)
|
||
return;
|
||
|
||
for (int i = 0; i < olvItem.SubItems.Count; i++) {
|
||
if (this.GetColumn(i).IsEditable) {
|
||
this.StartCellEdit(olvItem, i);
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Begin an edit operation on the given cell.
|
||
/// </summary>
|
||
/// <remarks>This performs various sanity checks and passes off the real work to StartCellEdit().</remarks>
|
||
/// <param name="item">The row to be edited</param>
|
||
/// <param name="subItemIndex">The index of the cell to be edited</param>
|
||
public virtual void EditSubItem(OLVListItem item, int subItemIndex) {
|
||
if (item == null)
|
||
return;
|
||
|
||
if (subItemIndex < 0 && subItemIndex >= item.SubItems.Count)
|
||
return;
|
||
|
||
if (this.CellEditActivation == CellEditActivateMode.None)
|
||
return;
|
||
|
||
if (!this.GetColumn(subItemIndex).IsEditable)
|
||
return;
|
||
|
||
if (!item.Enabled)
|
||
return;
|
||
|
||
this.StartCellEdit(item, subItemIndex);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Really start an edit operation on a given cell. The parameters are assumed to be sane.
|
||
/// </summary>
|
||
/// <param name="item">The row to be edited</param>
|
||
/// <param name="subItemIndex">The index of the cell to be edited</param>
|
||
public virtual void StartCellEdit(OLVListItem item, int subItemIndex) {
|
||
OLVColumn column = this.GetColumn(subItemIndex);
|
||
Control c = this.GetCellEditor(item, subItemIndex);
|
||
Rectangle cellBounds = this.CalculateCellBounds(item, subItemIndex);
|
||
//c.Bounds = this.CalculateCellEditorBounds(item, subItemIndex, c.PreferredSize);
|
||
c.Bounds = cellBounds;
|
||
// Try to align the control as the column is aligned. Not all controls support this property
|
||
Munger.PutProperty(c, "TextAlign", column.TextAlign);
|
||
|
||
// Give the control the value from the model
|
||
this.SetControlValue(c, column.GetValue(item.RowObject), column.GetStringValue(item.RowObject));
|
||
|
||
// Give the outside world the chance to munge with the process
|
||
this.CellEditEventArgs = new CellEditEventArgs(column, c, cellBounds, item, subItemIndex);
|
||
this.OnCellEditStarting(this.CellEditEventArgs);
|
||
if (this.CellEditEventArgs.Cancel)
|
||
return;
|
||
|
||
// The event handler may have completely changed the control, so we need to remember it
|
||
this.cellEditor = this.CellEditEventArgs.Control;
|
||
|
||
this.Invalidate();
|
||
this.Controls.Add(this.cellEditor);
|
||
this.ConfigureControl();
|
||
this.PauseAnimations(true);
|
||
}
|
||
private Control cellEditor;
|
||
internal CellEditEventArgs CellEditEventArgs;
|
||
|
||
/// <summary>
|
||
/// Calculate the bounds of the edit control for the given item/column
|
||
/// </summary>
|
||
/// <param name="item"></param>
|
||
/// <param name="subItemIndex"></param>
|
||
/// <param name="preferredSize"> </param>
|
||
/// <returns></returns>
|
||
public Rectangle CalculateCellEditorBounds(OLVListItem item, int subItemIndex, Size preferredSize) {
|
||
Rectangle r = CalculateCellBounds(item, subItemIndex);
|
||
|
||
// Calculate the width of the cell's current contents
|
||
return this.OwnerDraw
|
||
? CalculateCellEditorBoundsOwnerDrawn(item, subItemIndex, r, preferredSize)
|
||
: CalculateCellEditorBoundsStandard(item, subItemIndex, r, preferredSize);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Calculate the bounds of the edit control for the given item/column, when the listview
|
||
/// is being owner drawn.
|
||
/// </summary>
|
||
/// <param name="item"></param>
|
||
/// <param name="subItemIndex"></param>
|
||
/// <param name="r"></param>
|
||
/// <param name="preferredSize"> </param>
|
||
/// <returns>A rectangle that is the bounds of the cell editor</returns>
|
||
protected Rectangle CalculateCellEditorBoundsOwnerDrawn(OLVListItem item, int subItemIndex, Rectangle r, Size preferredSize) {
|
||
IRenderer renderer = this.View == View.Details
|
||
? this.GetCellRenderer(item.RowObject, this.GetColumn(subItemIndex))
|
||
: this.ItemRenderer;
|
||
|
||
if (renderer == null)
|
||
return r;
|
||
|
||
using (Graphics g = this.CreateGraphics()) {
|
||
return renderer.GetEditRectangle(g, r, item, subItemIndex, preferredSize);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Calculate the bounds of the edit control for the given item/column, when the listview
|
||
/// is not being owner drawn.
|
||
/// </summary>
|
||
/// <param name="item"></param>
|
||
/// <param name="subItemIndex"></param>
|
||
/// <param name="cellBounds"></param>
|
||
/// <param name="preferredSize"> </param>
|
||
/// <returns>A rectangle that is the bounds of the cell editor</returns>
|
||
protected Rectangle CalculateCellEditorBoundsStandard(OLVListItem item, int subItemIndex, Rectangle cellBounds, Size preferredSize) {
|
||
if (this.View == View.Tile)
|
||
return cellBounds;
|
||
|
||
// Center the editor vertically
|
||
if (cellBounds.Height != preferredSize.Height)
|
||
cellBounds.Y += (cellBounds.Height - preferredSize.Height) / 2;
|
||
|
||
// Only Details view needs more processing
|
||
if (this.View != View.Details)
|
||
return cellBounds;
|
||
|
||
// Allow for image (if there is one).
|
||
int offset = 0;
|
||
object imageSelector = null;
|
||
if (subItemIndex == 0)
|
||
imageSelector = item.ImageSelector;
|
||
else {
|
||
// We only check for subitem images if we are owner drawn or showing subitem images
|
||
if (this.OwnerDraw || this.ShowImagesOnSubItems)
|
||
imageSelector = item.GetSubItem(subItemIndex).ImageSelector;
|
||
}
|
||
if (this.GetActualImageIndex(imageSelector) != -1) {
|
||
offset += this.SmallImageSize.Width + 2;
|
||
}
|
||
|
||
// Allow for checkbox
|
||
if (this.CheckBoxes && this.StateImageList != null && subItemIndex == 0) {
|
||
offset += this.StateImageList.ImageSize.Width + 2;
|
||
}
|
||
|
||
// Allow for indent (first column only)
|
||
if (subItemIndex == 0 && item.IndentCount > 0) {
|
||
offset += (this.SmallImageSize.Width * item.IndentCount);
|
||
}
|
||
|
||
// Do the adjustment
|
||
if (offset > 0) {
|
||
cellBounds.X += offset;
|
||
cellBounds.Width -= offset;
|
||
}
|
||
|
||
return cellBounds;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Try to give the given value to the provided control. Fall back to assigning a string
|
||
/// if the value assignment fails.
|
||
/// </summary>
|
||
/// <param name="control">A control</param>
|
||
/// <param name="value">The value to be given to the control</param>
|
||
/// <param name="stringValue">The string to be given if the value doesn't work</param>
|
||
protected virtual void SetControlValue(Control control, Object value, String stringValue) {
|
||
// Handle combobox explicitly
|
||
ComboBox cb = control as ComboBox;
|
||
if (cb != null) {
|
||
if (cb.Created)
|
||
cb.SelectedValue = value;
|
||
else
|
||
this.BeginInvoke(new MethodInvoker(delegate {
|
||
cb.SelectedValue = value;
|
||
}));
|
||
return;
|
||
}
|
||
|
||
if (Munger.PutProperty(control, "Value", value))
|
||
return;
|
||
|
||
// There wasn't a Value property, or we couldn't set it, so set the text instead
|
||
try
|
||
{
|
||
String valueAsString = value as String;
|
||
control.Text = valueAsString ?? stringValue;
|
||
}
|
||
catch (ArgumentOutOfRangeException) {
|
||
// The value couldn't be set via the Text property.
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Setup the given control to be a cell editor
|
||
/// </summary>
|
||
protected virtual void ConfigureControl() {
|
||
this.cellEditor.Validating += new CancelEventHandler(CellEditor_Validating);
|
||
this.cellEditor.Select();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Return the value that the given control is showing
|
||
/// </summary>
|
||
/// <param name="control"></param>
|
||
/// <returns></returns>
|
||
protected virtual Object GetControlValue(Control control) {
|
||
if (control == null)
|
||
return null;
|
||
|
||
TextBox box = control as TextBox;
|
||
if (box != null)
|
||
return box.Text;
|
||
|
||
ComboBox comboBox = control as ComboBox;
|
||
if (comboBox != null)
|
||
return comboBox.SelectedValue;
|
||
|
||
CheckBox checkBox = control as CheckBox;
|
||
if (checkBox != null)
|
||
return checkBox.Checked;
|
||
|
||
try {
|
||
return control.GetType().InvokeMember("Value", BindingFlags.GetProperty, null, control, null);
|
||
} catch (MissingMethodException) { // Microsoft throws this
|
||
return control.Text;
|
||
} catch (MissingFieldException) { // Mono throws this
|
||
return control.Text;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Called when the cell editor could be about to lose focus. Time to commit the change
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
protected virtual void CellEditor_Validating(object sender, CancelEventArgs e) {
|
||
this.CellEditEventArgs.Cancel = false;
|
||
this.CellEditEventArgs.NewValue = this.GetControlValue(this.cellEditor);
|
||
this.OnCellEditorValidating(this.CellEditEventArgs);
|
||
|
||
if (this.CellEditEventArgs.Cancel) {
|
||
this.CellEditEventArgs.Control.Select();
|
||
e.Cancel = true;
|
||
} else
|
||
FinishCellEdit();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Return the bounds of the given cell
|
||
/// </summary>
|
||
/// <param name="item">The row to be edited</param>
|
||
/// <param name="subItemIndex">The index of the cell to be edited</param>
|
||
/// <returns>A Rectangle</returns>
|
||
public virtual Rectangle CalculateCellBounds(OLVListItem item, int subItemIndex) {
|
||
|
||
// It seems on Win7, GetSubItemBounds() does not have the same problems with
|
||
// column 0 that it did previously.
|
||
|
||
// TODO - Check on XP
|
||
|
||
if (this.View != View.Details)
|
||
return this.GetItemRect(item.Index, ItemBoundsPortion.Label);
|
||
|
||
Rectangle r = item.GetSubItemBounds(subItemIndex);
|
||
r.Width -= 1;
|
||
r.Height -= 1;
|
||
return r;
|
||
|
||
// We use ItemBoundsPortion.Label rather than ItemBoundsPortion.Item
|
||
// since Label extends to the right edge of the cell, whereas Item gives just the
|
||
// current text width.
|
||
//return this.CalculateCellBounds(item, subItemIndex, ItemBoundsPortion.Label);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Return the bounds of the given cell only until the edge of the current text
|
||
/// </summary>
|
||
/// <param name="item">The row to be edited</param>
|
||
/// <param name="subItemIndex">The index of the cell to be edited</param>
|
||
/// <returns>A Rectangle</returns>
|
||
public virtual Rectangle CalculateCellTextBounds(OLVListItem item, int subItemIndex) {
|
||
return this.CalculateCellBounds(item, subItemIndex, ItemBoundsPortion.ItemOnly);
|
||
}
|
||
|
||
private Rectangle CalculateCellBounds(OLVListItem item, int subItemIndex, ItemBoundsPortion portion) {
|
||
// SubItem.Bounds works for every subitem, except the first.
|
||
if (subItemIndex > 0)
|
||
return item.GetSubItemBounds(subItemIndex);
|
||
|
||
// For non detail views, we just use the requested portion
|
||
Rectangle r = this.GetItemRect(item.Index, portion);
|
||
if (r.Y < -10000000 || r.Y > 10000000) {
|
||
r.Y = item.Bounds.Y;
|
||
}
|
||
if (this.View != View.Details)
|
||
return r;
|
||
|
||
// Finding the bounds of cell 0 should not be a difficult task, but it is. Problems:
|
||
// 1) item.SubItem[0].Bounds is always the full bounds of the entire row, not just cell 0.
|
||
// 2) if column 0 has been dragged to some other position, the bounds always has a left edge of 0.
|
||
|
||
// We avoid both these problems by using the position of sides the column header to calculate
|
||
// the sides of the cell
|
||
Point sides = NativeMethods.GetScrolledColumnSides(this, 0);
|
||
r.X = sides.X + 4;
|
||
r.Width = sides.Y - sides.X - 5;
|
||
|
||
return r;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Calculate the visible bounds of the given column. The column's bottom edge is
|
||
/// either the bottom of the last row or the bottom of the control.
|
||
/// </summary>
|
||
/// <param name="bounds">The bounds of the control itself</param>
|
||
/// <param name="column">The column</param>
|
||
/// <returns>A Rectangle</returns>
|
||
/// <remarks>This returns an empty rectnage if the control isn't in Details mode,
|
||
/// OR has doesn't have any rows, OR if the given column is hidden.</remarks>
|
||
public virtual Rectangle CalculateColumnVisibleBounds(Rectangle bounds, OLVColumn column)
|
||
{
|
||
// Sanity checks
|
||
if (column == null ||
|
||
this.View != System.Windows.Forms.View.Details ||
|
||
this.GetItemCount() == 0 ||
|
||
!column.IsVisible)
|
||
return Rectangle.Empty;
|
||
|
||
Point sides = NativeMethods.GetScrolledColumnSides(this, column.Index);
|
||
if (sides.X == -1)
|
||
return Rectangle.Empty;
|
||
|
||
Rectangle columnBounds = new Rectangle(sides.X, bounds.Top, sides.Y - sides.X, bounds.Bottom);
|
||
|
||
// Find the bottom of the last item. The column only extends to there.
|
||
OLVListItem lastItem = this.GetLastItemInDisplayOrder();
|
||
if (lastItem != null)
|
||
{
|
||
Rectangle lastItemBounds = lastItem.Bounds;
|
||
if (!lastItemBounds.IsEmpty && lastItemBounds.Bottom < columnBounds.Bottom)
|
||
columnBounds.Height = lastItemBounds.Bottom - columnBounds.Top;
|
||
}
|
||
|
||
return columnBounds;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Return a control that can be used to edit the value of the given cell.
|
||
/// </summary>
|
||
/// <param name="item">The row to be edited</param>
|
||
/// <param name="subItemIndex">The index of the cell to be edited</param>
|
||
/// <returns>A Control to edit the given cell</returns>
|
||
protected virtual Control GetCellEditor(OLVListItem item, int subItemIndex) {
|
||
OLVColumn column = this.GetColumn(subItemIndex);
|
||
Object value = column.GetValue(item.RowObject) ?? this.GetFirstNonNullValue(column);
|
||
|
||
// TODO: What do we do if value is still null here?
|
||
|
||
// Ask the registry for an instance of the appropriate editor.
|
||
// Use a default editor if the registry can't create one for us.
|
||
Control editor = ObjectListView.EditorRegistry.GetEditor(item.RowObject, column, value) ??
|
||
this.MakeDefaultCellEditor(column);
|
||
|
||
return editor;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Get the first non-null value of the given column.
|
||
/// At most 1000 rows will be considered.
|
||
/// </summary>
|
||
/// <param name="column"></param>
|
||
/// <returns>The first non-null value, or null if no non-null values were found</returns>
|
||
internal object GetFirstNonNullValue(OLVColumn column) {
|
||
for (int i = 0; i < Math.Min(this.GetItemCount(), 1000); i++) {
|
||
object value = column.GetValue(this.GetModelObject(i));
|
||
if (value != null)
|
||
return value;
|
||
}
|
||
return null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Return a TextBox that can be used as a default cell editor.
|
||
/// </summary>
|
||
/// <param name="column">What column does the cell belong to?</param>
|
||
/// <returns></returns>
|
||
protected virtual Control MakeDefaultCellEditor(OLVColumn column) {
|
||
TextBox tb = new TextBox();
|
||
if (column.AutoCompleteEditor)
|
||
this.ConfigureAutoComplete(tb, column);
|
||
return tb;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Configure the given text box to autocomplete unique values
|
||
/// from the given column. At most 1000 rows will be considered.
|
||
/// </summary>
|
||
/// <param name="tb">The textbox to configure</param>
|
||
/// <param name="column">The column used to calculate values</param>
|
||
public void ConfigureAutoComplete(TextBox tb, OLVColumn column) {
|
||
this.ConfigureAutoComplete(tb, column, 1000);
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// Configure the given text box to autocomplete unique values
|
||
/// from the given column. At most 1000 rows will be considered.
|
||
/// </summary>
|
||
/// <param name="tb">The textbox to configure</param>
|
||
/// <param name="column">The column used to calculate values</param>
|
||
/// <param name="maxRows">Consider only this many rows</param>
|
||
public void ConfigureAutoComplete(TextBox tb, OLVColumn column, int maxRows) {
|
||
// Don't consider more rows than we actually have
|
||
maxRows = Math.Min(this.GetItemCount(), maxRows);
|
||
|
||
// Reset any existing autocomplete
|
||
tb.AutoCompleteCustomSource.Clear();
|
||
|
||
// CONSIDER: Should we use ClusteringStrategy here?
|
||
|
||
// Build a list of unique values, to be used as autocomplete on the editor
|
||
Dictionary<string, bool> alreadySeen = new Dictionary<string, bool>();
|
||
List<string> values = new List<string>();
|
||
for (int i = 0; i < maxRows; i++) {
|
||
string valueAsString = column.GetStringValue(this.GetModelObject(i));
|
||
if (!String.IsNullOrEmpty(valueAsString) && !alreadySeen.ContainsKey(valueAsString)) {
|
||
values.Add(valueAsString);
|
||
alreadySeen[valueAsString] = true;
|
||
}
|
||
}
|
||
|
||
tb.AutoCompleteCustomSource.AddRange(values.ToArray());
|
||
tb.AutoCompleteSource = AutoCompleteSource.CustomSource;
|
||
tb.AutoCompleteMode = column.AutoCompleteEditorMode;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Stop editing a cell and throw away any changes.
|
||
/// </summary>
|
||
public virtual void CancelCellEdit() {
|
||
if (!this.IsCellEditing)
|
||
return;
|
||
|
||
// Let the world know that the user has cancelled the edit operation
|
||
this.CellEditEventArgs.Cancel = true;
|
||
this.CellEditEventArgs.NewValue = this.GetControlValue(this.cellEditor);
|
||
this.OnCellEditFinishing(this.CellEditEventArgs);
|
||
|
||
// Now cleanup the editing process
|
||
this.CleanupCellEdit(false, this.CellEditEventArgs.AutoDispose);
|
||
}
|
||
|
||
/// <summary>
|
||
/// If a cell edit is in progress, finish the edit.
|
||
/// </summary>
|
||
/// <returns>Returns false if the finishing process was cancelled
|
||
/// (i.e. the cell editor is still on screen)</returns>
|
||
/// <remarks>This method does not guarantee that the editing will finish. The validation
|
||
/// process can cause the finishing to be aborted. Developers should check the return value
|
||
/// or use IsCellEditing property after calling this method to see if the user is still
|
||
/// editing a cell.</remarks>
|
||
public virtual bool PossibleFinishCellEditing() {
|
||
return this.PossibleFinishCellEditing(false);
|
||
}
|
||
|
||
/// <summary>
|
||
/// If a cell edit is in progress, finish the edit.
|
||
/// </summary>
|
||
/// <returns>Returns false if the finishing process was cancelled
|
||
/// (i.e. the cell editor is still on screen)</returns>
|
||
/// <remarks>This method does not guarantee that the editing will finish. The validation
|
||
/// process can cause the finishing to be aborted. Developers should check the return value
|
||
/// or use IsCellEditing property after calling this method to see if the user is still
|
||
/// editing a cell.</remarks>
|
||
/// <param name="expectingCellEdit">True if it is likely that another cell is going to be
|
||
/// edited immediately after this cell finishes editing</param>
|
||
public virtual bool PossibleFinishCellEditing(bool expectingCellEdit) {
|
||
if (!this.IsCellEditing)
|
||
return true;
|
||
|
||
this.CellEditEventArgs.Cancel = false;
|
||
this.CellEditEventArgs.NewValue = this.GetControlValue(this.cellEditor);
|
||
this.OnCellEditorValidating(this.CellEditEventArgs);
|
||
|
||
if (this.CellEditEventArgs.Cancel)
|
||
return false;
|
||
|
||
this.FinishCellEdit(expectingCellEdit);
|
||
|
||
return true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Finish the cell edit operation, writing changed data back to the model object
|
||
/// </summary>
|
||
/// <remarks>This method does not trigger a Validating event, so it always finishes
|
||
/// the cell edit.</remarks>
|
||
public virtual void FinishCellEdit() {
|
||
this.FinishCellEdit(false);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Finish the cell edit operation, writing changed data back to the model object
|
||
/// </summary>
|
||
/// <remarks>This method does not trigger a Validating event, so it always finishes
|
||
/// the cell edit.</remarks>
|
||
/// <param name="expectingCellEdit">True if it is likely that another cell is going to be
|
||
/// edited immediately after this cell finishes editing</param>
|
||
public virtual void FinishCellEdit(bool expectingCellEdit) {
|
||
if (!this.IsCellEditing)
|
||
return;
|
||
|
||
this.CellEditEventArgs.Cancel = false;
|
||
this.CellEditEventArgs.NewValue = this.GetControlValue(this.cellEditor);
|
||
this.OnCellEditFinishing(this.CellEditEventArgs);
|
||
|
||
// If someone doesn't cancel the editing process, write the value back into the model
|
||
if (!this.CellEditEventArgs.Cancel) {
|
||
this.CellEditEventArgs.Column.PutValue(this.CellEditEventArgs.RowObject, this.CellEditEventArgs.NewValue);
|
||
this.RefreshItem(this.CellEditEventArgs.ListViewItem);
|
||
}
|
||
|
||
this.CleanupCellEdit(expectingCellEdit, this.CellEditEventArgs.AutoDispose);
|
||
|
||
// Tell the world that the cell has been edited
|
||
this.OnCellEditFinished(this.CellEditEventArgs);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Remove all trace of any existing cell edit operation
|
||
/// </summary>
|
||
/// <param name="expectingCellEdit">True if it is likely that another cell is going to be
|
||
/// edited immediately after this cell finishes editing</param>
|
||
/// <param name="disposeOfCellEditor">True if the cell editor should be disposed </param>
|
||
protected virtual void CleanupCellEdit(bool expectingCellEdit, bool disposeOfCellEditor) {
|
||
if (this.cellEditor == null)
|
||
return;
|
||
|
||
this.cellEditor.Validating -= new CancelEventHandler(CellEditor_Validating);
|
||
|
||
Control soonToBeOldCellEditor = this.cellEditor;
|
||
this.cellEditor = null;
|
||
|
||
// Delay cleaning up the cell editor so that if we are immediately going to
|
||
// start a new cell edit (because the user pressed Tab) the new cell editor
|
||
// has a chance to grab the focus. Without this, the ListView gains focus
|
||
// momentarily (after the cell editor is remove and before the new one is created)
|
||
// causing the list's selection to flash momentarily.
|
||
EventHandler toBeRun = null;
|
||
toBeRun = delegate(object sender, EventArgs e) {
|
||
Application.Idle -= toBeRun;
|
||
this.Controls.Remove(soonToBeOldCellEditor);
|
||
if (disposeOfCellEditor)
|
||
soonToBeOldCellEditor.Dispose();
|
||
this.Invalidate();
|
||
|
||
if (!this.IsCellEditing) {
|
||
if (this.Focused)
|
||
this.Select();
|
||
this.PauseAnimations(false);
|
||
}
|
||
};
|
||
|
||
// We only want to delay the removal of the control if we are expecting another cell
|
||
// to be edited. Otherwise, we remove the control immediately.
|
||
if (expectingCellEdit)
|
||
this.RunWhenIdle(toBeRun);
|
||
else
|
||
toBeRun(null, null);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Hot row and cell handling
|
||
|
||
/// <summary>
|
||
/// Force the hot item to be recalculated
|
||
/// </summary>
|
||
public virtual void ClearHotItem() {
|
||
this.UpdateHotItem(new Point(-1, -1));
|
||
}
|
||
|
||
/// <summary>
|
||
/// Force the hot item to be recalculated
|
||
/// </summary>
|
||
public virtual void RefreshHotItem() {
|
||
this.UpdateHotItem(this.PointToClient(Cursor.Position));
|
||
}
|
||
|
||
/// <summary>
|
||
/// The mouse has moved to the given pt. See if the hot item needs to be updated
|
||
/// </summary>
|
||
/// <param name="pt">Where is the mouse?</param>
|
||
/// <remarks>This is the main entry point for hot item handling</remarks>
|
||
protected virtual void UpdateHotItem(Point pt) {
|
||
this.UpdateHotItem(this.OlvHitTest(pt.X, pt.Y));
|
||
}
|
||
|
||
/// <summary>
|
||
/// The mouse has moved to the given pt. See if the hot item needs to be updated
|
||
/// </summary>
|
||
/// <param name="hti"></param>
|
||
/// <remarks>This is the main entry point for hot item handling</remarks>
|
||
protected virtual void UpdateHotItem(OlvListViewHitTestInfo hti) {
|
||
|
||
// We only need to do the work of this method when the list has hot parts
|
||
// (i.e. some element whose visual appearance changes when under the mouse)?
|
||
// Hot item decorations and hyperlinks are obvious, but if we have checkboxes
|
||
// or buttons, those are also "hot". It's difficult to quickly detect if there are any
|
||
// columns that have checkboxes or buttons, so we just abdicate responsibililty and
|
||
// provide a property (UseHotControls) which lets the programmer say whether to do
|
||
// the hot processing or not.
|
||
if (!this.UseHotItem && !this.UseHyperlinks && !this.UseHotControls)
|
||
return;
|
||
|
||
int newHotRow = hti.RowIndex;
|
||
int newHotColumn = hti.ColumnIndex;
|
||
HitTestLocation newHotCellHitLocation = hti.HitTestLocation;
|
||
HitTestLocationEx newHotCellHitLocationEx = hti.HitTestLocationEx;
|
||
OLVGroup newHotGroup = hti.Group;
|
||
|
||
// In non-details view, we treat any hit on a row as if it were a hit
|
||
// on column 0 -- which (effectively) it is!
|
||
if (newHotRow >= 0 && this.View != View.Details)
|
||
newHotColumn = 0;
|
||
|
||
if (this.HotRowIndex == newHotRow &&
|
||
this.HotColumnIndex == newHotColumn &&
|
||
this.HotCellHitLocation == newHotCellHitLocation &&
|
||
this.HotCellHitLocationEx == newHotCellHitLocationEx &&
|
||
this.HotGroup == newHotGroup) {
|
||
return;
|
||
}
|
||
|
||
// Trigger the hotitem changed event
|
||
HotItemChangedEventArgs args = new HotItemChangedEventArgs();
|
||
args.HotCellHitLocation = newHotCellHitLocation;
|
||
args.HotCellHitLocationEx = newHotCellHitLocationEx;
|
||
args.HotColumnIndex = newHotColumn;
|
||
args.HotRowIndex = newHotRow;
|
||
args.HotGroup = newHotGroup;
|
||
args.OldHotCellHitLocation = this.HotCellHitLocation;
|
||
args.OldHotCellHitLocationEx = this.HotCellHitLocationEx;
|
||
args.OldHotColumnIndex = this.HotColumnIndex;
|
||
args.OldHotRowIndex = this.HotRowIndex;
|
||
args.OldHotGroup = this.HotGroup;
|
||
this.OnHotItemChanged(args);
|
||
|
||
// Update the state of the control
|
||
this.HotRowIndex = newHotRow;
|
||
this.HotColumnIndex = newHotColumn;
|
||
this.HotCellHitLocation = newHotCellHitLocation;
|
||
this.HotCellHitLocationEx = newHotCellHitLocationEx;
|
||
this.HotGroup = newHotGroup;
|
||
|
||
// If the event handler handled it complete, don't do anything else
|
||
if (args.Handled)
|
||
return;
|
||
|
||
// System.Diagnostics.Debug.WriteLine(String.Format("Changed hot item: {0}", args));
|
||
|
||
this.BeginUpdate();
|
||
try {
|
||
this.Invalidate();
|
||
if (args.OldHotRowIndex != -1)
|
||
this.UnapplyHotItem(args.OldHotRowIndex);
|
||
|
||
if (this.HotRowIndex != -1) {
|
||
// Virtual lists apply hot item style when fetching their rows
|
||
if (this.VirtualMode) {
|
||
this.ClearCachedInfo();
|
||
this.RedrawItems(this.HotRowIndex, this.HotRowIndex, true);
|
||
} else {
|
||
this.UpdateHotRow(this.HotRowIndex, this.HotColumnIndex, this.HotCellHitLocation, hti.Item);
|
||
}
|
||
}
|
||
|
||
if (this.UseHotItem && this.HotItemStyleOrDefault.Overlay != null) {
|
||
this.RefreshOverlays();
|
||
}
|
||
}
|
||
finally {
|
||
this.EndUpdate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Update the given row using the current hot item information
|
||
/// </summary>
|
||
/// <param name="olvi"></param>
|
||
protected virtual void UpdateHotRow(OLVListItem olvi) {
|
||
this.UpdateHotRow(this.HotRowIndex, this.HotColumnIndex, this.HotCellHitLocation, olvi);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Update the given row using the given hot item information
|
||
/// </summary>
|
||
/// <param name="rowIndex"></param>
|
||
/// <param name="columnIndex"></param>
|
||
/// <param name="hitLocation"></param>
|
||
/// <param name="olvi"></param>
|
||
protected virtual void UpdateHotRow(int rowIndex, int columnIndex, HitTestLocation hitLocation, OLVListItem olvi) {
|
||
if (rowIndex < 0 || columnIndex < 0)
|
||
return;
|
||
|
||
// System.Diagnostics.Debug.WriteLine(String.Format("UpdateHotRow: {0}, {1}, {2}", rowIndex, columnIndex, hitLocation));
|
||
|
||
if (this.UseHyperlinks) {
|
||
OLVColumn column = this.GetColumn(columnIndex);
|
||
OLVListSubItem subItem = olvi.GetSubItem(columnIndex);
|
||
if (column.Hyperlink && hitLocation == HitTestLocation.Text && !String.IsNullOrEmpty(subItem.Url)) {
|
||
this.ApplyCellStyle(olvi, columnIndex, this.HyperlinkStyle.Over);
|
||
this.Cursor = this.HyperlinkStyle.OverCursor ?? Cursors.Default;
|
||
} else {
|
||
this.Cursor = Cursors.Default;
|
||
}
|
||
}
|
||
|
||
if (this.UseHotItem) {
|
||
if (!olvi.Selected && olvi.Enabled) {
|
||
this.ApplyRowStyle(olvi, this.HotItemStyleOrDefault);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Apply a style to the given row
|
||
/// </summary>
|
||
/// <param name="olvi"></param>
|
||
/// <param name="style"></param>
|
||
public virtual void ApplyRowStyle(OLVListItem olvi, IItemStyle style) {
|
||
if (style == null)
|
||
return;
|
||
|
||
Font font = style.Font ?? olvi.Font;
|
||
|
||
if (style.FontStyle != FontStyle.Regular)
|
||
font = new Font(font ?? this.Font, style.FontStyle);
|
||
|
||
if (!Equals(font, olvi.Font)) {
|
||
if (olvi.UseItemStyleForSubItems)
|
||
olvi.Font = font;
|
||
else {
|
||
foreach (ListViewItem.ListViewSubItem x in olvi.SubItems)
|
||
x.Font = font;
|
||
}
|
||
}
|
||
|
||
if (!style.ForeColor.IsEmpty) {
|
||
if (olvi.UseItemStyleForSubItems)
|
||
olvi.ForeColor = style.ForeColor;
|
||
else {
|
||
foreach (ListViewItem.ListViewSubItem x in olvi.SubItems)
|
||
x.ForeColor = style.ForeColor;
|
||
}
|
||
}
|
||
|
||
if (!style.BackColor.IsEmpty) {
|
||
if (olvi.UseItemStyleForSubItems)
|
||
olvi.BackColor = style.BackColor;
|
||
else {
|
||
foreach (ListViewItem.ListViewSubItem x in olvi.SubItems)
|
||
x.BackColor = style.BackColor;
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Apply a style to a cell
|
||
/// </summary>
|
||
/// <param name="olvi"></param>
|
||
/// <param name="columnIndex"></param>
|
||
/// <param name="style"></param>
|
||
protected virtual void ApplyCellStyle(OLVListItem olvi, int columnIndex, IItemStyle style) {
|
||
if (style == null)
|
||
return;
|
||
|
||
// Don't apply formatting to subitems when not in Details view
|
||
if (this.View != View.Details && columnIndex > 0)
|
||
return;
|
||
|
||
olvi.UseItemStyleForSubItems = false;
|
||
|
||
ListViewItem.ListViewSubItem subItem = olvi.SubItems[columnIndex];
|
||
if (style.Font != null)
|
||
subItem.Font = style.Font;
|
||
|
||
if (style.FontStyle != FontStyle.Regular)
|
||
subItem.Font = new Font(subItem.Font ?? olvi.Font ?? this.Font, style.FontStyle);
|
||
|
||
if (!style.ForeColor.IsEmpty)
|
||
subItem.ForeColor = style.ForeColor;
|
||
|
||
if (!style.BackColor.IsEmpty)
|
||
subItem.BackColor = style.BackColor;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Remove hot item styling from the given row
|
||
/// </summary>
|
||
/// <param name="index"></param>
|
||
protected virtual void UnapplyHotItem(int index) {
|
||
this.Cursor = Cursors.Default;
|
||
// Virtual lists will apply the appropriate formatting when the row is fetched
|
||
if (this.VirtualMode) {
|
||
if (index < this.VirtualListSize)
|
||
this.RedrawItems(index, index, true);
|
||
} else {
|
||
OLVListItem olvi = this.GetItem(index);
|
||
if (olvi != null) {
|
||
//this.PostProcessOneRow(index, index, olvi);
|
||
this.RefreshItem(olvi);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
#endregion
|
||
|
||
#region Drag and drop
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <param name="e"></param>
|
||
protected override void OnItemDrag(ItemDragEventArgs e) {
|
||
base.OnItemDrag(e);
|
||
|
||
if (this.DragSource == null)
|
||
return;
|
||
|
||
Object data = this.DragSource.StartDrag(this, e.Button, (OLVListItem)e.Item);
|
||
if (data != null) {
|
||
DragDropEffects effect = this.DoDragDrop(data, this.DragSource.GetAllowedEffects(data));
|
||
this.DragSource.EndDrag(data, effect);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <param name="args"></param>
|
||
protected override void OnDragEnter(DragEventArgs args) {
|
||
base.OnDragEnter(args);
|
||
|
||
if (this.DropSink != null)
|
||
this.DropSink.Enter(args);
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <param name="args"></param>
|
||
protected override void OnDragOver(DragEventArgs args) {
|
||
base.OnDragOver(args);
|
||
|
||
if (this.DropSink != null)
|
||
this.DropSink.Over(args);
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <param name="args"></param>
|
||
protected override void OnDragDrop(DragEventArgs args) {
|
||
base.OnDragDrop(args);
|
||
|
||
if (this.DropSink != null)
|
||
this.DropSink.Drop(args);
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <param name="e"></param>
|
||
protected override void OnDragLeave(EventArgs e) {
|
||
base.OnDragLeave(e);
|
||
|
||
if (this.DropSink != null)
|
||
this.DropSink.Leave();
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <param name="args"></param>
|
||
protected override void OnGiveFeedback(GiveFeedbackEventArgs args) {
|
||
base.OnGiveFeedback(args);
|
||
|
||
if (this.DropSink != null)
|
||
this.DropSink.GiveFeedback(args);
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <param name="args"></param>
|
||
protected override void OnQueryContinueDrag(QueryContinueDragEventArgs args) {
|
||
base.OnQueryContinueDrag(args);
|
||
|
||
if (this.DropSink != null)
|
||
this.DropSink.QueryContinue(args);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Decorations and Overlays
|
||
|
||
/// <summary>
|
||
/// Add the given decoration to those on this list and make it appear
|
||
/// </summary>
|
||
/// <param name="decoration">The decoration</param>
|
||
/// <remarks>
|
||
/// A decoration scrolls with the listview. An overlay stays fixed in place.
|
||
/// </remarks>
|
||
public virtual void AddDecoration(IDecoration decoration) {
|
||
if (decoration == null)
|
||
return;
|
||
this.Decorations.Add(decoration);
|
||
this.Invalidate();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Add the given overlay to those on this list and make it appear
|
||
/// </summary>
|
||
/// <param name="overlay">The overlay</param>
|
||
public virtual void AddOverlay(IOverlay overlay) {
|
||
if (overlay == null)
|
||
return;
|
||
this.Overlays.Add(overlay);
|
||
this.Invalidate();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Draw all the decorations
|
||
/// </summary>
|
||
/// <param name="g">A Graphics</param>
|
||
/// <param name="itemsThatWereRedrawn">The items that were redrawn and whose decorations should also be redrawn</param>
|
||
protected virtual void DrawAllDecorations(Graphics g, List<OLVListItem> itemsThatWereRedrawn) {
|
||
g.TextRenderingHint = ObjectListView.TextRenderingHint;
|
||
g.SmoothingMode = ObjectListView.SmoothingMode;
|
||
|
||
Rectangle contentRectangle = this.ContentRectangle;
|
||
|
||
if (this.HasEmptyListMsg && this.GetItemCount() == 0) {
|
||
this.EmptyListMsgOverlay.Draw(this, g, contentRectangle);
|
||
}
|
||
|
||
// Let the drop sink draw whatever feedback it likes
|
||
if (this.DropSink != null) {
|
||
this.DropSink.DrawFeedback(g, contentRectangle);
|
||
}
|
||
|
||
// Draw our item and subitem decorations
|
||
foreach (OLVListItem olvi in itemsThatWereRedrawn) {
|
||
if (olvi.HasDecoration) {
|
||
foreach (IDecoration d in olvi.Decorations) {
|
||
d.ListItem = olvi;
|
||
d.SubItem = null;
|
||
d.Draw(this, g, contentRectangle);
|
||
}
|
||
}
|
||
foreach (OLVListSubItem subItem in olvi.SubItems) {
|
||
if (subItem.HasDecoration) {
|
||
foreach (IDecoration d in subItem.Decorations) {
|
||
d.ListItem = olvi;
|
||
d.SubItem = subItem;
|
||
d.Draw(this, g, contentRectangle);
|
||
}
|
||
}
|
||
}
|
||
if (this.SelectedRowDecoration != null && olvi.Selected && olvi.Enabled) {
|
||
this.SelectedRowDecoration.ListItem = olvi;
|
||
this.SelectedRowDecoration.SubItem = null;
|
||
this.SelectedRowDecoration.Draw(this, g, contentRectangle);
|
||
}
|
||
}
|
||
|
||
// Now draw the specifically registered decorations
|
||
foreach (IDecoration decoration in this.Decorations) {
|
||
decoration.ListItem = null;
|
||
decoration.SubItem = null;
|
||
decoration.Draw(this, g, contentRectangle);
|
||
}
|
||
|
||
// Finally, draw any hot item decoration
|
||
if (this.UseHotItem) {
|
||
IDecoration hotItemDecoration = this.HotItemStyleOrDefault.Decoration;
|
||
if (hotItemDecoration != null) {
|
||
hotItemDecoration.ListItem = this.GetItem(this.HotRowIndex);
|
||
if (hotItemDecoration.ListItem == null || hotItemDecoration.ListItem.Enabled) {
|
||
hotItemDecoration.SubItem = hotItemDecoration.ListItem == null ? null : hotItemDecoration.ListItem.GetSubItem(this.HotColumnIndex);
|
||
hotItemDecoration.Draw(this, g, contentRectangle);
|
||
}
|
||
}
|
||
}
|
||
|
||
// If we are in design mode, we don't want to use the glass panels,
|
||
// so we draw the background overlays here
|
||
if (this.DesignMode) {
|
||
foreach (IOverlay overlay in this.Overlays) {
|
||
overlay.Draw(this, g, contentRectangle);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Is the given decoration shown on this list
|
||
/// </summary>
|
||
/// <param name="decoration">The overlay</param>
|
||
public virtual bool HasDecoration(IDecoration decoration) {
|
||
return this.Decorations.Contains(decoration);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Is the given overlay shown on this list?
|
||
/// </summary>
|
||
/// <param name="overlay">The overlay</param>
|
||
public virtual bool HasOverlay(IOverlay overlay) {
|
||
return this.Overlays.Contains(overlay);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Hide any overlays.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This is only a temporary hiding -- the overlays will be shown
|
||
/// the next time the ObjectListView redraws.
|
||
/// </remarks>
|
||
public virtual void HideOverlays() {
|
||
foreach (GlassPanelForm glassPanel in this.glassPanels) {
|
||
glassPanel.HideGlass();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Create and configure the empty list msg overlay
|
||
/// </summary>
|
||
protected virtual void InitializeEmptyListMsgOverlay() {
|
||
TextOverlay overlay = new TextOverlay();
|
||
overlay.Alignment = System.Drawing.ContentAlignment.MiddleCenter;
|
||
overlay.TextColor = SystemColors.ControlDarkDark;
|
||
overlay.BackColor = Color.BlanchedAlmond;
|
||
overlay.BorderColor = SystemColors.ControlDark;
|
||
overlay.BorderWidth = 2.0f;
|
||
this.EmptyListMsgOverlay = overlay;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Initialize the standard image and text overlays
|
||
/// </summary>
|
||
protected virtual void InitializeStandardOverlays() {
|
||
this.OverlayImage = new ImageOverlay();
|
||
this.AddOverlay(this.OverlayImage);
|
||
this.OverlayText = new TextOverlay();
|
||
this.AddOverlay(this.OverlayText);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Make sure that any overlays are visible.
|
||
/// </summary>
|
||
public virtual void ShowOverlays() {
|
||
// If we shouldn't show overlays, then don't create glass panels
|
||
if (!this.ShouldShowOverlays())
|
||
return;
|
||
|
||
// Make sure that each overlay has its own glass panels
|
||
if (this.Overlays.Count != this.glassPanels.Count) {
|
||
foreach (IOverlay overlay in this.Overlays) {
|
||
GlassPanelForm glassPanel = this.FindGlassPanelForOverlay(overlay);
|
||
if (glassPanel == null) {
|
||
glassPanel = new GlassPanelForm();
|
||
glassPanel.Bind(this, overlay);
|
||
this.glassPanels.Add(glassPanel);
|
||
}
|
||
}
|
||
}
|
||
foreach (GlassPanelForm glassPanel in this.glassPanels) {
|
||
glassPanel.ShowGlass();
|
||
}
|
||
}
|
||
|
||
private bool ShouldShowOverlays() {
|
||
// If we are in design mode, we dont show the overlays
|
||
if (this.DesignMode)
|
||
return false;
|
||
|
||
// If we are explicitly not using overlays, also don't show them
|
||
if (!this.UseOverlays)
|
||
return false;
|
||
|
||
// If there are no overlays, guess...
|
||
if (!this.HasOverlays)
|
||
return false;
|
||
|
||
// If we don't have 32-bit display, alpha blending doesn't work, so again, no overlays
|
||
// TODO: This should actually figure out which screen(s) the control is on, and make sure
|
||
// that each one is 32-bit.
|
||
if (Screen.PrimaryScreen.BitsPerPixel < 32)
|
||
return false;
|
||
|
||
// Finally, we can show the overlays
|
||
return true;
|
||
}
|
||
|
||
private GlassPanelForm FindGlassPanelForOverlay(IOverlay overlay) {
|
||
return this.glassPanels.Find(delegate(GlassPanelForm x) { return x.Overlay == overlay; });
|
||
}
|
||
|
||
/// <summary>
|
||
/// Refresh the display of the overlays
|
||
/// </summary>
|
||
public virtual void RefreshOverlays() {
|
||
foreach (GlassPanelForm glassPanel in this.glassPanels) {
|
||
glassPanel.Invalidate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Refresh the display of just one overlays
|
||
/// </summary>
|
||
public virtual void RefreshOverlay(IOverlay overlay) {
|
||
GlassPanelForm glassPanel = this.FindGlassPanelForOverlay(overlay);
|
||
if (glassPanel != null)
|
||
glassPanel.Invalidate();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Remove the given decoration from this list
|
||
/// </summary>
|
||
/// <param name="decoration">The decoration to remove</param>
|
||
public virtual void RemoveDecoration(IDecoration decoration) {
|
||
if (decoration == null)
|
||
return;
|
||
this.Decorations.Remove(decoration);
|
||
this.Invalidate();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Remove the given overlay to those on this list
|
||
/// </summary>
|
||
/// <param name="overlay">The overlay</param>
|
||
public virtual void RemoveOverlay(IOverlay overlay) {
|
||
if (overlay == null)
|
||
return;
|
||
this.Overlays.Remove(overlay);
|
||
GlassPanelForm glassPanel = this.FindGlassPanelForOverlay(overlay);
|
||
if (glassPanel != null) {
|
||
this.glassPanels.Remove(glassPanel);
|
||
glassPanel.Unbind();
|
||
glassPanel.Dispose();
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Filtering
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>ɸѡ<C9B8><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɸѡ<C9B8><D1A1><EFBFBD><EFBFBD>ִ<EFBFBD>е<EFBFBD>ǰ<EFBFBD><C7B0>װ<EFBFBD>ڿɼ<DABF><C9BC><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD><EFBFBD>ɸѡ<C9B8><D1A1>
|
||
/// </summary>
|
||
public virtual IModelFilter CreateColumnFilter() {
|
||
List<IModelFilter> filters = new List<IModelFilter>();
|
||
foreach (OLVColumn column in this.Columns) {
|
||
IModelFilter filter = column.ValueBasedFilter;
|
||
if (filter != null)
|
||
filters.Add(filter);
|
||
}
|
||
return (filters.Count == 0) ? null : new CompositeAllFilter(filters);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Do the actual work of filtering
|
||
/// </summary>
|
||
/// <param name="originalObjects"></param>
|
||
/// <param name="aModelFilter"></param>
|
||
/// <param name="aListFilter"></param>
|
||
/// <returns></returns>
|
||
virtual protected IEnumerable FilterObjects(IEnumerable originalObjects, IModelFilter aModelFilter, IListFilter aListFilter) {
|
||
// Being cautious
|
||
originalObjects = originalObjects ?? new ArrayList();
|
||
|
||
// Tell the world to filter the objects. If they do so, don't do anything else
|
||
// ReSharper disable PossibleMultipleEnumeration
|
||
FilterEventArgs args = new FilterEventArgs(originalObjects);
|
||
this.OnFilter(args);
|
||
if (args.FilteredObjects != null)
|
||
return args.FilteredObjects;
|
||
|
||
// Apply a filter to the list as a whole
|
||
if (aListFilter != null)
|
||
originalObjects = aListFilter.Filter(originalObjects);
|
||
|
||
// Apply the object filter if there is one
|
||
if (aModelFilter != null) {
|
||
ArrayList filteredObjects = new ArrayList();
|
||
foreach (object model in originalObjects) {
|
||
if (aModelFilter.Filter(model))
|
||
filteredObjects.Add(model);
|
||
}
|
||
originalObjects = filteredObjects;
|
||
}
|
||
|
||
return originalObjects;
|
||
// ReSharper restore PossibleMultipleEnumeration
|
||
}
|
||
|
||
/// <summary>
|
||
/// ɾ<><C9BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɸѡ<C9B8><D1A1>
|
||
/// </summary>
|
||
public virtual void ResetColumnFiltering() {
|
||
foreach (OLVColumn column in this.Columns) {
|
||
column.ValuesChosenForFiltering.Clear();
|
||
}
|
||
this.UpdateColumnFiltering();
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD>ֵɸѡ<C9B8><D1A1><EFBFBD>´<EFBFBD>ObjectListView<65><77>ɸѡ
|
||
/// </summary>
|
||
public virtual void UpdateColumnFiltering() {
|
||
//List<IModelFilter> filters = new List<IModelFilter>();
|
||
//IModelFilter columnFilter = this.CreateColumnFilter();
|
||
//if (columnFilter != null)
|
||
// filters.Add(columnFilter);
|
||
//if (this.AdditionalFilter != null)
|
||
// filters.Add(this.AdditionalFilter);
|
||
//this.ModelFilter = filters.Count == 0 ? null : new CompositeAllFilter(filters);
|
||
|
||
if (this.AdditionalFilter == null)
|
||
this.ModelFilter = this.CreateColumnFilter();
|
||
else {
|
||
IModelFilter columnFilter = this.CreateColumnFilter();
|
||
if (columnFilter == null)
|
||
this.ModelFilter = this.AdditionalFilter;
|
||
else {
|
||
List<IModelFilter> filters = new List<IModelFilter>();
|
||
filters.Add(columnFilter);
|
||
filters.Add(this.AdditionalFilter);
|
||
this.ModelFilter = new CompositeAllFilter(filters);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// When some setting related to filtering changes, this method is called.
|
||
/// </summary>
|
||
protected virtual void UpdateFiltering() {
|
||
this.BuildList(true);
|
||
}
|
||
|
||
/// <summary>
|
||
/// ʹ<>õ<EFBFBD>ǰ<EFBFBD><C7B0>װ<EFBFBD><D7B0>ģ<EFBFBD><EFBFBD><CDB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ⱦ<EFBFBD><C8BE>
|
||
/// </summary>
|
||
protected virtual void NotifyNewModelFilter() {
|
||
IFilterAwareRenderer filterAware = this.DefaultRenderer as IFilterAwareRenderer;
|
||
if (filterAware != null)
|
||
filterAware.Filter = this.ModelFilter;
|
||
|
||
foreach (OLVColumn column in this.AllColumns) {
|
||
filterAware = column.Renderer as IFilterAwareRenderer;
|
||
if (filterAware != null)
|
||
filterAware.Filter = this.ModelFilter;
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Persistent check state
|
||
|
||
/// <summary>
|
||
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>ģ<EFBFBD>͵ĸ<CDB5>ѡ<EFBFBD><D1A1>״̬<D7B4><CCAC>
|
||
/// </summary>
|
||
/// <param name="model">The model</param>
|
||
/// <returns>ģ<>͵ĸ<CDB5>ѡ<EFBFBD><D1A1>״̬<D7B4><CCAC>Ĭ<EFBFBD><C4AC>Ϊδѡ<CEB4>С<EFBFBD></returns>
|
||
protected virtual CheckState GetPersistentCheckState(object model) {
|
||
CheckState state;
|
||
if (model != null && this.CheckStateMap.TryGetValue(model, out state))
|
||
return state;
|
||
return CheckState.Unchecked;
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD>ø<EFBFBD><C3B8><EFBFBD>ģ<EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD>ĸ<EFBFBD>ѡ<EFBFBD><D1A1>״̬
|
||
/// </summary>
|
||
/// <param name="model">The model to be remembered</param>
|
||
/// <param name="state">The model's checkedness</param>
|
||
/// <returns>The state given to the method</returns>
|
||
protected virtual CheckState SetPersistentCheckState(object model, CheckState state) {
|
||
if (model == null)
|
||
return CheckState.Unchecked;
|
||
|
||
this.CheckStateMap[model] = state;
|
||
return state;
|
||
}
|
||
|
||
/// <summary>
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD>κγ־ø<D6BE>ѡ<EFBFBD><D1A1>״̬
|
||
/// </summary>
|
||
protected virtual void ClearPersistentCheckState() {
|
||
this.CheckStateMap = null;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Implementation variables
|
||
|
||
private bool isOwnerOfObjects; // does this ObjectListView own the Objects collection?
|
||
private bool hasIdleHandler; // has an Idle handler already been installed?
|
||
private bool hasResizeColumnsHandler; // has an idle handler been installed which will handle column resizing?
|
||
private bool isInWmPaintEvent; // is a WmPaint event currently being handled?
|
||
private bool shouldDoCustomDrawing; // should the list do its custom drawing?
|
||
private bool isMarqueSelecting; // Is a marque selection in progress?
|
||
private int suspendSelectionEventCount; // How many unmatched SuspendSelectionEvents() calls have been made?
|
||
|
||
private readonly List<GlassPanelForm> glassPanels = new List<GlassPanelForm>(); // The transparent panel that draws overlays
|
||
private Dictionary<string, bool> visitedUrlMap = new Dictionary<string, bool>(); // Which urls have been visited?
|
||
|
||
// TODO
|
||
//private CheckBoxSettings checkBoxSettings = new CheckBoxSettings();
|
||
|
||
#endregion
|
||
}
|
||
}
|