Class

DesktopTable

Table, Grid


Description

The scrollable DesktopTable control displays one or more columns of information.

Rows can be held by the table itself or supplied by a TableDataSource, in which case the table keeps no copy of the data and asks for the visible cells only.

Properties

Name

Type

Read-Only

Shared

Active

Boolean

✓

ActiveTextControl

DesktopTextControl

✓

AllowAutoDeactivate

Boolean

AllowAutoHideScrollbars

Boolean

AllowColumnReordering

Boolean

AllowExpandableRows

Boolean

AllowFocus

Boolean

AllowFocusRing

Boolean

AllowResizableColumns

Boolean

AllowResizableRows

Boolean

AllowRowAnimation

Boolean

AllowRowDragging

Boolean

AllowRowReordering

Boolean

AllowTabs

Boolean

AllowTabStop

Boolean

AlternatingRowColor

ColorGroup

Bold

Boolean

BottomInset

Double

CellContainerPadding

Double

ColumnCount

Integer

ColumnWidths

String

ContainerCacheSize

Integer

Content

String

DataSource

TableDataSource

DefaultRowHeight

Integer

DropIndicatorVisible

Boolean

Enabled

Boolean

FontName

String

FontSize

Single

FontUnit

FontUnits

FrozenColumns

DesktopTableFrozenColumns

✓

FrozenRows

DesktopTableFrozenRows

✓

GridColor

ColorGroup

GridLineStyle

DesktopTable.GridLineStyles

Handle

Ptr

✓

HasAlternatingRowColors

Boolean

HasBorder

Boolean

HasColumnHeader

Boolean

HasHorizontalScrollbar

Boolean

HasTranslucentBackground

Boolean

HasTranslucentHeader

Boolean

HasVerticalScrollbar

Boolean

HeaderHeight

Integer

HeadingIndex

Integer

Height

Integer

Index

Integer

InitialValue

String

Italic

Boolean

LastAddedColumnIndex

Integer

✓

LastAddedRowIndex

Integer

✓

LastColumnIndex

Integer

✓

LastRowIndex

Integer

✓

Left

Integer

LockBottom

Boolean

LockLeft

Boolean

LockRight

Boolean

LockTop

Boolean

MouseCursor

MouseCursor

Name

String

✓

PanelIndex

Integer

Parent

Object

RequiresSelection

Boolean

RowCount

Integer

✓

RowHeight

Integer

✓

RowSelectionType

DesktopTable.RowSelectionTypes

Scope

Integer

✓

ScrollPosition

Integer

ScrollPositionX

Integer

SelectedRowCount

Integer

✓

SelectedRowIndex

Integer

SelectedRowText

String

✓

SortingColumn

Integer

TabIndex

Integer

Tooltip

String

Top

Integer

TopInset

Double

Transparent

Boolean

Underline

Boolean

Visible

Boolean

Width

Integer

Window

DesktopWindow

✓

Methods

Name

Parameters

Returns

Shared

AcceptFileDrop

FileType As String

AcceptPictureDrop

AcceptRawDataDrop

Type As String

AcceptTextDrop

AddAllExpandableRows

rows As RowSet

items() As String

items(,) As String

ParamArray item As String

count As Integer

AddAllRows

rows As RowSet

items() As String

items(,) As String

ParamArray item As String

count As Integer

AddColumn

header As String = ""

AddColumnAt

index As Integer, header As String = ""

AddExpandableRow

items() As String

ParamArray item As String

AddExpandableRowAt

row As Integer, text As String, depth As Integer = 0

AddListSelectionNotificationReceiver

receiver As ListSelectionNotificationReceiver

AddRow

items() As String

ParamArray item As String

AddRowAt

row As Integer, text As String, depth As Integer = 0

CellAlignmentAt

row As Integer, column As Integer

DesktopTable.Alignments

row As Integer, column As Integer, Assigns value As DesktopTable.Alignments

CellAlignmentOffsetAt

row As Integer, column As Integer

Integer

row As Integer, column As Integer, Assigns value As Integer

CellBoldAt

row As Integer, column As Integer

Boolean

row As Integer, column As Integer, Assigns value As Boolean

CellBorderColorAt

row As Integer, column As Integer

ColorGroup

row As Integer, column As Integer, Assigns value As ColorGroup

CellBoundsAt

row As Integer, column As Integer

Rect

CellCheckBoxEnabledAt

row As Integer, column As Integer

Boolean

row As Integer, column As Integer, Assigns value As Boolean

CellCheckBoxStateAt

row As Integer, column As Integer

DesktopCheckBox.VisualStates

row As Integer, column As Integer, Assigns value As DesktopCheckBox.VisualStates

CellCheckBoxValueAt

row As Integer, column As Integer

Boolean

row As Integer, column As Integer, Assigns value As Boolean

CellIsMerged

row As Integer, column As Integer

Boolean

CellItalicAt

row As Integer, column As Integer

Boolean

row As Integer, column As Integer, Assigns value As Boolean

CellMergeBounds

row As Integer, column As Integer, ByRef anchorRow As Integer, ByRef anchorColumn As Integer, ByRef rowSpan As Integer, ByRef columnSpan As Integer

Boolean

CellProgressBarMaximumValueAt

row As Integer, column As Integer

Double

row As Integer, column As Integer, Assigns value As Double

CellProgressBarValueAt

row As Integer, column As Integer

Double

row As Integer, column As Integer, Assigns value As Double

CellTagAt

row As Integer, column As Integer

Variant

row As Integer, column As Integer, Assigns value As Variant

CellTextAt

row As Integer, column As Integer = 0

String

row As Integer, column As Integer = 0, Assigns value As String

CellTooltipAt

row As Integer, column As Integer

String

row As Integer, column As Integer, Assigns value As String

CellTypeAt

row As Integer, column As Integer

DesktopTable.CellTypes

row As Integer, column As Integer, Assigns value As DesktopTable.CellTypes

CellUnderlineAt

row As Integer, column As Integer

Boolean

row As Integer, column As Integer, Assigns value As Boolean

Close

CollapseAllRows

ColumnAlignmentAt

column As Integer

DesktopTable.Alignments

column As Integer, Assigns value As DesktopTable.Alignments

ColumnAlignmentOffsetAt

column As Integer

Integer

column As Integer, Assigns value As Integer

ColumnAttributesAt

column As Integer

DesktopTableColumn

column As Integer, Assigns value As DesktopTableColumn

ColumnFromXY

x As Integer, y As Integer

Integer

ColumnHeaderAt

index As Integer

String

index As Integer, Assigns value As String

Columns

Iterable

ColumnSortDirectionAt

column As Integer

DesktopTable.SortDirections

column As Integer, Assigns value As DesktopTable.SortDirections

ColumnSortTypeAt

column As Integer

DesktopTable.SortTypes

column As Integer, Assigns value As DesktopTable.SortTypes

ColumnTagAt

column As Integer

Variant

column As Integer, Assigns value As Variant

ColumnTypeAt

column As Integer

DesktopTable.CellTypes

column As Integer, Assigns value As DesktopTable.CellTypes

ColumnVisibleAt

index As Integer

Boolean

index As Integer, Assigns value As Boolean

ContainerForCellAt

row As Integer, column As Integer

DesktopContainer

DrawInto

g As Graphics, left As Integer, top As Integer

EditCellAt

row As Integer, column As Integer

ExpandAllRows

MergeCells

row As Integer, column As Integer, rowSpan As Integer, columnSpan As Integer

Open

file As FolderItem, delimiter As String = ",", importHeaders As Boolean = True

PressColumnHeaderAt

column As Integer

Refresh

immediately As Boolean = False

x As Integer, y As Integer, width As Integer, height As Integer, immediately As Boolean = False

RefreshCellAt

row As Integer, column As Integer

ReloadFromDataSource

RemoveAllColumns

RemoveAllMerges

RemoveAllRows

RemoveColumnAt

index As Integer

RemoveListSelectionNotificationReceiver

receiver As ListSelectionNotificationReceiver

RemoveRowAt

index As Integer

ReusableContainer

identifier As String

DesktopContainer

RowAt

row As Integer

DesktopTableRow

RowDepthAt

row As Integer

Integer

RowExpandableAt

row As Integer

Boolean

row As Integer, Assigns value As Boolean

RowExpandedAt

row As Integer

Boolean

row As Integer, Assigns value As Boolean

RowForContainer

container As DesktopContainer

Integer

RowFromXY

x As Integer, y As Integer

Integer

RowHeightAt

row As Integer

Double

row As Integer, Assigns height As Double

RowImageAt

index As Integer

Picture

index As Integer, Assigns value As Picture

Rows

Iterable

RowSelectedAt

index As Integer

Boolean

index As Integer, Assigns value As Boolean

RowTagAt

row As Integer

Variant

row As Integer, Assigns value As Variant

Save

file As FolderItem, delimiter As String = ",", exportHeaders As Boolean = True

ScrollTo

row As Integer, column As Integer = 0

SectionHeaderAt

row As Integer

Boolean

row As Integer, Assigns value As Boolean

SelectAll

SetFocus

Sort

UnmergeCellsAt

row As Integer, column As Integer

Events

Name

Parameters

Returns

Activated

ApplyLeadingActionsForRow

row As Integer

DesktopTableRowAction()

ApplyTrailingActionsForRow

row As Integer

DesktopTableRowAction()

CellAction

row As Integer, column As Integer

CellFocusLost

row As Integer, column As Integer

CellFocusReceived

row As Integer, column As Integer

CellKeyDown

row As Integer, column As Integer, key As String

Boolean

CellPressed

row As Integer, column As Integer, x As Integer, y As Integer

Boolean

CellTextChanged

row As Integer, column As Integer

Closing

ColumnHeaderPressed

column As Integer

Boolean

ColumnReordered

fromColumn As Integer, toColumn As Integer

ColumnReordering

fromColumn As Integer, toColumn As Integer

Boolean

ColumnResized

column As Integer, width As Integer

ColumnResizing

column As Integer, width As Integer

ColumnSorted

column As Integer

Boolean

ConstructContextualMenu

base As DesktopMenuItem, x As Integer, y As Integer

Boolean

ContainerAt

row As Integer, column As Integer

DesktopContainer

ContainerRemovedAt

row As Integer, column As Integer, container As DesktopContainer

Boolean

ContextualMenuItemSelected

selectedItem As DesktopMenuItem

Boolean

Deactivated

DoublePressed

row As Integer, column As Integer

DragEnter

obj As DragItem, action As DragItem.Types

Boolean

DragExit

obj As DragItem, action As DragItem.Types

DragOver

x As Integer, y As Integer, obj As DragItem, action As DragItem.Types

Boolean

DragOverRow

x As Integer, y As Integer, obj As DragItem, action As Integer, ByRef row As Integer, ByRef parentRow As Integer, ByRef location As DesktopTable.DropLocations

Boolean

DragReorderRows

newPosition As Integer, parentRow As Integer

Boolean

DragRow

drag As DragItem, row As Integer

Boolean

DropObject

obj As DragItem, action As DragItem.Types

DropObjectOnRow

x As Integer, y As Integer, obj As DragItem, action As Integer, row As Integer, parentRow As Integer, location As DesktopTable.DropLocations

FocusLost

FocusReceived

KeyDown

key As String

Boolean

KeyUp

key As String

MenuBarSelected

MouseDown

x As Integer, y As Integer

Boolean

MouseDrag

x As Integer, y As Integer

MouseEnter

MouseExit

MouseMove

x As Integer, y As Integer

MouseUp

x As Integer, y As Integer

MouseWheel

x As Integer, y As Integer, deltaX As Integer, deltaY As Integer

Boolean

Opening

PaintBackground

g As Graphics

PaintCellBackground

g As Graphics, row As Integer, column As Integer

Boolean

PaintCellText

g As Graphics, row As Integer, column As Integer, x As Integer, y As Integer

Boolean

PaintDisclosureWidget

g As Graphics, row As Integer, ByRef x As Integer, ByRef y As Integer, ByRef width As Integer, ByRef height As Integer

Boolean

PaintHeaderBackground

g As Graphics, column As Integer

Boolean

PaintHeaderContent

g As Graphics, column As Integer, x As Integer, y As Integer

Boolean

PaintRowAction

g As Graphics, row As Integer, action As DesktopTableRowAction, pressed As Boolean

Boolean

PaintSortWidget

g As Graphics, column As Integer, ByRef x As Integer, ByRef y As Integer, ByRef width As Integer, ByRef height As Integer

Boolean

RowActionSelected

row As Integer, action As DesktopTableRowAction

RowCollapsed

row As Integer

RowComparison

row1 As Integer, row2 As Integer, column As Integer, ByRef result As Integer

Boolean

RowExpanded

row As Integer

Scrolled

x As Integer, y As Integer

SelectionChanged

Constants

These constants are designed to be used with some DesktopTable methods to make code more readable.

Name

Description

AllColumns

Sentinel for 'every column' in cell and column setters.

AllRows

Sentinel for 'every row' in cell setters.

NoSelection

Returned by SelectedRowIndex when nothing is selected.

Enumerations

