MainGrid
The MainGrid component is a standalone grid for displaying Dataverse records. Unlike SubGrid, it does not require a parent RecordContext — it loads records directly from a specified table or view.
Loading by Table Name
Set the TableName parameter to automatically load all public views for that table. The first default view is selected initially.
<MainGrid TableName="contact" />
Loading by View IDs
Use ViewIds and DefaultViewId to control exactly which views are available and which one is selected on load. You can also provide CustomViewDefinitions with inline FetchXML to define views directly in code.
<MainGrid ViewIds="_viewIds"
DefaultViewId="@(new Guid("..."))">
</MainGrid>
@code {
private List<Guid> _viewIds = new List<Guid>
{
new Guid("..."),
new Guid("..."),
};
}
Custom Views with FetchXML
Use CustomViewDefinitions to define views with custom FetchXML queries. This is useful for views that include filters based on the current user, linked entities, or other dynamic criteria.
Note
The
Idfor a customGridViewDefinitionmust be a unique random GUID that does not correspond to an existing Dataverse view. If it matches an existing view ID, the Dataverse view will take precedence and the custom definition will be ignored.
private List<GridViewDefinition> _customViews = new List<GridViewDefinition>
{
new GridViewDefinition
{
Id = new Guid("..."),
TableName = "contact",
FetchXml = @"<fetch>
<entity name='contact'>
<attribute name='fullname' />
<attribute name='emailaddress1' />
<order attribute='fullname' />
</entity>
</fetch>",
Columns = new List<ViewColumn>
{
new ViewColumn { ColumnName = "fullname", Width = 200 },
new ViewColumn { ColumnName = "emailaddress1", Width = 250 },
}
}
};
Toolbar Buttons
The MainGrid supports the same toolbar buttons as SubGrid. For standalone grids, NavigateNewRecordGridButton and NavigateEditRecordGridButton are commonly used to navigate to separate form pages. See the Grid Buttons documentation for a complete reference of all available buttons and their configuration options.
<MainGrid TableName="contact">
<Buttons>
<NavigateNewRecordGridButton Url="/contacts/new" />
<NavigateEditRecordGridButton Url="/contacts/edit?contactId={0}" />
</Buttons>
</MainGrid>
Search Box Behavior
When the user types in the grid's search box, the configured view is automatically re-queried with additional filter conditions applied to every search-eligible column shown in the view. The conditions are joined with OR logic, so a record is included if any of its visible columns match the search term. The default match semantics differ depending on the column type.
Text and Lookup Columns
Text columns (string fields) and lookup columns (matched against the target record's primary name) use a starts with search by default. Typing joh matches values that begin with joh — for example John or Johnson. The match is delegated to FetchXML's like operator, which is case-insensitive in Dataverse.
Use * as a wildcard for more flexible matching. Typing *hn performs a contains-style match (e.g. John, Johnson); typing j*n matches values where any characters can appear between the j and the n (e.g. John, Joneson). The wildcard is converted to FetchXML's % wildcard at query time.
Numeric and Money Columns
Numeric columns — int, big int, decimal, double, and money — support comparison operators in the search term. The search box parses an optional leading operator and applies the corresponding FetchXML condition operator:
= 100or just100— equal (the default when no operator is specified)> 100— greater than< 100— less than>= 100— greater than or equal<= 100— less than or equal
Note
Search conditions for every column type are added to the same
ORfilter group, so the same search term is evaluated against text columns, lookup columns, and numeric columns simultaneously. Typing100in a grid that has both a name column and an amount column will match records whose name starts with100or whose amount equals 100. The search filter is layered on top of the view's existing filter, so view-level constraints (such as astatecode = 0filter) are always preserved.
Disabling Search
Set AllowSearch="false" on the grid to hide the search box entirely. This is useful for grids that contain only a small fixed set of records, or where filtering is handled externally (for example via OnBeforeQuery or a custom toolbar).
<MainGrid TableName="contact" AllowSearch="false" />
Full Size Mode
Set FullSize="true" to make the grid expand to fill the full height of its parent container. This is useful when the grid is the main content of a page.
<PageLayout>
<Body>
<MainGrid TableName="contact" FullSize="true" />
</Body>
</PageLayout>
Persisting the Selected View
Use SelectedViewQueryParameter to persist the currently selected view ID to a URL query parameter. This allows the selected view to be preserved when navigating back to the page.
<MainGrid TableName="contact"
SelectedViewQueryParameter="viewId" />
Multi-Table Grids
A MainGrid can display views from different tables by including view IDs from multiple tables in the ViewIds collection. When the user switches views, the grid automatically loads the correct table's data. Use the OnClick callback on navigation buttons to dynamically set the URL based on the selected view's table name.
<MainGrid ViewIds="_viewIds"
CustomViewDefinitions="_customViews"
DefaultViewId="@(new Guid(AllContactsViewId))">
<Buttons>
<NavigateNewRecordGridButton OnClick="OnNewClick" />
<NavigateEditRecordGridButton OnClick="OnEditClick" />
</Buttons>
</MainGrid>
@code {
private async Task OnNewClick(NavigateGridButtonContext ctx)
{
ctx.Url = ctx.GridContext.SelectedView.TableName switch
{
"contact" => "/contacts/new",
"account" => "/accounts/new",
_ => throw new Exception("Unknown table"),
};
}
private async Task OnEditClick(NavigateGridButtonContext ctx)
{
ctx.Url = ctx.GridContext.SelectedView.TableName switch
{
"contact" => "/contacts/edit?id={0}",
"account" => "/accounts/edit?id={0}",
_ => throw new Exception("Unknown table"),
};
}
}
Filtering with OnBeforeQuery
Use the OnBeforeQuery parameter to apply additional filter criteria to the FetchXML query before it is executed. The callback receives a FetchXMLBuilder and must return it after applying any modifications. This is called after all built-in search, sort, and paging logic has been applied.
<MainGrid TableName="contact"
OnBeforeQuery="ApplyContactFilter" />
@code {
private Task<FetchXMLBuilder> ApplyContactFilter(FetchXMLBuilder fetchXmlBuilder)
{
var filter = fetchXmlBuilder.Fetch.Entity.AddFilter();
var condition = filter.AddCondition();
condition.Column = "statecode";
condition.Operator = ConditionOperator.Equal;
condition.Value = "0";
return Task.FromResult(fetchXmlBuilder);
}
}
Tip
The
OnBeforeQuerycallback is ideal for applying context-specific filters such as restricting records to a specific status, the current user, or a parent record. Because filters are applied at the query level, filtered-out records are never retrieved from Dataverse.
MainGrid Class
Parameters
Name | Type | Default | Description |
|---|---|---|---|
AllowChangingItemsPerPage | bool | True | When true, the user can change the number of items displayed per page. |
AllowEdit | bool | False | Should the option be available for the user to turn on inline editing for the grid. |
AllowEditOnRowDoubleClick | bool | True | If a button is present that has the set to true, and this is set to 'true', then the event delegate will be called for the record. |
AllowSearch | bool | True | Should the user be allowed to search the grid. |
BorderVisible | bool | True | Controls whether a visible border is rendered around the grid. |
Buttons | RenderFragment? | Optional render fragment used to define the button toolbar displayed above the grid. | |
CustomViewDefinitions | List<GridViewDefinition>? | Custom views to display in the dropdown. | |
DefaultItemsPerPage | int | 50 | Default number of records to load on a page. |
DefaultViewId | Guid? | Id of the view that the grid should display upon initial load. | |
Editable | bool | False | Is inline editing turned on for the grid. |
FullSize | bool | False | When true, the grid expands to fill all available vertical space instead of using a fixed minimum height. |
HidePaging | bool | False | Force the page size and paging components to be hidden. Only do this when the number of items is known and the page size is set to something greater than the item count. |
IsDirty | bool | False | Indicates whether the grid has unsaved create, update, or delete operations pending. |
MaxHeight | string? | Max Height that the grid control should expand to. | |
MinHeight | string? | 250px | Minimum height that the grid control should occupy. |
Mode | GridMode | RecordSelection | Sets the behavioural mode of the grid, such as default interaction or record-selection mode. |
OnBeforeQuery | Func<FetchXMLBuilder, Task<FetchXMLBuilder>>? | Optional callback to apply additional filter criteria to the FetchXML query before it is executed. | |
PageSizes | IEnumerable<int> | Collection of available page sizes for the grid. | |
PagingMode | GridPagingMode | Paged | Determines whether the grid uses traditional paging or infinite-scroll virtualisation. |
SelectedRecords | IEnumerable<TableRecord> | Records that are currently selected in the Grid. | |
SelectedViewQueryParameter | string? | Query parameter to persist the selected view to. | |
SelectFromEntireRow | bool | True | When true, clicking anywhere on a row selects it; when false, only the checkbox selects the row. |
SelectMode | DataGridSelectMode | Multiple | Controls whether the grid allows single or multiple row selection. |
TableName | string? | The logical name of the table whose public views should be loaded. Only applicable when no values are specified for or . | |
Title | string? | Name to display when the view dropdown is not displayed. | |
ViewIds | IEnumerable<Guid>? | List of id's of the views that the grid should limit to in the view dropdown. | |
ViewSort | ViewSort | NameAscending | Sort order of the views in the view dropdown. |
AllowChangingItemsPerPageAllowEditAllowEditOnRowDoubleClickand this is set to 'true', then the event delegate will be called for the record.
AllowSearchBorderVisibleButtonsCustomViewDefinitionsDefaultItemsPerPageDefaultViewIdEditableFullSizeHidePagingOnly do this when the number of items is known and the page size is set to something greater than the item count.
IsDirtyMaxHeightMinHeightModeOnBeforeQueryPageSizesPagingModeSelectedRecordsSelectedViewQueryParameterSelectFromEntireRowSelectModeTableNameTitleViewIdsViewSortEvents
Name | Type | Description |
|---|---|---|
EditableChanged | EventCallback<bool> | Callback invoked when the inline editing state changes. |
SelectedRecordsChanged | EventCallback<IEnumerable<TableRecord>> | Callback invoked when the selected records collection changes. |
EditableChangedSelectedRecordsChangedMethods
Name | Parameters | Type | Description |
|---|---|---|---|
ClearSelectionAsync | Task | Clears all currently selected rows. | |
RefreshAsync | bool forceRefresh | Task | Instructs the grid to re-fetch and render the current data from the supplied data source. |
Validate | bool | Validates all editable rows in the grid. |
ClearSelectionAsyncRefreshAsyncValidate