Table of Contents

Overview screens

How to create a custom overview screen using OverviewScreenBase

An overview screen shows a high-level summary of a single record — a product, a customer, a configuration entry, or any other entity. Rather than exposing every editable field, it presents key information as widgets arranged in a card layout. Each widget can link to a related list or edit screen via a View more or Manage button. An optional info bar at the top can display prominent key-value data.

OverViewScreen

When to build an overview screen

Build an overview screen when:

  • You want a read-only summary of a record before a user drills into editing.
  • Your entity has multiple related sub-lists (e.g., orders for a customer) and you want them surfaced as widgets rather than buried in an edit form.
  • You need a landing page that aggregates data from several sources in one place.

For editing a record's own fields, use an edit screen. For browsing a collection of records, use a list screen.

Required overrides

Inherit from OverviewScreenBase<TModel> in Dynamicweb.CoreUI.Screens.

Override Purpose
string GetScreenName() Title shown in the topbar
void BuildOverviewScreen() Add widgets and components to the overview

Adding widgets

Inside BuildOverviewScreen call AddComponent or AddWidget to place a component on the overview:

protected override void BuildOverviewScreen()
{
    AddComponent(myComponent, heading: "Summary", width: Group.GroupWidth.Col_12);
}

The width parameter uses Group.GroupWidth values:

Value Grid columns
Col_3 Quarter width
Col_4 One third
Col_6 Half width (default)
Col_8 Two thirds
Col_12 Full width

Worked example

A complete overview screen for a hypothetical ServiceDataModel:

using System.Collections.Generic;
using Dynamicweb.CoreUI.Actions;
using Dynamicweb.CoreUI.Actions.Implementations;
using Dynamicweb.CoreUI.Displays.Information;
using Dynamicweb.CoreUI.Displays.Widgets;
using Dynamicweb.CoreUI.Icons;
using Dynamicweb.CoreUI.Layout;
using Dynamicweb.CoreUI.Screens;

public sealed class ServiceOverviewScreen : OverviewScreenBase<ServiceDataModel>
{
    protected override string GetScreenName()
        => Model?.Name ?? "Service";

    protected override void BuildOverviewScreen()
    {
        // Info bar at the top
        SetInfobar(new InfoBar
        {
            Information = new Dictionary<string, InfoValue>
            {
                { "Status",  new InfoValue(Model?.Active ?? false) },
                { "Expires", new InfoValue(Model?.ExpiryDate) },
                { "Contact", new InfoValue(Model?.ContactEmail ?? "") },
            }
        });

        // Key details card — full width
        AddComponent(
            new CardInfo { /* ... */ },
            heading: "Details",
            width: Group.GroupWidth.Col_12);

        // Related items widget — half width each
        AddComponent(
            BuildRelatedLogsWidget(),
            heading: "Recent logs",
            width: Group.GroupWidth.Col_6);

        AddComponent(
            BuildSettingsWidget(),
            heading: "Settings",
            width: Group.GroupWidth.Col_6);
    }

    private Widget BuildRelatedLogsWidget()
    {
        return new Widget
        {
            Label = "Recent logs",
            Component = new ListDisplay
            {
                ScreenType = typeof(ServiceLogListScreen),
                Query = new ServiceLogListQuery { ServiceId = Model?.Id ?? 0 }
            },
            ContextMenu = new ContextMenu().WithActionNode(new ActionNode(
                "View all logs",
                Icon.List,
                NavigateScreenAction.To<ServiceLogListScreen>()
                    .With(new ServiceLogListQuery { ServiceId = Model?.Id ?? 0 })))
        };
    }

    private Widget BuildSettingsWidget()
    {
        return new Widget
        {
            Label = "Settings",
            Component = new InfoCardDisplay
            {
                Value = new InfoCardDisplay.InfoCardValue
                {
                    Description = Model?.Description ?? "",
                    AdditionalInfo = new Dictionary<InfoCardDisplay.InfoLabel, InfoValue>
                    {
                        { new("Max retries"),     new InfoValue(Model?.MaxRetries.ToString() ?? "") },
                        { new("Timeout"),         new InfoValue($"{Model?.TimeoutSeconds}s") },
                    }
                }
            },
            ContextMenu = new ContextMenu().WithActionNode(
                ActionBuilder.Edit<ServiceEditScreen>(
                    new ServiceByIdQuery { Id = Model?.Id ?? 0 }))
        };
    }

    protected override IEnumerable<ActionGroup>? GetScreenActions() =>
    [
        new ActionGroup
        {
            Nodes =
            [
                ActionBuilder.Edit<ServiceEditScreen>(
                    new ServiceByIdQuery { Id = Model?.Id ?? 0 }),
                new ActionNode("Run now", Icon.Play,
                    RunCommandAction.For(new ServiceRunCommand { Id = Model?.Id ?? 0 }))
            ]
        }
    ];
}

Info bar

Call SetInfobar to display key values prominently above the widget grid. InfoValue accepts several types:

Constructor argument Rendered as
string Plain text
DateTime? Formatted date
bool Checkmark or cross icon
(string, ActionBase) Clickable text with an action
SetInfobar(new InfoBar
{
    Icon = Icon.Gear,
    Information = new Dictionary<string, InfoValue>
    {
        { "Active",  new InfoValue(Model?.Active ?? false) },
        { "Created", new InfoValue(Model?.CreatedAt) },
        { "Owner",   new InfoValue("Edit owner",
            NavigateScreenAction.To<UserEditScreen>()
                .With(new UserByIdQuery { Id = Model?.OwnerId ?? 0 })) },
    }
});

Tabs on overview screens

Use the tabbed AddComponent overload to place widgets on named tabs:

AddComponent("Summary", mySummaryComponent, heading: "Key info");
AddComponent("Logs",    myLogListDisplay,   heading: "Recent activity");

If you never pass a tab name, all widgets appear on a single unnamed default tab.

Optional overrides

Override What it does
IEnumerable<ActionGroup>? GetScreenActions() Add entries to the Actions context menu
ActionBase? GetBackAction() Action for the Back button (requires ShowCloseAction = true)
bool ShowCloseAction { get; set; } Set to true in the constructor to show a Back button
public ServiceOverviewScreen()
{
    ShowCloseAction = true;
}

protected override ActionBase? GetBackAction() =>
    NavigateScreenAction.To<ServiceListScreen>()
        .With(new ServiceListQuery());

Gotchas

  • SetInfobar must be called inside BuildOverviewScreen, not in the constructor. The layout field is only initialized when GetDefinitionInternal runs.
  • Widget width is controlled at the AddComponent call, not on the widget itself. Pass width there, not on the Widget object.
  • OverviewScreenBase has no injector equivalent. To extend an overview screen from a 3rd-party assembly, use ScreenInjector<T> with OnAfter to traverse and modify the rendered layout tree. See Screen injectors.
  • Discovery is automatic. AddInManager scans all loaded assemblies — no registration is needed.
To top