DesktopTable.Alignments

Alignments

Used to indicate how the content of a cell or column is aligned.

Enum

Description

Default

The platform's default alignment, left in a left-to-right layout.

Left

The value is left-justified.

Center

The value is centred.

Right

The value is right-justified.

Decimal

The value is aligned on its decimal separator.

DesktopTable.CellTypes

CellTypes

Used to indicate what a cell contains and whether the user can edit it.

Enum

Description

Default

The cell uses the type of its column.

Normal

A cell the user cannot edit directly.

CheckBox

The cell shows a native checkbox.

TextField

The cell can be edited in a single-line inline editor.

TextArea

The cell can be edited in a multi-line inline editor.

ProgressBar

The cell shows a native progress bar; the value comes from CellProgressBarValueAt.

Container

The cell shows a DesktopContainer, supplied by the ContainerAt event.

DesktopTable.DropLocations

DropLocations

Used to indicate where on the table an object was dropped.

Enum

Description

OnRow

The drop happens on the row itself.

AfterRow

The drop happens between rows, after the row given. -1 inserts above all rows.

AfterAllRows

The drop happens after the last row.

OnControl

The drop happens on the control as a whole, not on a particular row.

DesktopTable.GridLineStyles

GridLineStyles

Used to indicate which grid lines are drawn.

Enum

Description

None

No grid lines. This is the default.

Horizontal

Horizontal grid lines only.

Vertical

Vertical grid lines only.

Both

Both horizontal and vertical grid lines.

DesktopTable.RowSelectionTypes

RowSelectionTypes

Used to indicate whether one or more rows can be selected.

Enum

Description

Single

Only one row can be selected at a time.

Multiple

Any number of rows can be selected at the same time.

DesktopTable.SortDirections

SortDirections

Used to indicate whether a column sorts ascending, descending or not at all.

Enum

Description

Descending

The rows are sorted in reverse order.

None

The column is not sorted and its header shows no sort indicator.

Ascending

The rows are sorted in standard order.

DesktopTable.SortTypes

SortTypes

Used to indicate whether the user can sort a column by its header.

Enum

Description

Sortable

The column header sorts the table when it is clicked.

NotSortable

The column header does not sort the table.

Property descriptions


DesktopTable.Active

Active As Boolean

Indicates whether the control is active.

Active is False when the control's window is not in the foreground. When a DesktopWindow is deactivated, its controls are automatically deactivated unless AllowAutoDeactivate is set to False.

This property is read-only.

This example reads the property:

Var value As Boolean = Table1.Active

DesktopTable.ActiveTextControl

ActiveTextControl As DesktopTextControl

The live inline editor (DesktopTextField or DesktopTextArea), or Nil when no cell is being edited.

This property is read-only.

This example reads the live inline editor (DesktopTextField or DesktopTextArea), or Nil when no cell is being edited:

Var value As DesktopTextControl = Table1.ActiveTextControl

DesktopTable.AllowAutoDeactivate

AllowAutoDeactivate As Boolean

Determines whether the control should be deactivated (on macOS) when the parent window is deactivated. The default is True.

This example sets the property:

Table1.AllowAutoDeactivate = True

DesktopTable.AllowAutoHideScrollbars

AllowAutoHideScrollbars As Boolean

Lets the scrollbars hide themselves when the content fits. With False the scrollbars stay visible even when everything fits. On macOS the system setting for overlay scrollbars decides how they are drawn; the table follows a change of that setting while it is running.

This example lets the scrollbars hide themselves when the content fits:

Table1.AllowAutoHideScrollbars = True

DesktopTable.AllowColumnReordering

AllowColumnReordering As Boolean

Columns can be dragged by their header. Allows reordering columns by dragging the column headers. The user drags a column by its header and an insertion marker shows where it will land. The move is reported by ColumnReordering before and ColumnReordered after it, and the column index changes with it. With frozen columns, reordering is confined to the scrolling middle band.

This example sets the columns can be dragged by their header:

Table1.AllowColumnReordering = True

DesktopTable.AllowExpandableRows

AllowExpandableRows As Boolean

Reserves space for disclosure widgets and enables the hierarchy. Rows added with AddExpandableRow then show a disclosure widget, and every row is indented by its RowDepthAt. Opening and closing a row fires RowExpanded and RowCollapsed.

This example sets the reserves space for disclosure widgets and enables the hierarchy:

Table1.AllowExpandableRows = True

DesktopTable.AllowFocus

AllowFocus As Boolean

If True, the canvas will be included in the Tab order and can accept the focus. The FocusReceived and FocusLost events are called at the appropriate times.

This code enables the AllowFocus property. It is in the Opening event of the control.

Me.AllowFocus = True

DesktopTable.AllowFocusRing

AllowFocusRing As Boolean

If True, the DesktopTable indicates that it has the focus with a ring around its border; if False, the appearance of the object does not change when it has the focus.

Setting this property to True has no effect on Windows or Linux. The default is True.

This code turns AllowFocusRing off.

Me.AllowFocusRing = False

DesktopTable.AllowResizableColumns

AllowResizableColumns As Boolean

Column widths can be dragged in the header. The pointer changes shape over a column divider, and dragging it changes that column's width expression. ColumnResizing fires while dragging, ColumnResized once. A single column can be locked against resizing with ColumnAttributesAt and its UserResizable property.

This example sets the column widths can be dragged in the header:

Table1.AllowResizableColumns = True

DesktopTable.AllowResizableRows

AllowResizableRows As Boolean

