Sign in Join
Wiki copytemporary

TListView: what changed

Revision 2 to 3. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11**TListView** ![](/wiki-images/d/d7/Tlistview.png) is a visible component on the [[Common Controls tab]] of the [[Component Palette]] that provides a list view of its associated Items. Items can be represented by an icon from each of the associated [[TImageList|TImageLists]]: SmallImages, LargeImages and StateImages.
22
33## Notes
44
55- **GetNextItem**() requires StartItem to be provided. This is incompatible with Delphi's GetNextItem(), where startItem is allowed to be **nil**, which will perform the search from the relative (direction driven) start.
66
77## Sorting
88
9-`TODO: add description on how OwnerData affects the sorting`
9+```text
10+TODO: add description on how OwnerData affects the sorting
11+```
1012
1113Sorting is (typically?) applied when using **vsReport** ViewStyle, as it's column driven (with Sortcolumn index required). Sorting might be a time consuming for a larger data scale (when comparison of items takes a considerable time).
1214
1315**SortType** is the key property in order to perform any sorting in TListView.
1416
1517
1618**stNone** - (the default value) that no sorting should be for the control.
1719
1820**stText** - the text of a cells would be used for item comparison. The actual text entry is controlled by **SortColumn** property. Note the default sorting comparison is actually treats the text as Ansi, rather than UTF8. Thus the result might be undesired for the non-English texts
1921
2022**stData** - the default sorting comparison treats **Data** property as an integer value (by casting pointer to an integer) and sorts the according to value. (in most cases such sorting is useless, unless "Data" is an actual integer casted to the pointer)
2123
2224**stBoth** - treated as **stText** for in the default sorting comparison.
2325
2426Unless using text sorting, the default comparison method is not the best approach, instead a custom comparison could be used. The custom comparison is assigned with **OnCompare** event of TListView. The following parameters are passed:
2527
2628
2729**Sender** - TListview that's being sorted
2830
2931**Item1** - one TListItem being compared
3032
3133**Item2** - another TListItem being compared to the one
3234
3335**Data** - is not used and is always passed as zero. (provided for Delphi compatibility)
3436
3537**Compare** - the result of the comparison, that must be populated by the event. The following values should be assigned to the **Compare** argument.
3638
3739
3840-1 - if Item1 should show up "earlier" in Ascending order, than Item2. (Item1 is less than Item2)
3941
40420 - if two items are equal
4143
42441 - if Item2 should show up "earlier" in Ascending order, than Item1. (Item2 is less than Item1)
4345
4446It's a normal practice to reverse the comparison result value, if SortDirection is descending. I.e.:
4547
4648```delphi
4749procedure TForm1.ListView1OnCompare(Sender: TObject; Item1, Item2: TListItem;
4850 Data: Integer; var Compare: Integer)
4951begin
5052 ... do the comparison...
5153
5254 if TListView(Sender).SortDirection = sdDescending then
5355 Compare := -Compare;
5456end;
5557```
5658
5759The OnCompare event should check for **SortType**, **SortColumn** and **SortDirection** properties of TListView, and do adjust the comparison result respectively of those properties.
5860
5961Method **Sort** performs of items, if **SortType** is other than **stNone** and SortColumn is assigned to a valid column index.
6062
6163Method **CustomSort** performs a one-time sorting using a provided sorting function.
6264
6365
6466ASortProc: TLVCompare - sorting function
6567
6668AOptionalParam: PtrInt - sorting parameter
6769
6870Sorting parameter is ignored (provided for the Delphi compatibility). If **ASortProc** is passed as nil, then the either sorting OnCompare is used or default sorting.
6971
7072Typically the sorting can be requested by a user. Whenever a user clicks on a column header, that requires to either sort (initially ascendancy) or to switch to the opposite sorting order (either from ascendant to descendant, or back). It's not a rule, but a common expectation. For some data sets selecting sorting might not make any sense. **AutoSort** (default value is true)the property of TListview controls, if the listview should be sorted automatically, as soon as user clicks on a column header. **AutoSort** will have no effect, while **SortType** is set to **stNone**.
7173
7274**AlphaSort** is a convenience method, that changes the settings to ascending sort (SortDirection=sdAscending) based on the text (SortType=stText) of the first column (SortColumn=0). Note that the actual properties are changed.
7375
7476### Sort Indicator
7577
7678Originating from: <https://bugs.freepascal.org/view.php?id=36281>
7779
7880In trunk since r62567
7981
80821\) Add a new property **SortIndicator** to TListViewColumn. The property controls system native sort indicator.
8183
8284The indicator is acting solely as a decorative feature. (Doesn't have any effect on the sorting). The indicator has 3 possible values
8385
8486
8587**siNone** - no sort indicator should be shown
8688
8789**siAscending** - ascending indicator should be shown
8890
8991**siDescending** - descending indicator should be shown
9092
9193The property can work independently of other TListview sorting properties.
9294
9395![](/wiki-images/2/29/Autosort0.gif)
9496
95972\) Add new property **AutoSortIndicator** to TListView. The property is intended to be used as a compliment to **AutoSort** property. If both are enabled, LCL code controls the current selection of the column sortindicator according to **AutoSort** rules.
9698
9799![](/wiki-images/7/78/Autosort2.gif)
98100
99101Early 2021 it was noticed that if you are using Qt5 and you have TListView.SortDirection set to sdAscending (the default), then setting a column's Sort Indicator to siDescending displays an ascending indicator. This does not happen with GTK2 or GTK3. Setting SortDirection to sdDescending makes all other combinations work fine so, seems an easy solution. Logged <https://bugs.freepascal.org/view.php?id=38393>
100102
101103## Custom drawing
102104
103105There is a good article on custom-drawing `TListView`: <https://delphidabbler.com/articles/article-16>. Most of the sample code in this article is working in Lazarus, too, however only **on Windows**. Here are some excerpts:
104106
105107Note: Keep the `OwnerDraw` property of the `TListView` at `false`.
106108
107109### Alternating row colors
108110
109111![](/wiki-images/7/70/Listview_alternating_rowcolors.png) Attach this handler for the `OnCustomDrawItem` event which is responsible for painting a full row. When the `DefaultDraw` parameter of the event handler is unchanged (i.e., `true`) then control still paints the text and additional gimmicks such as icons or checkboxes (see screenshot at the right):
110112
111113``` Pascal
112114procedure TForm1.ListView1CustomDrawItem(Sender: TCustomListView;
113115 Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
114116begin
115117 if Odd(Item.Index) then
116118 // odd list items have green background
117119 ListView1.Canvas.Brush.Color := clMoneyGreen
118120 else
119121 // even list items have window colour background
120122 ListView1.Canvas.Brush.Color := clWindow;
121123end;
122124```
123125
124126### Individual column colors
125127
126128At first prepare a procedure to set the brush color for each ListView column:
127129
128130``` Pascal
129131{ Sets the brush colour for the column. Our ListView has 3 columns }
130132procedure TForm1.SetLVColumnColour(AColIndex: Integer);
131133const
132134 cRainbow: array[0..2] of TColor = ($FFCCCC, $CCFFCC, $CCCCFF);
133135begin
134136 ListView1.Canvas.Brush.Color := cRainBow[AColumnIndex];
135137end;
136138```
137139
138140Then provide a handler of the `OnCustomDrawItem` event which is responsible for painting of the entire row and, in particular, of the 1st column, and the `OnCustomDrawSubItem` event which is called when the other columns are painted: ![](/wiki-images/1/1d/Listview_different_column_colors.png)
139141
140142``` Pascal
141143{ Draw the "Caption" column }
142144procedure TForm1.ListView1CustomDrawItem(Sender: TCustomListView;
143145 Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
144146begin
145147 SetLVColumnColour(0);
146148end;
147149
148150{ Draw the sub item columns }
149151procedure TForm1.ListView1CustomDrawSubItem(Sender: TCustomListView;
150152 Item: TListItem; SubItem: Integer; State: TCustomDrawState;
151153 var DefaultDraw: Boolean);
152154begin
153155 SetLVColumnColour(SubItem);
154156end;
155157```
156158
157159## Widgetset Implementation
158160
159161ListView is implemented via TWSCustomListViewClassinterface.
160162
161163**Method**
162164
163165**Description**
164166
165167SelectAll
166168
167169The method provides a parameter **AIsSet**.
168170
169171If the parameter is set to **true** then all items should selected in the view. If it's **false** then, all parameters should deselected.
170172
171173It's important that the event shouldn't trigger any events, as LCL will call SelectChange event by itself.
172174
173175## See also
174176
175177- [[doc:lcl/comctrls/tlistview.html|Doc. TListView]]
176178- [[TTreeView]]
177179- [[TShellListView]]
178180
179181---
180182*From the Free Pascal wiki, page "TListView", as it stood on 2023-04-28 after a change by Wp, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history