1. はじめに
Fluent UI Blazor
のデータグリッドでデータの追加・削除・編集、まとめて操作を行う方法をご紹介します。
2. 使用コンポーネント
本記事ではMicrosoft.FluentUI.AspNetCore.Components
を使用します。
上記の記事の導入方法で指定するコンポーネント名をMicrosoft.FluentUI.AspNetCore.Components
に変更し実施いただくことで利用できます。
3. ソースコード
本ソースコードは、プロジェクトテンプレートBlazor Web App
に含まれるServerProject\Components\Pages\Weather.razor
の実装を元にしています。
@page "/weather"
@rendermode CustomRenderingMode.InteractiveServerWithoutPrerendering
@using Microsoft.FluentUI.AspNetCore.Components
<PageTitle>Weather</PageTitle>
<h1>Weather</h1>
<FluentStack Orientation="Orientation.Horizontal" Width="1600px">
<FluentNumberField Min="-20" Max="50" @bind-Value="@(temperatureCNum)" Style="width:100px" />℃
<FluentButton Appearance="Appearance.Accent" OnClick="Create">
追加
</FluentButton>
<FluentButton Appearance="Appearance.Accent" OnClick="@(x => Update(forecasts!.Where(x => x.Selected).ToList()))" Disabled="@(forecasts!.Where(x => x.Selected).ToList().Count == 0)">
更新
</FluentButton>
<FluentButton Appearance="Appearance.Accent" OnClick="@(x => Delete(forecasts!.Where(x => x.Selected).ToList()))" Disabled="@(forecasts!.Where(x => x.Selected).ToList().Count == 0)">
削除
</FluentButton>
</FluentStack>
<FluentStack Orientation="Orientation.Horizontal" Width="1200px">
<div style="overflow-x: auto;">
<FluentDataGrid Style="height: 700px;width:1200px;overflow:auto;" TGridItem="WeatherRecord" Items="@forecasts?.OrderBy(x => x.weather.Date).AsQueryable()" GenerateHeader="GenerateHeaderOption.Sticky">
<ChildContent>
<SelectColumn TGridItem="WeatherRecord"
SelectMode="DataGridSelectMode.Multiple"
SelectFromEntireRow="true"
Property="@(e => e.Selected)"
OnSelect="@(e => e.Item.Selected = e.Selected)"
SelectAll="@(forecasts?.All(p => p.Selected))"
SelectAllChanged="@(all => forecasts?.ToList().ForEach(p => p.Selected = (all == true)))" />
<PropertyColumn Title="Date" Property="@(c => DateTimeToString(c.weather.Date.ToLocalTime()))" Align="Align.Start"/>
<PropertyColumn Title="℃" Property="@(c => c.weather.TemperatureC)" Align="Align.Start" />
<PropertyColumn Title="℉" Property="@(c => c.weather.TemperatureF)" Align="Align.Start"/>
<PropertyColumn Title="Summary" Property="@(c => GetSummariesStr(c.weather.Summary))" Align="Align.Start" />
</ChildContent>
<EmptyContent>
<FluentLabel> 該当データがありません。</FluentLabel>
</EmptyContent>
<LoadingContent>
<FluentStack Orientation="Orientation.Vertical" HorizontalAlignment="HorizontalAlignment.Center">
<FluentProgressRing Width="120px" />
</FluentStack>
</LoadingContent>
</FluentDataGrid>
</div>
</FluentStack>
@code {
public class WeatherForecast
{
public DateTime Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => (32 + (int)(TemperatureC / 0.5556));
public int Summary => GetSummaries(TemperatureC);
}
public record WeatherRecord
{
public WeatherForecast? weather { get; set; }
public bool Selected { get; set; } = false;
}
public enum summariesEnum : uint
{
Freezing = 1,
Bracing,
Chilly,
Cool,
Mild,
Warm,
Balmy,
Hot,
Sweltering,
Scorching,
Unknown = 100,
}
List<WeatherRecord>? forecasts = new List<WeatherRecord>();
int temperatureCNum { get; set; } = 0;
//表示用データを生成する
protected override async Task OnInitializedAsync()
{
if (!forecasts.Any())
{
for (int i = 0; i < 10; i++)
{
WeatherForecast tempWeather = new WeatherForecast()
{
Date = DateTime.UtcNow.AddDays(i),
TemperatureC = Random.Shared.Next(-20, 55),
};
WeatherRecord temp = new WeatherRecord() { weather = tempWeather, Selected = false };
forecasts.Add(temp);
}
}
}
//Summary判定用関数
public static int GetSummaries(int temperatureC)
{
if (-20 <= temperatureC && temperatureC <= -1)
{
//Freezing
return 1;
}
if (0 <= temperatureC && temperatureC <= 5)
{
//Bracing
return 2;
}
if (6 <= temperatureC && temperatureC <= 10)
{
//Chilly
return 3;
}
if (11 <= temperatureC && temperatureC <= 15)
{
//Cool
return 4;
}
if (16 <= temperatureC && temperatureC <= 20)
{
//Mild
return 5;
}
if (21 <= temperatureC && temperatureC <= 25)
{
//Warm
return 6;
}
if (26 <= temperatureC && temperatureC <= 30)
{
//Balmy
return 7;
}
if (31 <= temperatureC && temperatureC <= 35)
{
//Hot
return 8;
}
if (36 <= temperatureC && temperatureC <= 45)
{
//Sweltering
return 9;
}
if (46 <= temperatureC && temperatureC <= 55)
{
//Scorching
return 10;
}
//Unknown
return 100;
}
//Summary表示用関数
string GetSummariesStr(int summary)
{
switch (summary)
{
case 1:
return "Freezing";
case 2:
return "Bracing";
case 3:
return "Chilly";
case 4:
return "Cool";
case 5:
return "Mild";
case 6:
return "Warm";
case 7:
return "Balmy";
case 8:
return "Hot";
case 9:
return "Sweltering";
case 10:
return "Scorching";
default:
return "Unknown";
}
}
//Dateのフォーマット用関数
string DateTimeToString(DateTime? dateTime)
{
if (dateTime == null || dateTime == DateTime.MinValue || dateTime == DateTime.MinValue.ToLocalTime())
{
return string.Empty;
}
return dateTime?.ToString("yyyy-MM-dd") ?? string.Empty;
}
//追加処理
async Task Create()
{
WeatherForecast tempWeather = new WeatherForecast()
{
Date = DateTime.UtcNow,
TemperatureC = (int)temperatureCNum,
};
WeatherRecord temp = new WeatherRecord() { weather = tempWeather, Selected = false };
forecasts.Add(temp);
}
//編集処理
async Task Update(List<WeatherRecord> weathers)
{
foreach (var weather in weathers)
{
forecasts.Remove(weather);
WeatherForecast tempWeather = new WeatherForecast()
{
Date = weather.weather.Date,
TemperatureC = (int)temperatureCNum,
};
WeatherRecord temp = new WeatherRecord() { weather = tempWeather, Selected = false };
forecasts.Add(temp);
}
}
//削除処理
async Task Delete(List<WeatherRecord> weathers)
{
foreach (var weather in weathers)
{
forecasts.Remove(weather);
}
}
}
4. 解説
4.1 複数操作
<SelectColumn TGridItem="WeatherRecord"
SelectMode="DataGridSelectMode.Multiple"
SelectFromEntireRow="true"
Property="@(e => e.Selected)"
OnSelect="@(e => e.Item.Selected = e.Selected)"
SelectAll="@(forecasts?.All(p => p.Selected))"
SelectColumn
でチェックボックスの表示・選択状態の取得を行っています。
全選択用チェックボックスはヘッダーに生成されます。
プロパティ | 説明 |
---|---|
TGridItem | SelectColumnが扱う型を指定する |
SelectMode | チェックボックスが単一選択か複数選択かを指定する |
SelectFromEntireRow | チェックボックスの全選択に対応するかを指定する |
Property | 選択状態を指定された値にバインドする |
OnSelect | チェックされたときの動作を指定する |
SelectAll | 全選択が行われているかをチェックする |
4.2 追加
<FluentButton Appearance="Appearance.Accent" OnClick="Create">
追加
</FluentButton>
<FluentNumberField Min="-20" Max="50" @bind-Value="@(temperatureCNum)" Style="width:100px"/>℃
async Task Create()
{
WeatherForecast tempWeather = new WeatherForecast()
{
Date = DateTime.UtcNow,
TemperatureC = (int)temperatureCNum,
};
WeatherRecord temp = new WeatherRecord() { weather = tempWeather, Selected = false };
forecasts.Add(temp);
}
FluentNumberField
で指定したTemperatureC(℃)
を実行時の日時で登録します。
TemperatureF(℉)
・Summary
はTemperatureC(℃)
を元に算出します。
4.3 更新
<FluentButton Appearance="Appearance.Accent" OnClick="@(x => Update(forecasts!.Where(x => x.Selected).ToList()))" Disabled="@(forecasts!.Where(x => x.Selected).ToList().Count == 0)">
更新
</FluentButton>
<FluentNumberField Min="-20" Max="50" @bind-Value="@(temperatureCNum)" Style="width:100px"/>℃
async Task Update(List<WeatherRecord> weathers)
{
foreach (var weather in weathers)
{
forecasts.Remove(weather);
WeatherForecast tempWeather = new WeatherForecast()
{
Date = weather.weather.Date,
TemperatureC = (int)temperatureCNum,
};
WeatherRecord temp = new WeatherRecord() { weather = tempWeather, Selected = false };
forecasts.Add(temp);
}
}
チェックボックスで選択した項目をFluentNumberField
で指定したTemperatureC(℃)
を元に更新します。
チェックボックスでなにも選択していない場合は、Disabled
によって更新ボタンが無効になります。
4.4 削除
<FluentButton Appearance="Appearance.Accent" OnClick="@(x => Delete(forecasts!.Where(x => x.Selected).ToList()))" Disabled="@(forecasts!.Where(x => x.Selected).ToList().Count == 0)">
async Task Delete(List<WeatherRecord> weathers)
{
foreach (var weather in weathers)
{
forecasts.Remove(weather);
}
}
チェックボックスで選択した項目を削除します。
チェックボックスでなにも選択していない場合は、Disabled
によって削除ボタンが無効になります。
5. おわりに
Fluent UI Blazor
を使用することで、様々なデータの操作を行うことができるデータグリッドを簡単に実装することができました。
Fluent UI Blazor
に関する以下の記事も見ていただけると嬉しいです!
6. 参考