Row heights can be dragged. Allows changing the row height with the mouse (handle at the. The user drags the lower edge of a row in the same way a column divider is dragged, which sets that row's RowHeightAt.

This example sets the row heights can be dragged:

Table1.AllowResizableRows = True

DesktopTable.AllowRowAnimation

AllowRowAnimation As Boolean

A row added with AddRow, AddRowAt or AddExpandableRow fades and slides in, and one removed with RemoveRowAt fades and slides out. The default is True.

If you want to improve performance when adding and removing rows, you can set AllowRowAnimation to False.

This example turns the animation off:

Table1.AllowRowAnimation = False

DesktopTable.AllowRowDragging

AllowRowDragging As Boolean

Rows can be dragged out of the table. Allows dragging rows outward (DragRow event).

This example sets the rows can be dragged out of the table:

Table1.AllowRowDragging = True

DesktopTable.AllowRowReordering

AllowRowReordering As Boolean

Rows can be reordered by dragging. Allows reordering rows with the mouse (DragReorderRows event).

This example sets the rows can be reordered by dragging:

Table1.AllowRowReordering = True

DesktopTable.AllowTabs

AllowTabs As Boolean

If True and AllowFocus is True, then pressing Tab triggers the KeyDown event for processing. The default is False.

If False, pressing the Tab key does not trigger the KeyDown event; pressing Tab triggers the FocusLost Event and selects the next object in the window that can accept the focus.

The following turns on AllowTabs.

Me.AllowTabs = True

DesktopTable.AllowTabStop

AllowTabStop As Boolean

If True, the control is in the Tab Order and accepts the focus when the user tabs into it. The default is True. If False, the user cannot tab into it to give it the focus. However, the control can gain the focus by other means, such as the user's clicking on it or by setting the focus in code.

This example removes the control from the Tab Order:

Me.AllowTabStop = False

DesktopTable.AlternatingRowColor

AlternatingRowColor As ColorGroup

Background color of every second row while HasAlternatingRowColors is True. Nil (the default) uses the tint the platform itself uses for lists: on macOS the system's second content background color, on Windows and Linux a nearly transparent black in light mode and a nearly transparent white in dark mode, so whatever lies behind the table still shows through. A table with HasTranslucentBackground uses the transparent mix on macOS too, because the system color is opaque in light mode and would paint the blur away on every second row.

This example tints every second row in the company's pale gray instead of the system color:

Table1.AlternatingRowColor = New ColorGroup(&cF2F4F7, &c2B2F33)
Table1.HasAlternatingRowColors = True

DesktopTable.Bold

Bold As Boolean

Base font style for the whole table. It applies to every cell and to the column headers, unless a cell overrides it with CellBoldAt.

This example sets the base font style for the whole table:

Table1.Bold = True

DesktopTable.BottomInset

BottomInset As Double

Free, non-clickable area after the last row, in points; enlarges the scrollable content. Use it to keep the last row clear of something drawn over the lower edge, or simply to let the content scroll past the end.

This example sets the free, non-clickable area after the last row, in points; enlarges the scrollable content:

Table1.BottomInset = 1.0

DesktopTable.CellContainerPadding

CellContainerPadding As Double

Gap in points between the edge of a cell and the container shown in it, on all four sides. The default is 0.

It applies to every cell of type Container: the container is given what is left of the cell, so a padding of 4 makes it 8 points narrower and 8 points shorter than the cell itself.

This example keeps the containers clear of the grid lines:

Table1.CellContainerPadding = 4

DesktopTable.ColumnCount

ColumnCount As Integer

Number of columns. The original clamps at 256; thanks to virtualization. Raising it appends empty columns, lowering it removes the columns on the right including their cell content. The column count is not limited to 256, and the drawing cost depends on the columns actually visible, not on this number.

This example sets the number of columns:

Table1.ColumnCount = 3

DesktopTable.ColumnWidths

ColumnWidths As String

Comma-separated width expressions (points, * shares, or percentages). Each value applies to the column at the same position: a point value (120), a percentage (25%) or a share of the remaining width (*, 2*). An unusable expression raises an UnsupportedFormatException. Individual columns can be set through ColumnAttributesAt instead.

This example sets the comma-separated width expressions:

Table1.ColumnWidths = "120,*,80"

DesktopTable.ContainerCacheSize

ContainerCacheSize As Integer

How many containers the table keeps for reuse beyond the ones in use. The default is 24.

A cell that scrolls out of view hands its container to this pool, and ReusableContainer gives it to the next cell that asks for one of the same kind. 0 switches the reuse off: every cell then builds its own container, and ContainerRemovedAt reports each one the table has finished with.

This example switches the reuse off:

Table1.ContainerCacheSize = 0

DesktopTable.Content

Content As String

Whole content - rows separated by EndOfLine, cells by Tab. Reading it returns the whole table, writing it replaces every row. It is the text form the inline editor and CellTextAt also use, so a value containing a Tab or a line break changes the shape of the result.

This example sets the whole content - rows separated by EndOfLine, cells by Tab:

Table1.Content = "Anna" + Chr(9) + "Berlin"

DesktopTable.DataSource

DataSource As TableDataSource

Virtual data source; Nil selects in-memory mode. With a data source assigned the table keeps no rows of its own: it asks the source for RowCount and for the text of the cells it is about to draw. Everything else - selection, row heights, cell styles, tags - stays with the table, kept per row index. After the data behind the source changed, call ReloadFromDataSource.

This example sets the virtual data source; Nil selects in-memory mode:

Table1.DataSource = myTableDataSource

DesktopTable.DefaultRowHeight

DefaultRowHeight As Integer

Row height in points; -1 derives it from the font. It applies to every row that has no RowHeightAt of its own. Leaving all rows at the default is also the fastest case: the offset of a row is then a single multiplication, with no per-row data at all.

This example sets the row height in points; -1 derives it from the font:

Table1.DefaultRowHeight = 24

DesktopTable.DropIndicatorVisible

DropIndicatorVisible As Boolean

Shows the insertion indicator during a drop. It only changes what is drawn. The drag events fire either way.

This example shows the insertion indicator during a drop:

Table1.DropIndicatorVisible = True

DesktopTable.Enabled

Enabled As Boolean

Determines if the control should be enabled when the owning window is opened.

A disabled control cannot be clicked and cannot receive the focus.

This example disables the control.

Me.Enabled = False

DesktopTable.FontName

FontName As String

Base font. It applies to every cell and to the column headers. Besides an installed font you can use the metafonts System and SmallSystem.

This example sets the base font:

Table1.FontName = "Helvetica"

DesktopTable.FontSize

FontSize As Single

Base font size. A value of 0 uses the size that suits the platform. The row height follows the font when DefaultRowHeight is left at -1.

This example sets the base font size:

Table1.FontSize = 14

DesktopTable.FontUnit

FontUnit As FontUnits

Unit for FontSize. It says how FontSize is measured, points by default.

This example sets the unit for FontSize:

Table1.FontUnit = FontUnit

DesktopTable.FrozenColumns

FrozenColumns As DesktopTableFrozenColumns

Always the same instance; set .Left / .Right to pin columns. Set its Left and Right to pin that many columns to the edges while the columns in between scroll. In a right-to-left layout the leading edge is on the right.

This property is read-only.

This example reads the always the same instance; set .Left / .Right to pin columns:

Var value As DesktopTableFrozenColumns = Table1.FrozenColumns

DesktopTable.FrozenRows

FrozenRows As DesktopTableFrozenRows

Always the same instance; set .Top / .Bottom to pin rows. Set its Top and Bottom to pin that many rows below the header and above the lower edge, which is how a totals row is kept in view.

This property is read-only.

This example reads the always the same instance; set .Top / .Bottom to pin rows:

Var value As DesktopTableFrozenRows = Table1.FrozenRows

DesktopTable.GridColor

GridColor As ColorGroup

Body grid line color; Nil (the default) uses the theme-appropriate color. Does not affect the header's own column dividers or bottom border.

This example sets the body grid line color; Nil (the default) uses the theme-appropriate color:

Table1.GridColor = New ColorGroup(&cD93025, &cC5372C)

DesktopTable.GridLineStyle

GridLineStyle As DesktopTable.GridLineStyles

Which grid lines are drawn. Grid lines are drawn between cells, never through a merged cell, and they follow the column widths, so a hidden column adds no line of its own.

This example sets the which grid lines are drawn:

Table1.GridLineStyle = DesktopTable.GridLineStyles.Both

DesktopTable.Handle

Handle As Ptr

Returns a handle to the control.

This property is read-only.

For interfacing with Mac APIs using Declares, DesktopControl.Handle returns NSViews (except for DesktopToolbar).

On Windows returns the HWND of the control.

On Linux it returns a GtkWidget.

The following gets a handle to the control.

Var p As Ptr = Me.Handle

DesktopTable.HasAlternatingRowColors

HasAlternatingRowColors As Boolean

Draws every second row in AlternatingRowColor, which makes a wide row easier to follow across its columns. The default is False. Row 0 keeps the plain background, the stripes cover the full width of a row including frozen columns, the area past the last column and the action strips of a swiped row, and the pattern keeps running below the last row.

The stripe is drawn underneath everything else the row paints, so a PaintCellBackground handler that returns True, the selection highlight and the grid lines all keep their usual appearance.

This example turns the stripes on for a table with many columns:

Table1.HasAlternatingRowColors = True

DesktopTable.HasBorder

HasBorder As Boolean

Draws the control border. The border is drawn by the platform, so it matches other framed controls.

This example draws the control border:

Table1.HasBorder = True

DesktopTable.HasColumnHeader

HasColumnHeader As Boolean

Shows the column header row. Turn the translucent header on/off together with the header. The header shows the text of ColumnHeaderAt, is drawn in the platform theme and is where the user clicks to sort, drags to resize and drags to reorder columns.

This example shows the column header row:

Table1.HasColumnHeader = True

DesktopTable.HasHorizontalScrollbar

HasHorizontalScrollbar As Boolean

Enables horizontal scrolling. The scrollbar only appears when the columns are wider than the table. The position is available as ScrollPositionX.

This example sets the enables horizontal scrolling:

Table1.HasHorizontalScrollbar = True

DesktopTable.HasTranslucentBackground

HasTranslucentBackground As Boolean

macOS only - places an NSVisualEffectView behind the table. The inline editor of a TextField or TextArea cell is then drawn without a background of its own, so the translucency shows through while a cell is being edited.

This example sets the macOS only - places an NSVisualEffectView behind the table:

Table1.HasTranslucentBackground = True

DesktopTable.HasTranslucentHeader

HasTranslucentHeader As Boolean

macOS only - translucent header; rows glide blurred beneath it.

This example sets the macOS only - translucent header; rows glide blurred beneath it:

Table1.HasTranslucentHeader = True

DesktopTable.HasVerticalScrollbar

HasVerticalScrollbar As Boolean

Enables vertical scrolling. The position is available as ScrollPosition.

This example sets the enables vertical scrolling:

Table1.HasVerticalScrollbar = True

DesktopTable.HeaderHeight

HeaderHeight As Integer

Header height in points. Height of the header row in points. It is the height of the header row only; the rows below are unaffected.

This example sets the header height in points:

Table1.HeaderHeight = 28

DesktopTable.HeadingIndex

HeadingIndex As Integer

Sets the sort column and the sort indicator in the header row. It is the column the indicator is shown for. The sort itself runs when Sort is called or the user clicks a sortable header.

This example sets the sort column and the sort indicator in the header row:

Table1.HeadingIndex = 0

DesktopTable.Height

Height As Integer

The height (in points) of the control.

This example sets the height of the control to 100:

Me.Height = 100

DesktopTable.Index

Index As Integer

If the control is used in a control set, this specifies the control's index in the set.

This example sets the property:

Table1.Index = 0

DesktopTable.InitialValue

InitialValue As String

Design-time content, applied when you start your app. Rows are separated by line breaks and cells by Tab. It is applied while the control opens, so code in the Opening event runs on top of it.

This example sets the design-time content, applied in Opening:

Table1.InitialValue = "Name" + Chr(9) + "City"

DesktopTable.Italic

Italic As Boolean

Base font style. It applies to every cell and to the column headers, unless a cell overrides it with CellItalicAt.

This example sets the base font style:

Table1.Italic = True

DesktopTable.LastAddedColumnIndex

LastAddedColumnIndex As Integer

Index of the most recently added column, -1 if none. Use it to address a column right after adding it, instead of counting positions yourself.

This property is read-only.

This example reads the index of the most recently added column, -1 if none:

Var value As Integer = Table1.LastAddedColumnIndex

DesktopTable.LastAddedRowIndex

LastAddedRowIndex As Integer

Index of the most recently added row, NoSelection if none. Use it to fill the other cells of a row right after adding it.

This property is read-only.

This example reads the index of the most recently added row, NoSelection if none:

Var value As Integer = Table1.LastAddedRowIndex

DesktopTable.LastColumnIndex

LastColumnIndex As Integer

Index of the last column. It is one less than ColumnCount, and -1 while the table has no columns.

This property is read-only.

This example reads the index of the last column:

Var value As Integer = Table1.LastColumnIndex

DesktopTable.LastRowIndex

LastRowIndex As Integer

Index of the last row. It is one less than RowCount, and -1 while the table is empty.

This property is read-only.

This example reads the index of the last row:

Var value As Integer = Table1.LastRowIndex

DesktopTable.Left

Left As Integer

The distance from the left side of the control to the left side of its containing window or container.

The following example moves the control 100 points from the left side of the window:

Me.Left = 150

DesktopTable.LockBottom

LockBottom As Boolean

Determines whether the bottom edge of the control should stay at a set distance from the bottom edge of the parent control, if there is one, or the owning window.

This property can be set in the control's Inspector. The following example sets it in code.

Me.LockBottom = True

DesktopTable.LockLeft

LockLeft As Boolean

Determines whether the left edge of the control should stay at a set distance from the left edge of the parent control, if there is one, or the owning window.

LockLeft and Locktop default to True when you add a new control to a window. Existing controls will be altered only if LockRight and/or LockBottom are not set. LockLeft has no effect unless LockRight is True.

This property can be set in the control's Inspector. The following example sets it in code.

Me.LockLeft = True

DesktopTable.LockRight

LockRight As Boolean

Determines whether the right edge of the control should stay at a set distance from the right edge of the parent control, if there is one, or the owning window.

This property can be set in the control's Inspector. The following example sets it in code.

Me.LockRight = True

DesktopTable.LockTop

LockTop As Boolean

Determines whether the top edge of the control should stay at a set distance from the top edge of the parent control, if there is one, or the owning window.

LockTop and LockLeft default to True when you add a control to a window. Existing controls will be altered only if LockRight and/or LockBottom are not set. LockTop has no effect unless LockBottom is True.

This property can be set in the control's Inspector. The following example sets it in code.

Me.LockTop = True

DesktopTable.MouseCursor

MouseCursor As MouseCursor

The cursor to be displayed while the mouse is within the control and both the DesktopApplication and DesktopWindow class's MouseCursor properties are Nil.

If the DesktopApplication class's MouseCursor property is not Nil or the DesktopWindow's MouseCursor property is not Nil, then any control's MouseCursor property is ignored. You can use a cursor stored in the Cursors module. On macOS, you can also obtain a MouseCursor from a resource file.

This line in the Opening event of the control sets the default cursor to the finger pointer.

Me.MouseCursor = System.Cursors.FingerPointer

DesktopTable.Name

Name As String

The name of the control. Set the name of the control in the Inspector.

This property is read-only.

This example reads the property:

Var value As String = Table1.Name

DesktopTable.PanelIndex

PanelIndex As Integer

If the control has been placed on a DesktopTabPanel or DesktopPagePanel control, this is the panel (page/tab) that the control is on. If the control is not on a panel, it returns -1.

The first panel is numbered zero. If the control has been placed on a panel of a DesktopTabPanel or DesktopPagePanel control, it returns the panel number. If the control is not on a DesktopPagePanel or DesktopTabPanel, it returns -1. If you change the PanelIndex to a nonexistent panel, the control will disappear until you give it a PanelIndex value that corresponds to a panel that exists.

If you are looking to change the currently selected panel (page/tab), use DesktopPagePanel.SelectedPanelIndex.

This code displays the panel index of the control that is on the page.

MessageBox(Me.SelectedPanelIndex.ToString)

DesktopTable.Parent

Parent As Object

Used to get and set the control's parent control or window.

If the control is on the window, the Parent will be the Window. If the control is on the container, the Parent will be the container. If the control is completed enclosed by another control, the Parent will be that control.

If you do not want the enclosing control to be the parent, set the Parent property of that control to Nil to make it the Window.

If the parent control is somehow in another window, an InvalidParentException will occur.

The following example sets the parent of the control to the window.

Me.Parent = Nil

DesktopTable.RequiresSelection

RequiresSelection As Boolean

Keeps at least one row selected. True prevents the user from clearing the last selection. With True a click on empty space or on the selected row no longer clears the selection. It does not select a row by itself; that is up to your code.

This example keeps at least one row selected:

Table1.RequiresSelection = True

DesktopTable.RowCount

RowCount As Integer

Number of rows. In DataSource mode it is what the source reports, otherwise the number of rows the table holds itself.

This property is read-only.

This example reads the number of rows:

Var value As Integer = Table1.RowCount

DesktopTable.RowHeight

RowHeight As Integer

Resolved default row height in points. It is the height DefaultRowHeight resolves to, so it is a real measurement even when the height follows the font.

This property is read-only.

This example reads the resolved default row height in points:

Var value As Integer = Table1.RowHeight

DesktopTable.RowSelectionType

RowSelectionType As DesktopTable.RowSelectionTypes

Single or multiple selection. Single reduces a multiple selection to the bottom-most row. It decides how clicking, dragging and the arrow keys change the selection. Switching to Single while several rows are selected keeps the bottom-most one.

This example sets the single or multiple selection:

Table1.RowSelectionType = DesktopTable.RowSelectionTypes.Multiple

DesktopTable.Scope

Scope As Integer

Used to determine whether access to the control is Public (0) or Private (2). The default is Public.

This property is read-only.

Note

This is a designtime-only property and thus can only be set in the Inspector and is not accessible via code.

If the Scope of a control is set to Private, it cannot be accessed from outside its parent window.

This example reads the property:

Var value As Integer = Table1.Scope

DesktopTable.ScrollPosition

ScrollPosition As Integer

Index of the top-most visible row. Assigning it scrolls so that row becomes the top-most one, which is the same movement the vertical scrollbar makes.

This example sets the index of the top-most visible row:

Table1.ScrollPosition = 0

DesktopTable.ScrollPositionX

ScrollPositionX As Integer

Horizontal scroll offset in points. Horizontal scroll position in points. It is measured in points, not in columns, so it can stop in the middle of a column.

This example sets the horizontal scroll offset in points:

Table1.ScrollPositionX = 0

DesktopTable.SelectedRowCount

SelectedRowCount As Integer

Number of selected rows. It is kept as rows are selected and deselected, so it costs nothing to read even with many rows.

This property is read-only.

This example reads the number of selected rows:

Var value As Integer = Table1.SelectedRowCount

DesktopTable.SelectedRowIndex

SelectedRowIndex As Integer

Smallest selected row index, or NoSelection. With several rows selected it is the topmost of them; assigning it selects that single row. Use RowSelectedAt to read or set the state of a particular row.

This example sets the smallest selected row index, or NoSelection:

Table1.SelectedRowIndex = 0

DesktopTable.SelectedRowText

SelectedRowText As String

Text of column 0 of the selected row. Text (column 0) of the selected row. It is a shortcut for the first column of the selected row and follows the same rule as SelectedRowIndex when several rows are selected.

This property is read-only.

This example reads the text of column 0 of the selected row:

Var value As String = Table1.SelectedRowText

DesktopTable.SortingColumn

SortingColumn As Integer

Column used by Sort; -1 for none. Does not set a header indicator. It is the column Sort uses, together with the direction from ColumnSortDirectionAt. Set HeadingIndex as well to show the indicator in the header.

This example sets the column used by Sort; -1 for none:

Table1.SortingColumn = 0

DesktopTable.TabIndex

TabIndex As Integer

The control's position in the Tab Order. The control with whose TabIndex is 0 will get the focus first.

On macOS, only controls where you enter data from the keyboard typically get the focus. In order to manually set focus to controls that don't allow keyboard entry, go to System Preferences, click on the Keyboard icon then on the Shortcuts tab and then check the Use keyboard navigation to move focus between controls checkbox.

This example sets the control's TabIndex.

Me.TabIndex = 2

DesktopTable.Tooltip

Tooltip As String

Text of help message displayed as a Windows or Linux "tooltip" or macOS help tag.

The tip/tag is displayed when the user hovers the mouse cursor over the control.

This example adds a tooltip to a control:

Me.Tooltip = "Click to bark."

DesktopTable.Top

Top As Integer

The distance from the top of the control to the top of its containing window or container.

This example sets the top of the control to 140 points from the top of the window:

Me.Top = 140

DesktopTable.TopInset

TopInset As Double

Free, non-clickable area before the first row, in points. Use it to keep the first row clear of something drawn over the upper edge.

This example sets the free, non-clickable area before the first row, in points:

Table1.TopInset = 1.0

DesktopTable.Transparent

Transparent As Boolean

Determines whether the control is transparent on Windows. The default is False. Has no effect on macOS or Linux.

Transparent controls draw more slowly and use more memory in order to cache the background. Unless you absolutely require transparency, leave this set to False.

For projects that were created prior to 2018r1, this property defaults to True to emulate previous behavior. Consider changing it to False to improve performance if you do not require transparency.

This example sets the property:

Table1.Transparent = True

DesktopTable.Underline

Underline As Boolean

Base font style. It applies to every cell and to the column headers, unless a cell overrides it with CellUnderlineAt.

This example sets the base font style:

Table1.Underline = True

DesktopTable.Visible

Visible As Boolean

Determines whether the control is visible when its owning window is opened. The default is True: the control is visible.

The following code makes the control invisible:

Me.Visible = False

DesktopTable.Width

Width As Integer

The width (in points) of the control.

The following example resizes the control:

Me.Width = 200

DesktopTable.Window

Window As DesktopWindow

The control's parent window.

This property is read-only.

This code gets the parent window's Title property.

MessageBox(Me.Window.Title)

Method descriptions


DesktopTable.AcceptFileDrop

AcceptFileDrop(FileType As String)

Permits documents of type FileType to be dropped on the control. FileType must be a file type that you defined in via the FileType class or the File Type Sets Editor.

This code in the Opening event makes it possible for the user to drop either a picture or a file that is a jpeg image. The File Type Sets editor was used to define the “image/jpeg” file type. It is one of the “Common File Types” that is available in the editor.

Me.AcceptPictureDrop
Me.AcceptFileDrop("image/jpeg")

To restrict file drops to specific file types on macOS, in addition to creating a File Type (as a project item or via code) to define the file extension, you must also use the DragEnter event:

For example, to restrict drops to folders only:

If Not obj.FolderItem.IsFolder Then Return True

To restrict drops to a files with a specific extension:

If Not obj.FolderItem.Extension <> ".my_extension" Then Return True

DesktopTable.AcceptPictureDrop

AcceptPictureDrop

Permits Picture objects to be dropped on the control. This applies to pictures dragged from another control or application, not to image files dragged from the file system. To accept image files, use AcceptFileDrop instead.

If a control should accept pictures in a drag and drop, then AcceptPictureDrop needs to be called prior to the drop. Typically, it is in the Opening event of the control itself. For example, the line:

Me.AcceptPictureDrop

in the Opening event of the control that will receive the dragged pictures is needed. When the picture is dropped, the DropObject event is called and this is where you will put your code to handle the drop.

Opening Event:

Me.AcceptPictureDrop

DropObject Event:

If obj.PictureAvailable Then
  Me.RowImageAt(0) = obj.Picture
End If

Note

To prevent further drops after having called AcceptPictureDrop, return True in the DragOver event.


DesktopTable.AcceptRawDataDrop

AcceptRawDataDrop(Type As String)

Permits data (of the Type specified) to be dropped on the control.

The following specfies a generic file type defined in the File Type Sets editor.

Me.AcceptRawDataDrop("????")

DesktopTable.AcceptTextDrop

AcceptTextDrop

Permits text to be dropped on the control.

This line in the Opening event of a control that can accept dragged text.

Me.AcceptTextDrop

DesktopTable.AddAllExpandableRows

AddAllExpandableRows(rows As RowSet)

Appends all database rows as expandable rows and expands the column count if needed. Like AddAllRows, except that every row gets a disclosure widget - see AllowExpandableRows, and RowExpanded, which fills in the children.

This example appends all database rows as expandable rows:

Table1.AddAllExpandableRows(rows)

AddAllExpandableRows(items() As String)

Appends an expandable row (column 0) for each array element.

This example appends an expandable row for each array element:

Var items() As String = Array("Anna", "Berlin")
Table1.AddAllExpandableRows(items)

AddAllExpandableRows(items(,) As String)

Appends one expandable row per row of the array: items(row, column). Every one of them gets a disclosure widget; RowExpanded fills in its children. The column count grows when a row carries more values than the table has columns, the way the RowSet overload does.

This example appends two expandable rows of two columns each:

Var items(1, 1) As String

items(0, 0) = "Anna"
items(0, 1) = "Berlin"
items(1, 0) = "Bodo"
items(1, 1) = "Atlanta"

Table1.AddAllExpandableRows(items)

AddAllExpandableRows(ParamArray item As String)

Appends an expandable row (column 0) for each passed value.

This example appends an expandable row for each passed value:

Table1.AddAllExpandableRows("Anna", "Berlin")

AddAllExpandableRows(count As Integer)

Appends count empty rows - no text in any column. Every one of them gets a disclosure widget; RowExpanded fills in its children.

This example appends ten empty rows:

Table1.AddAllExpandableRows(10)

DesktopTable.AddAllRows

AddAllRows(rows As RowSet)

Appends all database rows and expands the column count if needed.

This example appends all database rows and expands the column count if needed:

Table1.AddAllRows(rows)

AddAllRows(items() As String)

Appends a new row (column 0) for each array element.

This example appends a new row (column 0) for each array element:

Var items() As String = Array("Anna", "Berlin")
Table1.AddAllRows(items)

AddAllRows(items(,) As String)

Appends one row per row of the array: items(row, column), as DesktopListBox does. The column count grows when a row carries more values than the table has columns, the way the RowSet overload does.

This example appends two rows of two columns each:

Var items(1, 1) As String

items(0, 0) = "Anna"
items(0, 1) = "Berlin"
items(1, 0) = "Bodo"
items(1, 1) = "Atlanta"

Table1.AddAllRows(items)

AddAllRows(ParamArray item As String)

Appends a new row (column 0) for each passed value.

This example appends a new row (column 0) for each passed value:

Table1.AddAllRows("Anna", "Berlin")

AddAllRows(count As Integer)

Appends count empty rows - no text in any column. For a table whose cells are filled afterwards through CellTextAt, drawn in PaintCellText, or are containers.

This example appends ten empty rows:

Table1.AddAllRows(10)

DesktopTable.AddColumn

AddColumn(header As String = "")

Appends a column on the right. The new column is empty in every row and its width follows the current ColumnWidths.

This example appends a column on the right:

Table1.AddColumn

DesktopTable.AddColumnAt

AddColumnAt(index As Integer, header As String = "")

Inserts a column; an index >= ColumnCount appends. The cells of every row move along with their column, so existing content stays with the column it belonged to. The sorting column and the heading index follow the shift as well.

This example inserts a column; an index >= ColumnCount appends:

Table1.AddColumnAt(0)

DesktopTable.AddExpandableRow

AddExpandableRow(items() As String)

Appends an expandable row; the array fills consecutive columns. Within the RowExpanded event the row is inserted as a child of a row currently being expanded.

If you want to improve performance when adding and removing rows, you can set AllowRowAnimation to False.

This example appends an expandable row; the array fills consecutive columns:

Var items() As String = Array("Anna", "Berlin")
Table1.AddExpandableRow(items)

AddExpandableRow(ParamArray item As String)

Appends an expandable row; one or more parameters fill consecutive columns. Within the RowExpanded event the row is inserted as a child of a row currently being expanded.

If you want to improve performance when adding and removing rows, you can set AllowRowAnimation to False.

This example appends an expandable row; one or more parameters fill consecutive columns:

Table1.AddExpandableRow("Anna", "Berlin")

DesktopTable.AddExpandableRowAt

AddExpandableRowAt(row As Integer, text As String, depth As Integer = 0)

Inserts an expandable row at a position and depth. The row shows a disclosure widget once AllowExpandableRows is on. Its children are usually added in the RowExpanded event, not in advance.

If you want to improve performance when adding and removing rows, you can set AllowRowAnimation to False.

This example inserts an expandable row at a position and depth:

Table1.AddExpandableRowAt(0, "Berlin")

DesktopTable.AddListSelectionNotificationReceiver

AddListSelectionNotificationReceiver(receiver As ListSelectionNotificationReceiver)

Registers a ListSelectionNotificationReceiver. The receiver is told about every selection change, which is how a database-bound control follows the table without a selection event of its own.

This example registers a receiver that follows the selection:

Table1.AddListSelectionNotificationReceiver(receiver)

DesktopTable.AddRow

AddRow(items() As String)

Appends a new row; the array fills consecutive columns.

If you want to improve performance when adding and removing rows, you can set AllowRowAnimation to False.

AddRow(ParamArray item As String)

Appends a new row; multiple parameters fill consecutive columns.

If you want to improve performance when adding and removing rows, you can set AllowRowAnimation to False.

This example adds a row in one go and another one cell by cell:

Table1.AddRow("Anna", "Berlin")

' A row added one cell at a time
Table1.AddRow("")
Table1.CellTextAt(Table1.LastAddedRowIndex, 0) = "Bob"

DesktopTable.AddRowAt

AddRowAt(row As Integer, text As String, depth As Integer = 0)

Inserts a row at a position and hierarchy depth. An index beyond the last row appends. depth places the row inside the hierarchy below its parent.

If you want to improve performance when adding and removing rows, you can set AllowRowAnimation to False.

This example inserts a row at a position and hierarchy depth:

Table1.AddRowAt(0, "Berlin")

DesktopTable.CellAlignmentAt

CellAlignmentAt(row As Integer, column As Integer) As DesktopTable.Alignments

Alignment of a cell.

This example reads the alignment of a cell:

Var value As DesktopTable.Alignments = Table1.CellAlignmentAt(0, 1)

CellAlignmentAt(row As Integer, column As Integer, Assigns value As DesktopTable.Alignments)

Sets the alignment of a cell (AllRows or AllColumns).

This example sets the alignment of a cell:

Table1.CellAlignmentAt(0, 1) = DesktopTable.Alignments.Right

DesktopTable.CellAlignmentOffsetAt

CellAlignmentOffsetAt(row As Integer, column As Integer) As Integer

Distance of the alignment point from the right cell edge in points.

This example reads the distance of the alignment point from the right cell edge in points:

Var value As Integer = Table1.CellAlignmentOffsetAt(0, 1)

CellAlignmentOffsetAt(row As Integer, column As Integer, Assigns value As Integer)

Sets the alignment offset of a cell (AllRows or AllColumns). It applies to that cell only: the offset of its column, and with it the other cells and the heading, stays as it is, the same as in a list box. In a checkbox cell (CellTypes.CheckBox) the checkbox moves along with the text, by the same distance.

This example moves the text of a single cell 50 points to the right:

Table1.CellAlignmentOffsetAt(0, 1) = 50

DesktopTable.CellBoldAt

CellBoldAt(row As Integer, column As Integer) As Boolean

Bold style of a cell.

This example reads the bold style of a cell:

Var value As Boolean = Table1.CellBoldAt(0, 1)

CellBoldAt(row As Integer, column As Integer, Assigns value As Boolean)

Sets the bold style of a cell (AllRows or AllColumns).

This example sets the bold style of a cell:

Table1.CellBoldAt(0, 1) = True

DesktopTable.CellBorderColorAt

CellBorderColorAt(row As Integer, column As Integer) As ColorGroup

Border color of a cell.

This example reads the border color of a cell:

Var value As ColorGroup = Table1.CellBorderColorAt(0, 1)

CellBorderColorAt(row As Integer, column As Integer, Assigns value As ColorGroup)

Sets the border color of a cell (AllRows or AllColumns).

This example sets the border color of a cell:

Table1.CellBorderColorAt(0, 1) = New ColorGroup(&cD93025, &cC5372C)

DesktopTable.CellBoundsAt

CellBoundsAt(row As Integer, column As Integer) As Rect

The cell's rectangle in the table's own coordinates - scroll, frozen bands and RTL applied; merge anchors report the merged rectangle.

This example places a control of your own over a cell:

' Place your own control over a cell
Var r As Rect = Table1.CellBoundsAt(2, 1)

ProgressBar1.Left = Table1.Left + r.Left
ProgressBar1.Top = Table1.Top + r.Top
ProgressBar1.Width = r.Width

DesktopTable.CellCheckBoxEnabledAt

CellCheckBoxEnabledAt(row As Integer, column As Integer) As Boolean

Whether a checkbox cell is clickable (default: True).

This example reads whether a checkbox cell is clickable:

Var value As Boolean = Table1.CellCheckBoxEnabledAt(0, 1)

CellCheckBoxEnabledAt(row As Integer, column As Integer, Assigns value As Boolean)

Enables/disables a checkbox cell (AllRows or AllColumns).

This example sets the enables/disables a checkbox cell:

Table1.CellCheckBoxEnabledAt(0, 1) = True

DesktopTable.CellCheckBoxStateAt

CellCheckBoxStateAt(row As Integer, column As Integer) As DesktopCheckBox.VisualStates

State (Checked/Unchecked/Indeterminate) of a checkbox cell.

This example reads the state (Checked/Unchecked/Indeterminate) of a checkbox cell:

Var value As DesktopCheckBox.VisualStates = Table1.CellCheckBoxStateAt(0, 1)

CellCheckBoxStateAt(row As Integer, column As Integer, Assigns value As DesktopCheckBox.VisualStates)

Sets the state of a checkbox cell (AllRows or AllColumns).

This example sets the state of a checkbox cell:

Table1.CellCheckBoxStateAt(0, 1) = DesktopCheckBox.VisualStates.Checked

DesktopTable.CellCheckBoxValueAt

CellCheckBoxValueAt(row As Integer, column As Integer) As Boolean

Value of a checkbox cell.

This example reads the value of a checkbox cell:

Var value As Boolean = Table1.CellCheckBoxValueAt(0, 1)

CellCheckBoxValueAt(row As Integer, column As Integer, Assigns value As Boolean)

Sets the value of a checkbox cell.

This example sets the value of a checkbox cell:

Table1.CellCheckBoxValueAt(0, 1) = True

DesktopTable.CellIsMerged

CellIsMerged(row As Integer, column As Integer) As Boolean

Whether a cell belongs to a merge (anchor or covered). It is True for the anchor as well as for every cell the merge covers. CellMergeBounds reports the extent.

This example reads whether a cell belongs to a merge:

Var value As Boolean = Table1.CellIsMerged(0, 1)

DesktopTable.CellItalicAt

CellItalicAt(row As Integer, column As Integer) As Boolean

Italic style of a cell.

This example reads the italic style of a cell:

Var value As Boolean = Table1.CellItalicAt(0, 1)

CellItalicAt(row As Integer, column As Integer, Assigns value As Boolean)

Sets the italic style of a cell (AllRows or AllColumns).

This example sets the italic style of a cell:

Table1.CellItalicAt(0, 1) = True

DesktopTable.CellMergeBounds

CellMergeBounds(row As Integer, column As Integer, ByRef anchorRow As Integer, ByRef anchorColumn As Integer, ByRef rowSpan As Integer, ByRef columnSpan As Integer) As Boolean

Anchor and span of the merge covering the cell; False if unmerged, in which case the ByRef values are left untouched.

This example reads the anchor and span of the merge covering the cell; False if unmerged, in which case the ByRef values are left untouched:

Var value As Boolean = Table1.CellMergeBounds(0, 1, anchorRow, anchorColumn, rowSpan, columnSpan)

DesktopTable.CellProgressBarMaximumValueAt

CellProgressBarMaximumValueAt(row As Integer, column As Integer) As Double

Upper bound of a progress bar cell (default: 100).

This example reads the upper bound of a progress bar cell:

Var value As Double = Table1.CellProgressBarMaximumValueAt(0, 1)

CellProgressBarMaximumValueAt(row As Integer, column As Integer, Assigns value As Double)

Sets the upper bound of a progress bar cell (AllRows or AllColumns). Unlike DesktopProgressBar a value <= 0 does NOT switch to an indeterminate bar (a cell has no animation) - the bar simply stays empty.

This example sets the upper bound of a progress bar cell:

Table1.CellProgressBarMaximumValueAt(0, 1) = 1.0

DesktopTable.CellProgressBarValueAt

CellProgressBarValueAt(row As Integer, column As Integer) As Double

Current value of a progress bar cell.

This example reads the current value of a progress bar cell:

Var value As Double = Table1.CellProgressBarValueAt(0, 1)

CellProgressBarValueAt(row As Integer, column As Integer, Assigns value As Double)

Sets the value of a progress bar cell (AllRows or AllColumns). The value is stored unchanged; only the drawing clamps it to 0 .. MaximumValue.

This example sets the value of a progress bar cell:

Table1.CellProgressBarValueAt(0, 1) = 1.0

DesktopTable.CellTagAt

CellTagAt(row As Integer, column As Integer) As Variant

Invisible companion value of a cell.

This example reads the invisible companion value of a cell:

Var value As Variant = Table1.CellTagAt(0, 1)

CellTagAt(row As Integer, column As Integer, Assigns value As Variant)

Sets the companion value of a cell (AllRows or AllColumns).

This example sets the companion value of a cell:

Table1.CellTagAt(0, 1) = "myTag"

DesktopTable.CellTextAt

CellTextAt(row As Integer, column As Integer = 0) As String

Text of a cell. row = AllRows returns the whole column (EndOfLine-separated), column = AllColumns the whole row (tab-separated).

CellTextAt(row As Integer, column As Integer = 0, Assigns value As String)

Sets the text of a cell. row = AllRows distributes an EndOfLine-separated value across the column, column = AllColumns a tab-separated value across the row.

This example reads and writes a cell, and reads a whole row:

Var name As String = Table1.CellTextAt(3, 0)
Table1.CellTextAt(3, 1) = "Hamburg"

' row = -1 returns a whole column, column = -1 a whole row (Tab-separated)
Var wholeRow As String = Table1.CellTextAt(3, -1)

DesktopTable.CellTooltipAt

CellTooltipAt(row As Integer, column As Integer) As String

Tooltip of a cell.

This example reads the tooltip of a cell:

Var value As String = Table1.CellTooltipAt(0, 1)

CellTooltipAt(row As Integer, column As Integer, Assigns value As String)

Sets the tooltip of a cell (AllRows or AllColumns).

This example sets the tooltip of a cell:

Table1.CellTooltipAt(0, 1) = "Berlin"

DesktopTable.CellTypeAt

CellTypeAt(row As Integer, column As Integer) As DesktopTable.CellTypes

Type of a cell; Default means: the column type applies.

This example reads the type of a cell; Default means: the column type applies:

Var value As DesktopTable.CellTypes = Table1.CellTypeAt(0, 1)

CellTypeAt(row As Integer, column As Integer, Assigns value As DesktopTable.CellTypes)

Sets the type of a cell, overriding the column type (AllRows or AllColumns).

This example sets the type of a cell, overriding the column type:

Table1.CellTypeAt(0, 1) = DesktopTable.CellTypes.CheckBox

DesktopTable.CellUnderlineAt

CellUnderlineAt(row As Integer, column As Integer) As Boolean

Underline style of a cell.

This example reads the underline style of a cell:

Var value As Boolean = Table1.CellUnderlineAt(0, 1)

CellUnderlineAt(row As Integer, column As Integer, Assigns value As Boolean)

Sets the underline style of a cell (AllRows or AllColumns).

This example sets the underline style of a cell:

Table1.CellUnderlineAt(0, 1) = True

DesktopTable.Close

Close

Closes a control.

Closing a control permanently removes the control from memory, making it impossible to access. You can close both non-indexed controls and indexed controls. When you close an indexed control, the indexes for the remaining controls will shift downward so that the indexes start with zero and are consecutive.

The following code closes the control. When this is executed from a visible control, the control disappears from the window.

Me.Close

DesktopTable.CollapseAllRows

CollapseAllRows

Collapses every expanded row, top to bottom. Collapsing a row removes its whole subtree in one step (see CollapseRowInternal), so descendants are never visited individually - a single forward pass over the shrinking row list is enough, and DataRowCount is re-read every iteration to reflect that shrink.

This example collapses every expanded row, top to bottom:

Table1.CollapseAllRows

DesktopTable.ColumnAlignmentAt

ColumnAlignmentAt(column As Integer) As DesktopTable.Alignments

Alignment of a column.

This example reads the alignment of a column:

Var value As DesktopTable.Alignments = Table1.ColumnAlignmentAt(1)

ColumnAlignmentAt(column As Integer, Assigns value As DesktopTable.Alignments)

Sets the alignment of a column (AllColumns).

This example sets the alignment of a column:

Table1.ColumnAlignmentAt(1) = DesktopTable.Alignments.Right

DesktopTable.ColumnAlignmentOffsetAt

ColumnAlignmentOffsetAt(column As Integer) As Integer

Alignment offset of a column in points.

This example reads the alignment offset of a column in points:

Var value As Integer = Table1.ColumnAlignmentOffsetAt(1)

ColumnAlignmentOffsetAt(column As Integer, Assigns value As Integer)

Sets the alignment offset of a column (AllColumns). In checkbox cells (CellTypes.CheckBox) the checkbox moves along with the text, by the same distance.

This example sets the alignment offset of a column:

Table1.ColumnAlignmentOffsetAt(1) = 0

DesktopTable.ColumnAttributesAt

ColumnAttributesAt(column As Integer) As DesktopTableColumn

Returns the column attribute object; AllColumns affects all columns.

This example returns the column attribute object; AllColumns affects all columns:

Var value As DesktopTableColumn = Table1.ColumnAttributesAt(1)

ColumnAttributesAt(column As Integer, Assigns value As DesktopTableColumn)

Applies the attributes of the passed object to the *column*(s).

This example sets the applies the attributes of the passed object to the column:

Table1.ColumnAttributesAt(1) = myColumn

DesktopTable.ColumnFromXY

ColumnFromXY(x As Integer, y As Integer) As Integer

Column index at a control-space point, -1 outside. The point is in the table's own coordinates, as the mouse events deliver them. A hidden column is never returned, and a point over the header or outside the table gives -1.

This example reads the column index at a control-space point, -1 outside:

Var value As Integer = Table1.ColumnFromXY(10, 20)

DesktopTable.ColumnHeaderAt

ColumnHeaderAt(index As Integer) As String

Heading of a column.

This example reads the heading of a column:

Var value As String = Table1.ColumnHeaderAt(0)

ColumnHeaderAt(index As Integer, Assigns value As String)

Sets the column heading. index = AllColumns distributes a tab-separated value across all columns. "" resets to the default.

This example sets the column heading:

Table1.ColumnHeaderAt(0) = "Berlin"

DesktopTable.Columns

Columns As Iterable

Allows For Each column As DesktopTableColumn In table.Columns. The objects handed out are DesktopTableColumn accessors, so a loop can change widths and visibility directly.

This example allows For Each column As DesktopTableColumn In table.Columns:

For Each c As DesktopTableColumn In Table1.Columns
  c.UserResizable = False
Next

DesktopTable.ColumnSortDirectionAt

ColumnSortDirectionAt(column As Integer) As DesktopTable.SortDirections

Sort direction of a column.

This example reads the sort direction of a column:

Var value As DesktopTable.SortDirections = Table1.ColumnSortDirectionAt(1)

ColumnSortDirectionAt(column As Integer, Assigns value As DesktopTable.SortDirections)

Sets the sort direction of a column; None disables sorting via the header.

This example sets the sort direction of a column; None disables sorting via the header:

Table1.ColumnSortDirectionAt(1) = DesktopTable.SortDirections.Ascending

DesktopTable.ColumnSortTypeAt

ColumnSortTypeAt(column As Integer) As DesktopTable.SortTypes

Sortability of a column.

This example reads the sortability of a column:

Var value As DesktopTable.SortTypes = Table1.ColumnSortTypeAt(1)

ColumnSortTypeAt(column As Integer, Assigns value As DesktopTable.SortTypes)

Sets the sortability of a column (AllColumns).

This example sets the sortability of a column:

Table1.ColumnSortTypeAt(1) = DesktopTable.SortTypes.Sortable

DesktopTable.ColumnTagAt

ColumnTagAt(column As Integer) As Variant

Companion value of a column.

This example reads the companion value of a column:

Var value As Variant = Table1.ColumnTagAt(1)

ColumnTagAt(column As Integer, Assigns value As Variant)

Sets the companion value of a column (AllColumns).

This example sets the companion value of a column:

Table1.ColumnTagAt(1) = "myTag"

DesktopTable.ColumnTypeAt

ColumnTypeAt(column As Integer) As DesktopTable.CellTypes

Type of a column.

This example reads the type of a column:

Var value As DesktopTable.CellTypes = Table1.ColumnTypeAt(1)

ColumnTypeAt(column As Integer, Assigns value As DesktopTable.CellTypes)

Sets the type of a column; individual cells can override it via CellTypeAt.

This example sets the type of a column; individual cells can override it via CellTypeAt:

Table1.ColumnTypeAt(1) = DesktopTable.CellTypes.CheckBox

DesktopTable.ColumnVisibleAt

ColumnVisibleAt(index As Integer) As Boolean

True if the column is shown.

ColumnVisibleAt(index As Integer, Assigns value As Boolean)

Shows or hides the column (AllColumns). A hidden column keeps its data, width expressions and index - it only takes no space: the layout gives it width 0, it raises no paint events, and it cannot be hit, resized, dragged or edited.

This example hides a single column and shows every column again:

' Hide the second column without removing it
Table1.ColumnVisibleAt(1) = False

' Show every column again
Table1.ColumnVisibleAt(DesktopTable.AllColumns) = True

DesktopTable.ContainerForCellAt

ContainerForCellAt(row As Integer, column As Integer) As DesktopContainer

The container currently shown in a cell, or Nil. It exists only while the cell is on screen: the table asks ContainerAt when a cell appears and lets the instance go again when the cell leaves.

This example reads the container of a cell:

Var container As DesktopContainer = Table1.ContainerForCellAt(0, 2)

DesktopTable.DrawInto

DrawInto(g As Graphics, left As Integer, top As Integer)

Renders the table into another Graphics context. It draws the table as it currently looks, which is how it ends up in a printout or in a picture.

This example renders the table into another Graphics context:

Table1.DrawInto(g, 10, 10)

DesktopTable.EditCellAt

EditCellAt(row As Integer, column As Integer)

Scrolls the cell into view and starts inline editing. The cell must be of type TextField or TextArea, set through CellTypeAt or ColumnTypeAt. A cell in a hidden column cannot be edited, and an editor that is already open is committed first.

This example scrolls the cell into view and starts inline editing:

Table1.EditCellAt(0, 1)

DesktopTable.ExpandAllRows

ExpandAllRows

Expands every expandable row, including rows only revealed by expanding an earlier one. It works down the hierarchy, so children that only appear once their parent is open are expanded as well.

This example expands every expandable row, including rows only revealed by expanding an earlier one:

Table1.ExpandAllRows

DesktopTable.MergeCells

MergeCells(row As Integer, column As Integer, rowSpan As Integer, columnSpan As Integer)

Merges a rectangular range; (row, column) is the anchor. Raises InvalidArgumentException on overlap. The anchor keeps the content and the styling; the cells it covers keep their data but are no longer drawn. A merge overlapping an existing one is refused.

This example merges a rectangular range; (row, column) is the anchor:

Table1.MergeCells(0, 1, 2, 3)

DesktopTable.Open

Open(file As FolderItem, delimiter As String = ",", importHeaders As Boolean = True)

Reads a delimited text file in UTF-8 and replaces the entire content, so save anything you still need first. The delimiter has to match the file: a comma for CSV, Chr(9) for TSV. Quoted fields are unquoted following RFC 4180, the column count grows to the widest record, and in DataSource mode the call raises an UnsupportedOperationException.

This example reads a delimited text file in UTF-8 and replaces the entire content, so save anything you still need first:

Table1.Open(f)

DesktopTable.PressColumnHeaderAt

PressColumnHeaderAt(column As Integer)

Triggers a header click programmatically. It behaves as though the user had clicked the header: ColumnHeaderPressed fires and a sortable column is sorted.

This example triggers a header click programmatically:

Table1.PressColumnHeaderAt(1)

DesktopTable.Refresh

Refresh(immediately As Boolean = False)

Redraws the portion specified of the contents of the control the next time the OS redraws the control or immediately if True is passed.

If you are calling this so frequently that you experience a slowdown in your code, pass True for the immediately parameter.

Calling this method causes the Render event to fire.

Refresh the entire area immediately:

Me.Refresh(True)

DesktopTable.Refresh

Refresh(x As Integer, y As Integer, width As Integer, height As Integer, immediately As Boolean = False)

Redraws the portion specified of the contents of the control the next time the OS redraws the control or immediately if True is passed.

Refresh a portion of the area the next time the OS redraws the control:

Me.Refresh(100, 150, 200, 300)

DesktopTable.RefreshCellAt

RefreshCellAt(row As Integer, column As Integer)

Redraws one cell; -1 for row or column redraws the whole column or row. Use it instead of a full refresh when a single value changed. If the cell is part of a merge, the whole merge is redrawn.

This example redraws one cell; -1 for row or column redraws the whole column or row:

Table1.RefreshCellAt(0, 1)

DesktopTable.ReloadFromDataSource

ReloadFromDataSource

Re-reads row count, row heights and cell content from the data source. Selection and scroll position are kept, so it is the call to make after the data behind a TableDataSource changed.

This example re-reads row count, row heights and cell content from the data source:

Table1.ReloadFromDataSource

DesktopTable.RemoveAllColumns

RemoveAllColumns

Removes all columns (ColumnCount = 0, empty table). The cell content goes with the columns. The rows themselves remain, but without columns nothing is drawn.

This example removes all columns:

Table1.RemoveAllColumns

DesktopTable.RemoveAllMerges

RemoveAllMerges

Removes all cell merges. The cells keep the data they had before the merge.

This example removes all cell merges:

Table1.RemoveAllMerges

DesktopTable.RemoveAllRows

RemoveAllRows

Removes all rows. With an editable data source the source is cleared, otherwise (in-memory only) the local storage.

This example removes all rows:

Table1.RemoveAllRows

DesktopTable.RemoveColumnAt

RemoveColumnAt(index As Integer)

Removes a column; columns to its right move left. The cells of that column are removed from every row, and merges, the sorting column and the heading index follow the shift.

This example removes a column; columns to its right move left:

Table1.RemoveColumnAt(0)

DesktopTable.RemoveListSelectionNotificationReceiver

RemoveListSelectionNotificationReceiver(receiver As ListSelectionNotificationReceiver)

Unregisters a receiver. Removing a receiver that was never registered does nothing.

This example unregisters the receiver again:

Table1.RemoveListSelectionNotificationReceiver(receiver)

DesktopTable.RemoveRowAt

RemoveRowAt(index As Integer)

Removes the row. With an editable data source it is removed (incl. subtree) from the source, otherwise from the in-memory storage.

If you want to improve performance when adding and removing rows, you can set AllowRowAnimation to False.

This example removes the row:

Table1.RemoveRowAt(0)

DesktopTable.ReusableContainer

ReusableContainer(identifier As String) As DesktopContainer

Called from inside ContainerAt: hands back a container an earlier cell has finished with, or Nil when there is none. The identifier is yours to choose, and a table whose cells hold containers of different kinds keeps them apart by it.

With the reuse the table gets by with about as many instances as there are visible cells, however many rows it has. Without it every cell scrolling into view builds one of its own. How many are kept is ContainerCacheSize.

This example asks for a used instance and builds one only when there is none:

Var container As DesktopContainer = Me.ReusableContainer("CurrencyContainer")

If container = Nil Then
  container = New CurrencyContainer
End If

DesktopTable.RowAt

RowAt(row As Integer) As DesktopTableRow

Lightweight read-only accessor for one row. The object reads what the table currently holds for that row index, so it is a view of the row rather than a copy. Changing a value goes through the table, for example CellTextAt.

This example reads the lightweight read-only accessor for one row:

Var value As DesktopTableRow = Table1.RowAt(0)

DesktopTable.RowDepthAt

RowDepthAt(row As Integer) As Integer

Hierarchy depth of a row (0 = top level). The depth is what the table indents by and what a disclosure widget opens into.

This example reads the hierarchy depth of a row:

Var value As Integer = Table1.RowDepthAt(0)

DesktopTable.RowExpandableAt

RowExpandableAt(row As Integer) As Boolean

True if the row shows a disclosure widget. Only a row marked as expandable can be opened by the user, and only while AllowExpandableRows is on.

This example reads the true if the row shows a disclosure widget:

Var value As Boolean = Table1.RowExpandableAt(0)

RowExpandableAt(row As Integer, Assigns value As Boolean)

Shows or hides the row's disclosure widget.

This example shows or hides the row's disclosure widget:

Table1.RowExpandableAt(0) = True

DesktopTable.RowExpandedAt

RowExpandedAt(row As Integer) As Boolean

Disclosure state of a row.

This example reads the disclosure state of a row:

Var value As Boolean = Table1.RowExpandedAt(0)

RowExpandedAt(row As Integer, Assigns value As Boolean)

Expands or collapses the row and fires RowExpanded or RowCollapsed.

This example expands or collapses the row and fires RowExpanded or RowCollapsed:

Table1.RowExpandedAt(0) = True

DesktopTable.RowForContainer

RowForContainer(container As DesktopContainer) As Integer

The row a container is currently shown in, or -1.

A reused container cannot remember its own row: row numbers move with every insertion, removal and sort, and the same instance serves other rows later. So a control inside the container asks at the moment it is used.

This example writes the value of a control back into the row its container serves:

Var row As Integer = Table1.RowForContainer(sender)
If row < 0 Then Return

Table1.CellTagAt(row, 2) = value

DesktopTable.RowFromXY

RowFromXY(x As Integer, y As Integer) As Integer

Row index at a control-space point, -1 outside. The point is in the table's own coordinates, as the mouse events deliver them. A point over the header or below the last row gives -1.

This example reads the row index at a control-space point, -1 outside:

Var value As Integer = Table1.RowFromXY(10, 20)

DesktopTable.RowHeightAt

RowHeightAt(row As Integer) As Double

Height of a row in points (default height as long as no custom one is set).

This example reads the height of a row in points:

Var value As Double = Table1.RowHeightAt(0)

RowHeightAt(row As Integer, Assigns height As Double)

Sets an individual row height; values <= 0 restore the default height.

This example sets an individual row height; values <= 0 restore the default height:

Table1.RowHeightAt(0) = 24

DesktopTable.RowImageAt

RowImageAt(index As Integer) As Picture

Image of a row.

This example reads the image of a row:

Var value As Picture = Table1.RowImageAt(0)

RowImageAt(index As Integer, Assigns value As Picture)

Sets the row's image; it is drawn to the left of the text.

This example sets the row's image; it is drawn to the left of the text:

Table1.RowImageAt(0) = myPicture

DesktopTable.Rows

Rows As Iterable

Allows For Each row As DesktopTableRow In lb.Rows. The objects handed out are DesktopTableRow accessors, so the loop reads the live content rather than a copy.

This example allows For Each row As DesktopTableRow In lb.Rows:

' Collect the names of the selected rows
Var names() As String

For Each r As DesktopTableRow In Table1.Rows
  If r.Selected Then names.Add(r.CellTextAt(0))
Next

DesktopTable.RowSelectedAt

RowSelectedAt(index As Integer) As Boolean

Selection state of a row.

This example reads the selection state of a row:

Var value As Boolean = Table1.RowSelectedAt(0)

RowSelectedAt(index As Integer, Assigns value As Boolean)

Sets the row's selection state (multiple rows only with RowSelectionType Multiple).

This example sets the row's selection state:

Table1.RowSelectedAt(0) = True

DesktopTable.RowTagAt

RowTagAt(row As Integer) As Variant

Companion value of a row.

This example reads the companion value of a row:

Var value As Variant = Table1.RowTagAt(0)

RowTagAt(row As Integer, Assigns value As Variant)

Sets the row's companion value.

This example sets the row's companion value:

Table1.RowTagAt(0) = "myTag"

DesktopTable.Save

Save(file As FolderItem, delimiter As String = ",", exportHeaders As Boolean = True)

Writes the entire content as a delimited text file in UTF-8. The delimiter decides the format: a comma - the default - writes CSV, Chr(9) writes TSV. Cells containing the delimiter, a double quote or a line break are quoted following RFC 4180, so the file reads back unchanged with Open. It works in DataSource mode as well, where the rows come from the source.

This example asks for a file and writes the table into it:

Var f As FolderItem = FolderItem.ShowSaveFileDialog("text/csv", "Table.csv")

If f <> Nil Then Table1.Save(f)

DesktopTable.ScrollTo

ScrollTo(row As Integer, column As Integer = 0)

Scrolls so the row becomes the top-most and the column the left-most visible. It scrolls no further than the content allows, so the last rows may stay where they are.

This example scrolls so the row becomes the top-most and the column the left-most visible:

Table1.ScrollTo(0)

DesktopTable.SectionHeaderAt

SectionHeaderAt(row As Integer) As Boolean

Whether the row is a section header. While scrolling, the current section's header stays pinned at the top (below the column header) until the next section header scrolls up and pushes it out; the normal rows scroll behind it.

This example reads whether the row is a section header:

Var value As Boolean = Table1.SectionHeaderAt(0)

SectionHeaderAt(row As Integer, Assigns value As Boolean)

Marks (or unmarks) the row as a section header (sticky while scrolling).

This example marks (or unmarks) the row as a section header:

Table1.SectionHeaderAt(0) = True

DesktopTable.SelectAll

SelectAll

Selects every row and fires SelectionChanged; meaningful with RowSelectionType = Multiple. It only has an effect with RowSelectionType set to Multiple. The table also handles the Edit menu item EditSelectAll itself while it has the focus.

This example allows multiple selection and selects every row:

Table1.RowSelectionType = DesktopTable.RowSelectionTypes.Multiple
Table1.SelectAll

DesktopTable.SetFocus

SetFocus

If applicable, sets the focus to the DesktopUIControl. KeyDown events are directed to the control.

If the control cannot get the focus on the platform on which the application is running, SetFocus does nothing. The SetFocus method of the DesktopWindow class or the ClearFocus method can be used to remove the focus from the control that currently has the focus, leaving no control with the focus.

Note

On macOS, you need Full Keyboard Access turned on in System Preferences (Keyboard->Shortcuts) in order to manually set focus to non-text controls.

The following example in the Opening event sets the focus to the that control. If another control has the focus when this line is executed, then the user sees this control gets the focus.

Me.SetFocus

DesktopTable.Sort

Sort

Sorts by SortingColumn and its sort direction. The rows are compared as text unless the RowComparison event decides the order. With a SortableTableDataSource the source sorts instead.

This example sorts by SortingColumn and its sort direction:

Table1.Sort

DesktopTable.UnmergeCellsAt

UnmergeCellsAt(row As Integer, column As Integer)

Removes the merge covering the cell (anchor or covered). The cells the merge covered are drawn on their own again, with the data they still carry.

This example removes the merge covering the cell:

Table1.UnmergeCellsAt(0, 1)

Event descriptions


DesktopTable.Activated

Activated

The control is activated. In a single window interface, the Activate event fires when the parent window is activated. See the DesktopApplication and DesktopWindow Activate events.

This can be because the app is launched or a window belonging to another app is no longer frontmost (active). The Deactivate event fires when another window becomes active. In a single window interface, the Activate event fires when the window is activated, e.g., when the app first displays the window.

This example reloads the data when the window comes forward again:

' The window came forward again - show the live data
Me.ReloadFromDataSource

DesktopTable.ApplyLeadingActionsForRow

ApplyLeadingActionsForRow(row As Integer) As DesktopTableRowAction()

macOS, Windows and Linux (touchpad). Actions for a two-finger swipe from the leading edge. Raised once, when the gesture is recognised. An empty array leaves the gesture as an ordinary scroll.

This example offers a single blue action on the leading edge:

Var actions() As DesktopTableRowAction

Var unread As New DesktopTableRowAction("Unread", "unread")
unread.BackgroundColor = New ColorGroup(&c2F6FDB, &c25589F)
actions.Add(unread)

Return actions

DesktopTable.ApplyTrailingActionsForRow

ApplyTrailingActionsForRow(row As Integer) As DesktopTableRowAction()

macOS, Windows and Linux (touchpad). Actions for a swipe from the trailing edge, same contract as above.

This example offers a red delete action, except on rows marked as locked:

' No actions for the rows that may not be deleted
If Me.RowTagAt(row) = "locked" Then Return Nil

Var actions() As DesktopTableRowAction

Var remove As New DesktopTableRowAction("Delete", "delete")
remove.BackgroundColor = New ColorGroup(&cD93025, &cC5372C)
actions.Add(remove)

Return actions

DesktopTable.CellAction

CellAction(row As Integer, column As Integer)

An inline editor was committed. It fires when the user leaves an editable cell, by pressing Return or Tab or by clicking elsewhere, and also when a checkbox cell is clicked. The content need not have changed.

This example writes the edited value back into the record behind the row:

' The user finished editing: write the value back
mRecords(row).Name = Me.CellTextAt(row, column)
mRecords(row).Modified = True

DesktopTable.CellFocusLost

CellFocusLost(row As Integer, column As Integer)

The inline editor lost focus. The user moved on to another cell or ended the editing with Return, Tab or Escape.

This example formats the value again once editing ends:

' Editing ended - show the value formatted again
Me.CellTextAt(row, column) = Val(Me.CellTextAt(row, column)).ToString("#,##0.00")

DesktopTable.CellFocusReceived

CellFocusReceived(row As Integer, column As Integer)

The inline editor gained focus. The cell is now being edited, so this is the place to preselect text or adjust the editor.

This example preselects the text so typing replaces it:

' Preselect the text so typing replaces it
If Me.ActiveTextControl <> Nil Then Me.ActiveTextControl.SelectAll

DesktopTable.CellKeyDown

CellKeyDown(row As Integer, column As Integer, key As String) As Boolean

The user pressed key while the inline editor of a cell (row, column) has the focus. Return True to swallow the key, for example to refuse characters the column does not accept.

This example refuses anything but digits in the amount column:

' Only digits in the amount column
If column = 2 And key.Asc > 31 And InStr("0123456789.", key) = 0 Then Return True

DesktopTable.CellPressed

CellPressed(row As Integer, column As Integer, x As Integer, y As Integer) As Boolean

Cell was clicked; x, y are cell-relative. It fires before the table changes the selection. Return True to keep the click to yourself, which is how a clickable area inside a cell is built.

This example treats a click on the icon column as opening the record:

' A click in the icon column opens the record instead of selecting the row
If column = 0 And x < 20 Then
  ShowRecord(row)
  Return True
End If

DesktopTable.CellTextChanged

CellTextChanged(row As Integer, column As Integer)

The editor's text changed. It fires on every keystroke in the inline editor, not only when the editing ends.

This example enables the Save button as soon as something is typed:

' Enable the Save button as soon as something is typed
SaveButton.Enabled = True

DesktopTable.Closing

Closing

The control is going away. The control is being destroyed. An open inline editor has already been committed at this point.

This example stores the column widths for the next launch:

' Keep the column widths for the next launch
mPreferences.ColumnWidths = Me.ColumnWidths

DesktopTable.ColumnHeaderPressed

ColumnHeaderPressed(column As Integer) As Boolean

Header clicked; return True to suppress sorting. It fires before the table sorts. Return True to handle the click yourself and keep the table from sorting.

This example keeps the first column from being sorted:

' The first column is the row number: never sort by it
If column = 0 Then Return True

DesktopTable.ColumnReordered

ColumnReordered(fromColumn As Integer, toColumn As Integer)

A column drag finished. The columns are already in their new order, so the indices reported are the new ones.

This example remembers the order the user arranged:

' Remember the new order by the headings
Var headings() As String

For i As Integer = 0 To Me.LastColumnIndex
  headings.Add(Me.ColumnHeaderAt(i))
Next

mPreferences.ColumnOrder = String.FromArray(headings, Chr(9))

DesktopTable.ColumnReordering

ColumnReordering(fromColumn As Integer, toColumn As Integer) As Boolean

A column drag is in progress; return True to reject. It fires while the column is being dragged. Return True to refuse that particular move; the column then stays where it is.

This example refuses to move the status column:

' The status column has to stay where it is
If fromColumn = 0 Or toColumn = 0 Then Return True

DesktopTable.ColumnResized

ColumnResized(column As Integer, width As Integer)

A column-width drag finished; width is the final width in whole points. Fires only when the width actually changed, so a plain click on the divider stays silent.

This example stores the width the user settled on:

' Store the width the user settled on
mPreferences.ColumnWidth(column) = width

DesktopTable.ColumnResizing

ColumnResizing(column As Integer, width As Integer)

Fires on every step of a column-width drag, reporting the whole-point width about to be applied. Purely informational - see the note below.

This example shows the width in a status label while it is dragged:

' Show the width while it is being dragged
StatusLabel.Text = width.ToString + " pt"

DesktopTable.ColumnSorted

ColumnSorted(column As Integer) As Boolean

Fires before sorting; return True to sort yourself. It fires before the rows are rearranged. Return True to sort the data yourself, for example in the database the rows come from.

This example lets the database sort and reloads afterwards:

' Let the database sort, then reload
mRowSet = mDatabase.SelectSQL("SELECT * FROM People ORDER BY " + FieldName(column))
Me.ReloadFromDataSource

Return True

DesktopTable.ConstructContextualMenu

ConstructContextualMenu(base As DesktopMenuItem, x As Integer, y As Integer) As Boolean

Build the contextual menu. A right-click first selects the row under the pointer, then this event fires so you can add items. Return True to suppress the menu.

This example adds an entry for the row under the pointer:

Var row As Integer = Me.RowFromXY(x, y)
If row < 0 Then Return False

base.AddMenu(New DesktopMenuItem("Delete " + Me.CellTextAt(row, 0), row))
Return True

DesktopTable.ContainerAt

ContainerAt(row As Integer, column As Integer) As DesktopContainer

Supplies the container for a cell of type Container. It fires when such a cell comes into view, and what it returns is shown in that cell until the cell leaves again. Nil leaves the cell empty.

Ask ReusableContainer first and build a new instance only when it returns Nil, then fill it with the row's data. The same instance serves other rows later, so everything that belongs to the row is set here.

A column's number is a position, not a name: AllowColumnReordering lets the user move the column, and the event then arrives with its new number. A handler that compares the number against a fixed one returns Nil for every cell from that moment on, and the column stays empty. Where the handler has to tell one container column from another, ColumnTagAt is the identifier that moves with the column.

This example hands out a container with a popup menu in it:

If Me.ColumnTagAt(column) <> "currency" Then Return Nil

Var container As DesktopContainer = Me.ReusableContainer("CurrencyContainer")

If container = Nil Then
  container = New CurrencyContainer
  AddHandler CurrencyContainer(container).CurrencySelected, WeakAddressOf CurrencySelected
End If

Var value As Variant = Me.CellTagAt(row, column)
CurrencyContainer(container).Init(If(value.IsNull, 0, value.IntegerValue))

Return container

DesktopTable.ContainerRemovedAt

ContainerRemovedAt(row As Integer, column As Integer, container As DesktopContainer) As Boolean

A cell has given up its container: it scrolled out of view, its row is gone or its type changed. Return True to keep the instance yourself - the table then only lets go of it - and False to have the table dispose of it.

A container fetched through ReusableContainer goes into the table's own pool instead, so for those this event fires only once the pool is full - see ContainerCacheSize.

This example leaves the instance to the table:

Return False

DesktopTable.ContextualMenuItemSelected

ContextualMenuItemSelected(selectedItem As DesktopMenuItem) As Boolean

A contextual menu item was chosen. It reports the item the user picked from the menu built in ConstructContextualMenu.

This example removes the row the menu entry was built for:

If selectedItem.Tag.IsNull Then Return False

Me.RemoveRowAt(selectedItem.Tag.IntegerValue)
Return True

DesktopTable.Deactivated

Deactivated

The DesktopTable is deactivated. See the DesktopApplication and DesktopWindow Deactivated events.

In a multiple window interface, the Deactivated event fires when the parent window is deactivated because another window has been brought to the front or a window belonging to another app becomes frontmost. In a single window app, the Deactivated event fires when a window belonging to another app becomes frontmost.

This example stops a refresh timer while the window is in the background:

' Stop anything that only needs to run while the window is in front
mRefreshTimer.RunMode = Timer.RunModes.Off

DesktopTable.DoublePressed

DoublePressed(row As Integer, column As Integer)

Double-click on a cell.

This example opens the record of the selected cell:

If Me.SelectedRowIndex <> DesktopTable.NoSelection Then
  ShowRecord(row, column)
End If

DesktopTable.DragEnter

DragEnter(obj As DragItem, action As DragItem.Types) As Boolean

A drag entered the control. Return True to refuse the drag. The table only receives dragged data after one of the Accept…Drop methods was called.

This example accepts folders only:

' Only take folders
If obj.FolderItem = Nil Or Not obj.FolderItem.IsFolder Then Return True

DesktopTable.DragExit

DragExit(obj As DragItem, action As DragItem.Types)

A drag left the control. The pointer left the table again; the drop did not happen here.

This example clears the hint shown during the drag:

' Remove the hint shown while the drag was over the table
StatusLabel.Text = ""

DesktopTable.DragOver

DragOver(x As Integer, y As Integer, obj As DragItem, action As DragItem.Types) As Boolean

A drag is moving over the control. It fires repeatedly while the pointer moves over the table. Return True to refuse the drop at that position.

This example refuses a drop over the header area:

' Refuse the drop over the header area
If y < Me.HeaderHeight Then Return True

DesktopTable.DragOverRow

DragOverRow(x As Integer, y As Integer, obj As DragItem, action As Integer, ByRef row As Integer, ByRef parentRow As Integer, ByRef location As DesktopTable.DropLocations) As Boolean

row-aware drag feedback; adjust the ByRef values to move the drop target.

This example drops into a folder row and between the other rows:

' Drop into a folder row, between the others
If Not Me.RowExpandableAt(row) Then location = DesktopTable.DropLocations.AfterRow
Return False

DesktopTable.DragReorderRows

DragReorderRows(newPosition As Integer, parentRow As Integer) As Boolean

Rows are being reordered by drag; return True to handle it yourself.

This example moves the record along with its row:

' Move the record along with the row
mRecords.AddAt(newPosition, mRecords(Me.SelectedRowIndex))
mRecords.RemoveAt(Me.SelectedRowIndex + If(newPosition < Me.SelectedRowIndex, 1, 0))

DesktopTable.DragRow

DragRow(drag As DragItem, row As Integer) As Boolean

The user started dragging row out of the table, which only happens while AllowRowDragging is on. Put the data into drag and return True to allow the drag.

This example puts the row's first cell into the drag and allows it:

drag.Text = Me.CellTextAt(row, 0)
Return True

DesktopTable.DropObject

DropObject(obj As DragItem, action As DragItem.Types)

Something was dropped on the control. The drop was not aimed at a particular row. DropObjectOnRow reports one that was.

This example adds the dropped text as a new row:

If obj.TextAvailable Then Me.AddRow(obj.Text)

DesktopTable.DropObjectOnRow

DropObjectOnRow(x As Integer, y As Integer, obj As DragItem, action As Integer, row As Integer, parentRow As Integer, location As DesktopTable.DropLocations)

Something was dropped on a specific row. The values tell you which row was hit and whether the drop happened on it or between rows, so the data can be inserted at the right place.

This example inserts below the row, or replaces its text when dropped on it:

If Not obj.TextAvailable Then Return

If location = DesktopTable.DropLocations.AfterRow Then
  Me.AddRowAt(row + 1, obj.Text)
Else
  Me.CellTextAt(row, 0) = obj.Text
End If

DesktopTable.FocusLost

FocusLost

The control lost keyboard focus. The table no longer receives keystrokes, and the selection is drawn in the inactive colour.

This example disables the actions that work on the selection:

' Grey out the actions that work on the selection
DeleteButton.Enabled = False

DesktopTable.FocusReceived

FocusReceived

The control gained keyboard focus. The table now receives keystrokes, and the selection is drawn in the active colour.

This example enables them again to match the selection:

DeleteButton.Enabled = Me.SelectedRowCount > 0

DesktopTable.KeyDown

KeyDown(key As String) As Boolean

The user pressed key while the table has the focus. It fires before the table acts on the key: return True to keep the key to yourself, otherwise the arrow keys move the selection, Shift extends it in Multiple mode, and Home, End, Page Up and Page Down scroll.

This example removes the selected rows on Delete:

' Delete removes the selected rows
If key.Asc = 8 Or key.Asc = 127 Then

  For i As Integer = Me.LastRowIndex DownTo 0
    If Me.RowSelectedAt(i) Then Me.RemoveRowAt(i)
  Next

  Return True

End If

DesktopTable.KeyUp

KeyUp(key As String)

The user released key while the table had the focus. It fires after the matching key press was dealt with and reports the key itself, not what the table did with it.

This example applies a filter once Return was released:

' Filter as the user types in a search field above the table
If key = Chr(13) Then ApplyFilter(SearchField.Text)

DesktopTable.MenuBarSelected

MenuBarSelected

The menu bar is about to open. It fires just before a menu opens, so menu items can be enabled or disabled to match the current selection.

This example enables the Edit menu items that need a selection:

EditCopy.Enabled = Me.SelectedRowCount > 0
EditClear.Enabled = Me.SelectedRowCount > 0

DesktopTable.MouseDown

MouseDown(x As Integer, y As Integer) As Boolean

The user pressed the mouse button over the table, at x, y in the table's own coordinates. It fires before the table changes the selection or starts a drag; returning True takes the click, which is also what makes the following MouseDrag and MouseUp reach you.

This example claims the click on the icon column:

' Take the click on the icon column, and with it MouseDrag and MouseUp
Var column As Integer = Me.ColumnFromXY(x, y)
If column = 0 Then Return True

DesktopTable.MouseDrag

MouseDrag(x As Integer, y As Integer)

Mouse moved with the button down. It only fires after MouseDown returned True.

This example reports the row the pointer is over while dragging:

' Show what the pointer is over while dragging
StatusLabel.Text = "Row " + Me.RowFromXY(x, y).ToString

DesktopTable.MouseEnter

MouseEnter

Pointer entered the control. Use it to change the mouse cursor or to show information about what is under the pointer.

This example changes the mouse cursor over the table:

Me.MouseCursor = System.Cursors.FingerPointer

DesktopTable.MouseExit

MouseExit

Pointer left the control. Anything shown while the pointer was inside, such as a highlight of your own, belongs back to its normal state here.

This example restores the cursor and clears the status label:

Me.MouseCursor = Nil
StatusLabel.Text = ""

DesktopTable.MouseMove

MouseMove(x As Integer, y As Integer)

Pointer moved. It fires while no mouse button is held down.

This example remembers the row under the pointer for a hover highlight:

' Highlight the row under the pointer
Var row As Integer = Me.RowFromXY(x, y)

If row <> mHotRow Then
  mHotRow = row
  Me.Refresh(False)
End If

DesktopTable.MouseUp

MouseUp(x As Integer, y As Integer)

Mouse button released. It only fires after MouseDown returned True.

This example toggles the status of the row that was clicked:

Var row As Integer = Me.RowFromXY(x, y)
If row >= 0 Then ToggleStatus(row)

DesktopTable.MouseWheel

MouseWheel(x As Integer, y As Integer, deltaX As Integer, deltaY As Integer) As Boolean

The user turned the mouse wheel or scrolled on a trackpad over the table; deltaX and deltaY are the steps. It fires before the table scrolls, so returning True lets you scroll by yourself or keep the table where it is.

This example zooms with Command and the wheel instead of scrolling:

' Command + wheel zooms instead of scrolling
If Keyboard.AsyncCommandKey Then
  Me.FontSize = Max(9, Me.FontSize + deltaY)
  Return True
End If

DesktopTable.Opening

Opening

The control is being set up. The table is ready to be filled, so rows added here cost a single layout pass no matter how many there are.

This example sets up the columns and fills the table:

Me.ColumnCount = 2
Me.ColumnHeaderAt(0) = "Name"
Me.ColumnHeaderAt(1) = "City"
Me.ColumnWidths = "*,120"

For Each r As Record In mRecords
  Me.AddRow(r.Name, r.City)
Next

DesktopTable.PaintBackground

PaintBackground(g As Graphics)

Fires once per repaint, right after the list background is filled and before rows, grid and header. g is the whole, unclipped control surface.

This example paints the area behind the rows:

' A watermark behind the rows
g.DrawingColor = Color.RGB(245, 245, 245)
g.FillRectangle(0, 0, g.Width, g.Height)

Return True

DesktopTable.PaintCellBackground

PaintCellBackground(g As Graphics, row As Integer, column As Integer) As Boolean

Draw the cell background yourself; return True to suppress the default. It fires once per visible cell per frame, before the selection and the cell content are drawn. Test the cheap condition first and leave the rest to the table.

This example draws every other row in a light grey:

' Stripes: test the cheap condition first, this fires once per visible cell
If row Mod 2 = 0 Then Return False

g.DrawingColor = Color.RGB(245, 245, 245)
g.FillRectangle(0, 0, g.Width, g.Height)

Return True

DesktopTable.PaintCellText

PaintCellText(g As Graphics, row As Integer, column As Integer, x As Integer, y As Integer) As Boolean

Draw the cell text yourself. The Graphics is clipped to the cell and x, y mark where the standard text would start. Return True to suppress it.

This example draws negative amounts right-aligned and in red:

' Negative amounts in red, right aligned
If column <> 2 Then Return False

Var amount As Double = Me.CellTextAt(row, column).Val

If amount < 0 Then g.DrawingColor = Color.RGB(200, 0, 0)
g.DrawText(amount.ToString("#,##0.00"), g.Width - g.TextWidth(amount.ToString("#,##0.00")) - 4, y)

Return True

DesktopTable.PaintDisclosureWidget

PaintDisclosureWidget(g As Graphics, row As Integer, ByRef x As Integer, ByRef y As Integer, ByRef width As Integer, ByRef height As Integer) As Boolean

Draw or reposition the disclosure widget. Changing the passed values moves and resizes the widget without taking the drawing over; returning True draws it yourself. The rectangle is in the coordinates of the cell, and it is the rectangle the row is expanded and collapsed by: wherever the widget is drawn is where it is clicked.

The width also says how much room stays free before the cell text, so a widget widened where it stands pushes the text along with it. A widget that is moved does not: a handler that puts it at the far end of the cell needs nothing kept free at the start, so the text keeps the indent every other row has.

The event fires for every expandable row, including one whose first column is the anchor of a merge. The graphics carries the cell's own font.

This example moves the widget to the right and lets the table draw it:

' Move the widget a little to the right, but let the table draw it
x = x + 4
Return False

DesktopTable.PaintHeaderBackground

PaintHeaderBackground(g As Graphics, column As Integer) As Boolean

Draw a header cell's background yourself. It fires once per visible header cell. A hidden column raises no paint event at all.

This example highlights the header of the sorting column:

If column <> Me.SortingColumn Then Return False

g.DrawingColor = Color.RGB(226, 236, 250)
g.FillRectangle(0, 0, g.Width, g.Height)

Return True

DesktopTable.PaintHeaderContent

PaintHeaderContent(g As Graphics, column As Integer, x As Integer, y As Integer) As Boolean

Draw the header cell's content manually. The x, y values specify the starting point of the standard text.

This example draws the heading in bold capitals:

g.Bold = True
g.DrawText(Me.ColumnHeaderAt(column).Uppercase, x, y)

Return True

DesktopTable.PaintRowAction

PaintRowAction(g As Graphics, row As Integer, action As DesktopTableRowAction, pressed As Boolean) As Boolean

Draw one row-action button yourself. g is clipped to the button, so (0,0) is its corner and g.Width/g.Height its size. pressed is True while the mouse is held on it.

This example draws a rounded button instead of the full-height default:

' A rounded button instead of the full-height default
g.DrawingColor = If(pressed, Color.RGB(150, 30, 25), Color.RGB(217, 48, 37))
g.FillRoundRectangle(6, 6, g.Width - 12, g.Height - 12, 8, 8)

g.DrawingColor = Color.White
g.DrawText(action.Title, (g.Width - g.TextWidth(action.Title)) / 2, g.Height / 2 + g.FontAscent / 2)

Return True

DesktopTable.PaintSortWidget

PaintSortWidget(g As Graphics, column As Integer, ByRef x As Integer, ByRef y As Integer, ByRef width As Integer, ByRef height As Integer) As Boolean

Draw or reposition the sort indicator. Independent of PaintHeaderContent - the standard indicator still draws even when the header's own text/background was handled.

This example shrinks the sort indicator and lets the table draw it:

' A smaller indicator, drawn by the table
width = 8
height = 8

Return False

DesktopTable.RowActionSelected

RowActionSelected(row As Integer, action As DesktopTableRowAction)

The user picked a row action. action is the DesktopTableRowAction itself, so Tag and Title are both available. The panel is already closed.

This example carries out the action the user picked:

Select Case action.Tag
Case "delete"
  Me.RemoveRowAt(row)
Case "unread"
  Me.CellBoldAt(row, 0) = True
End Select

DesktopTable.RowCollapsed

RowCollapsed(row As Integer)

A row was collapsed. The children of a row are no longer visible. Whether they are also removed from the data is up to you.

This example frees the children that were loaded for the open row:

' Free the children that were only loaded for the open row
RemoveChildrenOf(row)

DesktopTable.RowComparison

RowComparison(row1 As Integer, row2 As Integer, column As Integer, ByRef result As Integer) As Boolean

Custom sort comparison; set result to -1, 0 or 1 and return True. It is called while sorting, for every pair of rows the sort compares. A negative result puts row1 first, a positive one row2.

This example sorts the amount column numerically instead of as text:

' Sort the amount column numerically instead of as text
If column <> 2 Then Return False

Var a As Double = Me.CellTextAt(row1, column).Val
Var b As Double = Me.CellTextAt(row2, column).Val

result = If(a < b, -1, If(a > b, 1, 0))

Return True

DesktopTable.RowExpanded

RowExpanded(row As Integer)

A row was expanded - the place to add its children. Children added here appear directly below the row. Loading them only now keeps a large tree cheap.

This example loads the children only when the row is opened:

' Load the children only now
Var depth As Integer = Me.RowDepthAt(row) + 1

For Each child As Record In ChildrenOf(row)
  Me.AddRowAt(row + 1, depth, child.Name)
Next

DesktopTable.Scrolled

Scrolled(x As Integer, y As Integer)

The view scrolled. It fires for every scroll step, from the scrollbars, the mouse wheel, the keyboard and from code.

This example keeps a second table in sync:

' Keep a second table in sync
DetailTable.ScrollPosition = Me.ScrollPosition

DesktopTable.SelectionChanged

SelectionChanged

The selection changed. It fires once per change, no matter how many rows it affects.

This example follows the selection with a button and a detail view:

DeleteButton.Enabled = Me.SelectedRowCount > 0

If Me.SelectedRowIndex <> DesktopTable.NoSelection Then
  ShowRecord(Me.SelectedRowIndex)
End If

Notes

Row actions

A horizontal two-finger swipe on a row reveals the actions returned by ApplyLeadingActionsForRow and ApplyTrailingActionsForRow. The events are raised once per gesture, so building the array there costs nothing per frame; returning an empty array leaves the gesture an ordinary scroll. A swipe only takes over once the content cannot scroll further that way.

Menu handlers

While the table has the focus it handles two standard Edit menu items itself. EditCopy copies the selected rows to the clipboard as text - one line per row, the visible columns separated by Tab - and EditSelectAll calls SelectAll when RowSelectionType is Multiple. Both require menu items named exactly that, with AutoEnable turned on.

Custom drawing

The paint events fire once per visible item per frame and all follow the same contract: the Graphics is already clipped to the item, so (0, 0) is its own corner, and returning True suppresses the built-in drawing. Test the cheap condition first - a table of 25 visible rows and 5 columns raises PaintCellBackground 125 times per frame.

Interfaces

This class implements the ListSelectionNotifier class interface.

Compatibility

Project Types

Desktop

Operating Systems

All