MudDataGrid でグルーピングに見せない後部小計 (MudBlazor)
はじめに
この記事は、以下を下敷きにしています。
BlazorやMudBlazorについても、そちらをご参照ください。
なお、この記事のサンプルコードは、プライバシー上の理由で、全体が(未だ)公開されていません。
あしからずご了承ください。
前提
- .NET 8.0
- MudBlazor 8.10.0
やりたいこと
MudDataGrid
で作られた表に、グループの小計を含むフッターを付けたいです。
しかし、規定のグルーピングのような、開閉できたり内部がインデントされたりするヘッダーはいりません。
以下の「⌵ :2025/07/01 0:00:00」が規定のグループヘッダーで、内部の行はインデントされています。
階層のないフラットな
実装
<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の将来のバージョンでも有効であるとは限りません。
その点、非常に不安定な実装になっていますので、採用される際はご留意ください。
蛇足
-
MudTable
とMudDataGrid
を使ったことのある方はご存じだと思いますが、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