💨

MudDataGrid でグルーピングに見せない後部小計 (MudBlazor)

に公開

はじめに

この記事は、以下を下敷きにしています。

https://zenn.dev/tetr4lab/articles/74bd50585434ab

https://zenn.dev/tetr4lab/articles/6b1a70ca7800ed

BlazorMudBlazorについても、そちらをご参照ください。

なお、この記事のサンプルコードは、プライバシー上の理由で、全体が(未だ)公開されていません。
あしからずご了承ください。

前提

  • .NET 8.0
  • MudBlazor 8.10.0

やりたいこと

MudDataGridで作られた表に、グループの小計を含むフッターを付けたいです。

https://mudblazor.com/components/datagrid#grouping

しかし、規定のグルーピングのような、開閉できたり内部がインデントされたりするヘッダーはいりません。
以下の「⌵ :2025/07/01 0:00:00」が規定のグループヘッダーで、内部の行はインデントされています。

階層のないフラットな\small\overset{\tinyテーブル}{行列}のまま、グループの後に小計行が挿入されている外観が作りたいです。

実装

<style>
    tr.mud-table-row>*:first-child.mud-table-cell:not(.mud-datagrid-group) { display: none; } @* グループのインデント列を隠す *@
    td.footer-cell { background-color: var(--mud-palette-background-gray); } @* フッターの背景色 *@
    .mud-table-dense * .mud-table-row .footer-cell { padding: 2px 16px 0px; } @* フッターのカラムパディング *@
</style>
<MudDataGrid T="Transaction" Items="items" ReadOnly="false" Dense Hover Elevation="0" Breakpoint="Breakpoint.None" @ref="_dataGrid"
    SortMode="SortMode.None" ColumnResizeMode="ResizeMode.Column" FixedHeader Virtualize
    QuickFilter="FilterFunc" RowClick="OnRowClickAsync"
    Height="calc(100vh - var(--mud-appbar-height) * 2 - 0.6em)" ItemSize="@((float) RowSize)"
    Groupable GroupExpanded GroupClass="d-none"
>
    <Columns>
        <TemplateColumn Grouping="true" GroupBy="@(x => x.PaymentPeriod.Date)" CellClass="d-none" />
  • グリッド定義中のGroupExpandedによって、グループは最初から開かれた状態になります。
    • GroupClass="d-none"(display:none)によって、グループヘッダー行が表示されなくなります。
  • 最初の列定義で、PaymentPeriod.Dateによってグループ化されています。
    • CellClass="d-none"によって、グループのインデント列が表示されなくなります。
    • 直前のCSSで、総ヘッダーの同じ列も表示されないようにしています。

留意点

この実装は、tr.mud-table-row>*:first-child.mud-table-cell:not(.mud-datagrid-group)をはじめとした、冒頭で使用しているCSSセレクタに依存しています。
これらは、MudBlazorの将来のバージョンでも有効であるとは限りません。
その点、非常に不安定な実装になっていますので、採用される際はご留意ください。

蛇足

  • MudTableMudDataGridを使ったことのある方はご存じだと思いますが、MudTableが、見出し、通常、編集、集計などの行種を外側のループに、列を内側のループにしてテンプレートを列挙するのに対して、MudDataGridは、列を外に種別を内にして列挙します。
    • 言い換えると、テーブルは種別毎の行テンプレが列挙され、グリッドは、それぞれが全種別を含む列テンプレが列挙されます。
  • フッターは、以下のように、列ごとにAggregateTemplateに書きます。
    • AggregateTemplateは、総フッターとグループフッターで共用されます。
    • 総フッターとグループフッターの識別方法が分からなかったため、「集計数がグリッド全体の数と同じなら総フッターでしょ」と、力押しっぽくなっているのはご愛敬です。
    • 以下では、グループフッターの「決済日」の列に、グループの「年月」を表示しています。
	<TemplateColumn AggregateDefinition="@(new AggregateDefinition<Transaction> ())" HeaderClass="px-0" CellClass="py-1 pl-0 pr-1 text-nowrap" HeaderStyle="width:2em;" FooterClass="px-0" Title="@(Transaction.Label [nameof (Transaction.PaymentDate)])">
	    <CellTemplate>
	        <MudText Typo="Typo.inherit" Style="@(context.Item.PaymentDate < ToDay ? "color: var(--mud-palette-text-disabled);" : "")">
	            @(context.Item.PaymentDate.ToString ("yyyy/MM/dd ddd"))
	        </MudText>
	    </CellTemplate>
	    <AggregateTemplate>
	        @if (context.Count () == items.Count) {
	            // 総フッター
	            <MudText Align="Align.Right" Typo="Typo.inherit" Class="d-block;">Total</MudText>
	        } else {
	            // グループフッター
	            if (context.Count () > 0) {
	                var last = context.Last ();
	                @($"{last.PaymentPeriod.Year}/{last.PaymentPeriod.Month:00}")
	            }
	        }
	    </AggregateTemplate>
	</TemplateColumn>

おわりに

CSSやjavascriptを避けたくてMudBlazorを使っているので、こういうやり方は本意ではないのですが、できてしまったのでまあいいかという感じです。

執筆者は、諸々勉強中で、MudBlazorへの理解も浅いので、「そんな面倒なことしなくても、こうすればできる」といった「車輪の再発明」になっている可能性が大いにあります。
あるいは、変化の早いMudBlazorですから、単純にできるようになるのかもしれません。

最後までお読みいただきありがとうございました。
何かお気づきの際は、是非コメントや編集リクエストにてご指摘ください。
あるいは、「それでも解らない」、「自分はこう捉えている」などといった、ご意見、ご感想も歓迎いたします。

Discussion