Back to Devexpress

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

expressappframework-403531-analytics-dashboards-open-a-detail-view-when-the-grid-row-is-clicked-in-the-dashboard-blazor.md

latest8.2 KB
Original Source

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

  • Jul 09, 2025
  • 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.

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:

registerControllerStores a reference to the server-side Controller that calls this method.processItemClickA 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.onBeforeRenderRegisters processItemClick as a callback that the Dashboard control invokes when a user clicks a grid row.

js
"use strict";

globalThis.customScript = {
    showDetailViewControllers: {},
    onBeforeRender: function (dashboardControl) {
        const viewerApi = dashboardControl.findExtension("viewerApi");
        viewerApi.on("itemClick", globalThis.customScript.processItemClick.bind(dashboardControl));
    },
    registerController: function (key, controller) {
        globalThis.customScript.showDetailViewControllers[key] = controller;
    },
    unregisterController: function (key) {
        delete globalThis.customScript.showDetailViewControllers[key];
    },
    processItemClick: function (args) {
        const itemData = args.getData(),
            dataSlice = itemData.getSlice(args.getAxisPoint()),
            oidMeasure = dataSlice.getMeasures().find((measure) => measure.dataMember === 'ID').id,
            measureValue = dataSlice.getMeasureValue(oidMeasure),
            objectId = measureValue.getValue(),
            controllerId = this.element().dataset["showdetailid"];
        globalThis.customScript.showDetailViewControllers[controllerId].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.

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

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

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

Declare a BlazorShowDetailViewFromDashboardController ObjectViewController<ViewType, ObjectType> with the DetailView and IDashboardData generic parameters in the ASP.NET Core Blazor application project (MySolution.Blazor.Server). Customize the Controller as outlined below:

csharp
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Dashboards.Blazor.Components;
using DevExpress.Persistent.Base;
using OpenViewFromDashboardEF.Module.BusinessObjects;
using Microsoft.JSInterop;

namespace OpenViewFromDashboard.Blazor.Server.Controllers;
public class BlazorShowDetailViewFromDashboardController : ObjectViewController<DetailView, IDashboardData> {
    private string clientId = Guid.NewGuid().ToString();
    private DotNetObjectReference<BlazorShowDetailViewFromDashboardController> controllerReference;
    public BlazorShowDetailViewFromDashboardController() {
        controllerReference = DotNetObjectReference.Create(this);
    }
    protected override void OnActivated() {
        base.OnActivated();
        Application.ServiceProvider.GetRequiredService<IJSRuntime>().InvokeVoidAsync("customScript.registerController", clientId, controllerReference).Preserve();
        View.CustomizeViewItemControl<BlazorDashboardViewerViewItem>(this, CustomizeDashboardViewerViewItem);
    }
    private void CustomizeDashboardViewerViewItem(BlazorDashboardViewerViewItem dashboardViewerViewItem) {
        dashboardViewerViewItem.ComponentModel.SetAttribute("data-showdetailid", clientId);
    }
    protected override void OnDeactivated() {
        Application.ServiceProvider.GetRequiredService<IJSRuntime>().InvokeVoidAsync("customScript.unregisterController", clientId).Preserve();
        base.OnDeactivated();
    }
    protected override void Dispose(bool disposing) {
        base.Dispose(disposing);
        controllerReference.Dispose();
    }
    [JSInvokable]
    public void ShowDetailView(string oidString) {
        if(!Guid.TryParse(oidString, out var id)) {
            return;
        }
        var objectSpace = Application.CreateObjectSpace(typeof(Contact));
        var item = objectSpace.FirstOrDefault<Contact>(c => c.ID == id);
        if(item is not null) {
            var detailView = Application.CreateDetailView(objectSpace, item, true);
            Application.ShowViewStrategy.ShowViewFromCommonView(detailView);
        } else {
            objectSpace.Dispose();
        }
    }
}

See Also

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