Skip to main content
A newer version of this page is available. .
All docs
V21.2
.NET Standard 2.0+

Open a Detail View When the Grid Row is Clicked in the Dashboard (Blazor)

  • 4 minutes to read

This topic describes how to invoke a Detail View when a user clicks a row in GridDashboardItem. In the invoked Detail View, a user can view or edit a business object corresponding to the clicked row.

This example consists of the following parts:

View Example: Open a Detail View When the Grid Row is Clicked in the Dashboard (Blazor)

Add a Dashboard Hidden Measure

Add a key property to the Dashboard hidden measures and set the summary type to Min or Max. The key property in this example is Oid. Since Oid values are unique in the underlying dataset, the Min or Max function generates a list of identifiers that are unique within the aggregated data. This associates each row with Oid of the underlying object.

DashboardDesigner_OidMeasure_Web

Create a Client-Side Script

In your Blazor application project (MySolution.Blazor.Server), add a new JavaScript file to the wwwroot/js folder. In this file, declare an object (customScript) and implement the following methods in it:

registerController
Stores a reference to the server-side Controller that calls this method.
processItemClick
A callback that retrieves the ID of the object clicked in the Dashboard grid item and passes this ID to the server-side Controller’s ShowDetailView method.
onBeforeRender
Registers processItemClick as a callback that the Dashboard control invokes when a user clicks a grid row.

File: MySolution.Blazor.Server\wwwroot\js\customScript.js.

"use strict";

globalThis.customScript = {
    showDetailViewController: null,
    onBeforeRender: function (dashboardControl) {
        const viewerApi = dashboardControl.findExtension("viewerApi");
        viewerApi.on("itemClick", globalThis.customScript.processItemClick);
    },
    registerController: function (controller) {
        globalThis.customScript.showDetailViewController = controller;
    },
    processItemClick: function (args) {
        const itemData = args.getData(),
            dataSlice = itemData.getSlice(args.getAxisPoint()),
            oidMeasure = dataSlice.getMeasures().find((measure) => measure.dataMember === 'Oid').id,
            measureValue = dataSlice.getMeasureValue(oidMeasure),
            objectId = measureValue.getValue();
        globalThis.customScript.showDetailViewController.invokeMethodAsync("ShowDetailView", objectId);
    }
}

In the same file, create the globalThis.xafBlazorDashboardUserScripts array if it does not exist and add the customScript object to it. This ensures that the object’s onBeforeRender method is called before the Dashboard control is rendered.

File: MySolution.Blazor.Server\wwwroot\js\customScript.js.

// ...
if (!globalThis.xafBlazorDashboardUserScripts) {
    globalThis.xafBlazorDashboardUserScripts = [];
}
globalThis.xafBlazorDashboardUserScripts.push(globalThis.customScript);

Reference this script in the _Host.cshtml file in a <script> tag:

File: MySolution.Blazor.Server\Pages\_Host.cshtml.

<!-- ... -->
<html lang="en">
<!-- ... -->
<body>
    <!-- ... -->
    <script src="_framework/blazor.server.js"></script>
    <script src="js/customScript.js"></script>
    <!-- ... -->
</body>
</html>

Create a Server-Side Controller

In the Blazor-specific Module project (MySolution.Module.Blazor), declare a BlazorShowDetailViewFromDashboardController ObjectViewController<ViewType, ObjectType> with the DetailView and IDashboardData generic parameters. Customize the Controller as outlined below:

  • Create a DotNetObjectReference that stores the reference to this Controller.
  • In the overridden OnActivated method, use the IJSRuntime service to register a reference to this Controller on the client side. To do this, call the customScript.registerController method with this reference.
  • Declare the ShowDetailView method and decorate it with the JSInvokable attribute. This method is called from the client side and opens the Detail View for the clicked object.

File: MySolution.Module.Blazor\Controllers\BlazorShowDetailViewFromDashboardController.cs.

using System;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Blazor;
using DevExpress.Persistent.Base;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.JSInterop;
// ...
public class BlazorShowDetailViewFromDashboardController : ObjectViewController<DetailView, IDashboardData> {
    private IJSRuntime JSRuntime { get; set; }
    private DotNetObjectReference<BlazorShowDetailViewFromDashboardController> controllerReference;
    public BlazorShowDetailViewFromDashboardController() {
        controllerReference = DotNetObjectReference.Create(this);
    }
    protected override void OnActivated() {
        base.OnActivated();
        var application = (BlazorApplication)Application;
        JSRuntime = application.ServiceProvider.GetRequiredService<IJSRuntime>();
        _ = JSRuntime.InvokeVoidAsync("customScript.registerController", controllerReference).Preserve();
    }
    protected override void Dispose(bool disposing) {
        base.Dispose(disposing);
        controllerReference.Dispose();
    }
    [JSInvokable]
    public void ShowDetailView(string oidString) {
        if(!Guid.TryParse(oidString, out var oid)) {
            return;
        }
        var objectSpace = Application.CreateObjectSpace(typeof(Employee));
        var item = objectSpace.FirstOrDefault<Employee>(employee => employee.Oid == oid);
        if(item is not null) {
            var detailView = Application.CreateDetailView(objectSpace, item);
            Frame.SetView(detailView);
        }
        else {
            objectSpace.Dispose();
        }
    }
}
See Also