- 
はじめに - 記事の目的と背景
 VS Code と .NET8/9 を利用して、Blazor Bootstrap プロジェクトを構築したときの備忘録
 Blazor Bootstrap を利用したかった理由としては、PDF Viewer コンポーネントを簡単に利用したかったから。
- 想定読者
 Blazor Bootstrap を利用したプロジェクトを VS Code と .NET8/9 で構築したい人向け。
 
- 記事の目的と背景
- 
環境・前提条件 - 
使用したOS/バージョン 
 Windows11
- 
開発環境(IDE、ライブラリ、クラウドなど) 
 Windows11, VS Code
- 
前提知識や準備しておくべきこと 
 .Net8/9 のインストール
 VS Code のインストール
 Blazor Bootstrap プロジェクトの作成
 
- 
- 
準備 Blazor Page の追加 - メニューにページを追加
 MainLayout.razor のメニューリストに追加
 navItems = new List<NavItem> { new NavItem { Id = "1", Href = "/", IconName = IconName.HouseDoorFill, Text = "Home", Match=NavLinkMatch.All}, new NavItem { Id = "2", Href = "/counter", IconName = IconName.PlusSquareFill, Text = "Counter"}, new NavItem { Id = "3", Href = "/weather", IconName = IconName.Table, Text = "Fetch Data"}, new NavItem { Id = "4", Href = "/pdfview", IconName = IconName.Table, Text = "PDF View"}, new NavItem { Id = "5", Href = "/barChartView", IconName = IconName.BarChart, Text = "Bar Chart View"}, };Pages フォルダに BarChartView.razor ファイルを追加する。 
- メニューにページを追加
- 
Chart の表示 - コンポーネントの貼り付け
 PdfView.razor ファイルにコードを記述する。
 @page "/barChartView" <BarChart @ref="barChart" Width="500" Height="300" /> <div class="mt-5"> <Button Type="ButtonType.Button" Color="ButtonColor.Primary" Size="ButtonSize.Small" @onclick="async () => await RandomizeAsync()"> Randomize </Button> <Button Type="ButtonType.Button" Color="ButtonColor.Primary" Size="ButtonSize.Small" @onclick="async () => await AddDatasetAsync()"> Add Dataset </Button> <Button Type="ButtonType.Button" Color="ButtonColor.Primary" Size="ButtonSize.Small" @onclick="async () => await AddDataAsync()">Add Data</Button> <Button Type="ButtonType.Button" Color="ButtonColor.Primary" Size="ButtonSize.Small" @onclick="async () => await ShowHorizontalBarChartAsync()">Horizontal Bar Chart</Button> <Button Type="ButtonType.Button" Color="ButtonColor.Primary" Size="ButtonSize.Small" @onclick="async () => await ShowVerticalBarChartAsync()">Vertical Bar Chart</Button> </div> @code { private BarChart barChart = default!; private BarChartOptions barChartOptions = default!; private ChartData chartData = default!; private int datasetsCount = 0; private int labelsCount = 0; private string[] months = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; private Random random = new(); protected override void OnInitialized() { chartData = new ChartData { Labels = GetDefaultDataLabels(6), Datasets = GetDefaultDataSets(3) }; barChartOptions = new BarChartOptions { Responsive = true, Interaction = new Interaction { Mode = InteractionMode.Index } }; } protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { await barChart.InitializeAsync(chartData, barChartOptions); } await base.OnAfterRenderAsync(firstRender); } private async Task RandomizeAsync() { if (chartData is null || chartData.Datasets is null || !chartData.Datasets.Any()) return; var newDatasets = new List<IChartDataset>(); foreach (var dataset in chartData.Datasets) { if (dataset is BarChartDataset barChartDataset && barChartDataset is not null && barChartDataset.Data is not null) { var count = barChartDataset.Data.Count; var newData = new List<double?>(); for (var i = 0; i < count; i++) { newData.Add(random.Next(200)); } barChartDataset.Data = newData; newDatasets.Add(barChartDataset); } } chartData.Datasets = newDatasets; await barChart.UpdateAsync(chartData, barChartOptions); } private async Task AddDatasetAsync() { if (chartData is null || chartData.Datasets is null) return; if (datasetsCount >= 12) return; var chartDataset = GetRandomBarChartDataset(); chartData = await barChart.AddDatasetAsync(chartData, chartDataset, barChartOptions); } private async Task AddDataAsync() { if (chartData is null || chartData.Datasets is null) return; if (labelsCount >= 12) return; var data = new List<IChartDatasetData>(); foreach (var dataset in chartData.Datasets) { if (dataset is BarChartDataset barChartDataset) data.Add(new BarChartDatasetData(barChartDataset.Label, random.Next(200))); } chartData = await barChart.AddDataAsync(chartData, GetNextDataLabel(), data); } private async Task ShowHorizontalBarChartAsync() { barChartOptions.IndexAxis = "y"; await barChart.UpdateAsync(chartData, barChartOptions); } private async Task ShowVerticalBarChartAsync() { barChartOptions.IndexAxis = "x"; await barChart.UpdateAsync(chartData, barChartOptions); } #region Data Preparation private List<IChartDataset> GetDefaultDataSets(int numberOfDatasets) { var datasets = new List<IChartDataset>(); for (var index = 0; index < numberOfDatasets; index++) { datasets.Add(GetRandomBarChartDataset()); } return datasets; } private BarChartDataset GetRandomBarChartDataset() { var c = ColorUtility.CategoricalTwelveColors[datasetsCount].ToColor(); datasetsCount += 1; return new BarChartDataset() { Label = $"Product {datasetsCount}", Data = GetRandomData(), BackgroundColor = new List<string> { c.ToRgbString() }, BorderColor = new List<string> { c.ToRgbString() }, BorderWidth = new List<double> { 0 }, }; } private List<double?> GetRandomData() { var data = new List<double?>(); for (var index = 0; index < labelsCount; index++) { data.Add(random.Next(200)); } return data; } private List<string> GetDefaultDataLabels(int numberOfLabels) { var labels = new List<string>(); for (var index = 0; index < numberOfLabels; index++) { labels.Add(GetNextDataLabel()); } return labels; } private string GetNextDataLabel() { labelsCount += 1; return months[labelsCount - 1]; } #endregion Data Preparation }
- コンポーネントの貼り付け
簡単ですね。
- 
ハマったポイント・トラブルシューティング - 
実際に遭遇したエラーや課題 
 最初ビューの名前を BarChart という名前にしたのですが、コンポーネント名とクラス名が同じになるので定義があいまいになるので異なる名前で作成しなおしました。
- 
解決方法と参考リンク 
 
- 
- 
使ってみた感想 - 良かった点/イマイチだった点
 コンポーネントの貼り付けだけで簡単にマークダウンを挿入できます。エディタにもなります。非常に簡単ですね。
 
- 良かった点/イマイチだった点
- 
まとめ - 
記事の総括 
 今回はマークダウンをrazorページ内に埋め込みを行いました。
 Blazor のソースコードはやはりシンプルでよいです。
 簡単にコピペして動作確認できますね。
 今後、chart や grid を使った記事を書いていく予定。
- 
参考資料のリンク 
 Blazor Bootstrap のセットアップマニュアル(getting started)
 https://demos.blazorbootstrap.com/getting-started
 
- 

