How to: Show records as a two-line list
Show a short list of records the way Outlook and Teams do (a bold title, a gray detail line, a colored status, and a button for each entry, with no column headers), such as the open sessions on a dashboard, with an End button only where a session can be ended.
Requires WKL Forms Object Library 1.36 or later.
Solution overview
- A view of
WklGrid. SetViewModetowgvListand describe an entry inItemTemplate. The record source, server mode, selection, theLinkMasterFieldsof a subform next to it,BeforeDelete, andDeleteSelectedall work as they do in the grid. A continuous form can't do this, because it holds only a single instance of an ActiveX control. - The template names fields: a
title(optionally as a link), up to twolineswith Access formats, astatuspill with its kind field, abadge, aglyph, and up to twocommandswhose visibility and enabled state come from fields in the record. - Events:
ItemClickfor the entry,LinkClickfor the link, andItemCommandfor a button. The grid doesn't act on any of them by itself.RowSelectreports, as in the table, that the user selected another entry (keys or a click), not that code setSelectedKey. The table of all events of the list view is in the remarks onViewModein the API reference.
Implementation
Create the sample table once (run the procedure from the Immediate window):
Public Sub CreateListSample()
With CurrentDb
.Execute "CREATE TABLE tblSession (ID LONG CONSTRAINT PK_Session PRIMARY KEY, Person TEXT(50), " & _
"Method TEXT(20), Origin TEXT(30), ExpiresAt DATETIME, State TEXT(20), StateKind TEXT(10), CanEnd YESNO)"
.Execute "INSERT INTO tblSession VALUES (1, 'Jane Adams', 'Windows', '10.0.4.21', #2026-10-07 18:02:00#, 'Active', 'ok', True)"
.Execute "INSERT INTO tblSession VALUES (2, 'Robert Baker', 'Password', Null, #2026-10-07 19:30:00#, 'Expired', 'warn', False)"
End With
End Sub
The form frmStart contains a WklGrid named grdSessions. You usually make the settings once on
the designer's List page (property sheet, Custom row, [...]); here they're made in code:
Option Compare Database
Option Explicit
Private Sub Form_Load()
With Me!grdSessions.Object
.RecordSource = "tblSession"
.KeyField = "ID"
.ItemTemplate = "{""title"":{""field"":""Person"",""link"":true}," & _
"""lines"":[[{""field"":""Method""},{""field"":""Origin""},{""field"":""ExpiresAt"",""format"":""hh:nn""}]]," & _
"""status"":{""field"":""State"",""kindField"":""StateKind""}," & _
"""commands"":[{""key"":""end"",""caption"":""End"",""visibleField"":""CanEnd""}]}"
.EmptyText = "No open sessions."
.AllowDeletions = True
.ViewMode = wgvList
End With
End Sub
Private Sub grdSessions_LinkClick(ByVal Key As Variant, ByVal Field As String)
DoCmd.OpenForm "frmPerson", WhereCondition:="SessionID = " & Key
End Sub
Private Sub grdSessions_ItemCommand(ByVal Key As Variant, ByVal Command As String)
If Command = "end" Then Me!grdSessions.Object.DeleteSelected
End Sub
Private Sub grdSessions_BeforeDelete(ByVal Key As Variant, ByVal Count As Long, Cancel As Integer, Confirm As Boolean)
Confirm = False
Cancel = (MsgBox("End this session?", vbYesNo + vbQuestion) = vbNo)
End Sub
The list shows „Jane Adams“ in semibold with „Windows · 10.0.4.21 · 18:02“ below it, a green
„Active“ status, and an End button. „Robert Baker“ has no address (the empty value and its
separator are left out) and no button, because CanEnd is False.
Remarks
- A Null in a detail line is left out along with its separator. The formats are the same as for Access columns and follow the Windows regional settings. Relative times („5 min ago“) aren't built in; calculate them in the query.
Requerykeeps the selected record (SelectedKey), so you can call it from a timer to refresh a list such as the open sessions.- An entry is as tall as its text unless
ItemHeightis set; text that doesn't fit ends with „…“ and appears in full in its tooltip. - Keyboard: Tab moves from the entry to its buttons and then on to the next control. Screen readers announce each entry as one sentence, and the link and buttons as separate elements.
DeleteSelectedinItemCommandruns right after the procedure ends, so theBeforeDeleteprocedure above reaches the form (VBA doesn't deliver a grid event while one of the grid's event procedures is running). Code afterDeleteSelectedinItemCommandstill sees the record; show a message such as „Session ended“ withWklToastinAfterDelete.- The list draws no columns. To sort by a field the entries don't show, add a hidden column by code:
Set c = .Columns.Add("No"),c.Visible = False,c.SortDirection = wsdAscending. - Tiles side by side (cards) aren't part of the list view.