Core Docs

GridView

Grid tabular sortable / filterable / inline edit. Workhorse của Core. Cấu hình cột qua bảng `GridPolicy`.

Source: Core/Components/GridView.cs ComponentType trong DB: GridView. Khi GroupBy field set, Core tự pick GroupGridView. Khi cần data lớn (>1000 row) dùng VirtualGrid thay thế.

Cấu hình

ComType:           GridView
Reference:         Customer
DataSourceFilter:  ?$filter=Active eq true&$top=200   # bắt buộc đủ "?$filter="
CanAdd:            true
CanSearch:         true
Editable:          false

Field DB dùng

Bao gồm tất cả của ListView, plus:

FieldVai trò
EditableTrue → enable inline edit (empty row dưới cùng để insert).
CanAddTrue → hiện nút “Thêm dòng” trong grid.
ClassNameClass CSS thêm cho grid container.
FormatDataFormat hiển thị cell (chỉ áp khi grid render thay vì cell renderer).
FocusSearchTrue → auto focus search box khi grid render.
IsSumaryTrue → render dòng summary (footer) tổng hợp.
IsCollapsibleTrue → group rows có thể thu/mở.
OrderBySumaryField sắp xếp summary (nếu có nhiều aggregate).
FormatSumaryFieldFormat string cho cell summary.
GroupByField group rows theo (cho GroupGridView thừa kế).
GroupFormatFormat header group ("{StatusName} ({COUNT})").
AddDateTrue → auto thêm filter ngày hôm nay khi load.
DefaultAddStartSố tháng/ngày offset đầu range (vd -7 = 7 ngày trước).
DefaultAddEndSố tháng/ngày offset cuối range.
DefaultValGiá trị mặc định cho cell mới.
RefClassClass CSS cho reference display.
CastPropHint casting property cho Bridge.NET.
PopulateFieldAuto populate field từ reference khi pick row.
PostOrderOrder sau khi render xong.
PreQueryQuery chạy trước khi load data chính (lookup dependency).
ShowAuditTrue → hiện audit info (created/updated by).
ShowNullTrue → hiển thị null cell rõ ràng (thay vì empty).

Events kích hoạt

Kế thừa từ ListView, thêm:

EventMethod signature
change(rowData, rowSection)
BeforeCreated(rowData, this)
AfterCreated(rowData)
AfterEmptyRowCreated(emptyRow) — empty row dưới cùng (inline edit).
BeforePasted(originRows, copiedRows)
AfterPasted(originRows, copiedRows)

Format cell — FormatCell / FormatRow

GridPolicy.FormatCell / FormatRow được map sang Component.FormatData / FormatEntity lúc render (qua GridPolicy.MapToComponent()):

res.FormatData   = header.FormatCell;   // FormatCell ⇄ FormatData
res.FormatEntity = header.FormatRow;    // FormatRow  ⇄ FormatEntity

Sau đó Utils.GetCellTextInternal(component, cellData, row, refData) render text theo logic của ComponentType (xem Cấu hình UI → Logic render cell):

-- Cấu hình cột grid điển hình
INSERT INTO GridPolicy
  (FeatureId, ComponentId, EntityId, FieldName, ShortDesc, ComponentType, RefName, FormatCell, [Order]) VALUES

  -- Cột Date — dùng {0:format} positional
  (42, 100, 12, 'CreatedDate', N'Ngày tạo',  'Datepicker',   NULL,        '{0:dd/MM/yyyy HH:mm}',  10),

  -- Cột FK Customer — RefName trigger LoadMasterData fetch ref entity, FormatCell áp lên ref
  (42, 100, 12, 'CustomerId',  N'Khách hàng', 'Dropdown',     'Customer',  '{Code} - {Name}',       20),

  -- Cột Number formatted
  (42, 100, 12, 'Total',       N'Tổng',       'Number',       NULL,        '{0:N0}',                30),

  -- Cột text với FormatRow ghép nhiều field row
  (42, 100, 12, 'OrderNo',     N'Mã đơn',     NULL,           NULL,        NULL,                    40);
-- (cột thứ 4 set FormatRow trong cột riêng nếu cần — vd '{OrderNo} ({Status.Name})')

LoadMasterData — auto fetch ref entity cho FK cells

Khi grid có cột FK (ComponentType = Dropdown/Select2/SearchEntry/MultipleSearchEntry, RefName set), Core tự động gọi LoadMasterData(rows) sau khi load row data:

  1. Quét tất cả header có RefName.
  2. Lấy distinct ids từ rows (vd CustomerId in (1, 3, 7)).
  3. POST batch Client.LoadById(...) cho từng RefName → fetch ref entities trong 1 request.
  4. Cache vào RefData[refName].
  5. SyncMasterData(rows, headers) — set property nested trên row (vd row.Customer = customerEntity) → placeholder {Customer.Name} work.

→ Pattern khuyến cáo:

-- ✅ Đúng: set RefName + FormatCell, Core tự lo
RefName:    Customer
FormatCell: '{Code} - {Name}'

-- ❌ Sai: tự gọi API ngoài để load Customer rồi tự ghép trong code

Việc của bạn chỉ là cấu hình GridPolicy đúngRefName, ComponentType, FormatCell. Core lo:

  • Fetch ref data (LoadMasterData)
  • Cache (RefData)
  • Sync vào row (SyncMasterData)
  • Render text (GetCellTextInternal)

→ Cú pháp placeholder đầy đủ: Cấu hình UI → FormatData/FormatEntity/FormatCell.

Cấu hình cột (GridPolicy)

Cột grid là bảng riêng GridPolicy, scope theo (FeatureId, ComponentId = id của row GridView):

FieldMô tả
FieldNameProperty của row entity.
ShortDescHeader label.
WidthPx.
FrozenTrue → sticky bên trái.
SortableClick header để sort.
FilterableShow filter cell dưới header.
StatusBarTrue → cột toolbar (chứa button row action).
OrderVị trí cột.
ActiveHide khi false.
ComTypeRenderer cell (CellText, Number, Datepicker, …).
FormatCellTemplate {FieldName} / {Path.To.Field} áp lên row entity (xem mục Format cell trên).
FormatRowFallback khi FormatCell rỗng.
Aggregate"sum" / "avg" / "count" cho summary footer.

Inline edit

Set Editable = true → grid render thêm 1 empty row cuối cho insert. User gõ vào cell → row promote thành record thật, FK auto-fill từ entity cha.

Khi nào dùng

✅ Tabular list, sort/filter/group cột, master-detail (grid con bind navigation collection).

Variants:

Tip

  • DataSourceFilter phải đủ ?$filter=.... Có thể thêm $top, $expand, $orderby.
  • Để bind grid vào navigation collection của entity cha → set FieldName thay vì Reference (vd FieldName: Lines).

Core Docs · Astro · Core.API/wwwRoot/docs