ひとりでのアプリ開発 - fineの備忘録 -

ひとりでアプリ開発をするなかで起こったことや学んだことを書き溜めていきます

Blazor - UIフレームワーク「Radzen Blazor」の導入

初めに

 本記事では、Blazor WebAssembly アプリケーションに UI フレームワーク「Radzen Blazor」を導入する方法をまとめます。

導入の手順

NuGet パッケージマネージャーから「Radzen.Blazor」をインストール


_Imports.razor ファイルの編集

 .Client > Shared フォルダ > _Imports.razor ファイルに、下記を追加します。

@using Radzen
@using Radzen.Blazor
index.html の編集

 .Client > wwwroot > index.html ファイルを次のように編集します。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
    <title>Memorandum</title>
    <base href="/" />
    
    <!-- UIフレームワーク「boostrap」追加用, デフォルトのフレームワーク -->
    <link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
    <link href="css/app.css" rel="stylesheet" />
    <link rel="icon" type="image/png" href="favicon.png" />

     <!-- 以下の2行を追加,  UIフレームワーク「Radzen Blazor」テーマを追加 -->
    <link href="Memorandum.Client.styles.css" rel="stylesheet" />
    <link rel="stylesheet" href="_content/Radzen.Blazor/css/standard-base.css">  <!-- スタイルシートを追加 -->
</head>

<body>
    <div id="app">
        <svg class="loading-progress">
            <circle r="40%" cx="50%" cy="50%" />
            <circle r="40%" cx="50%" cy="50%" />
        </svg>
        <div class="loading-progress-text"></div>
    </div>

    <div id="blazor-error-ui">
        An unhandled error has occurred.
        <a href="" class="reload">Reload</a>
        <a class="dismiss">🗙</a>
    </div>
    <script src="_content/Microsoft.AspNetCore.Components.WebAssembly.Authentication/AuthenticationService.js"></script>
    <script src="_framework/blazor.webassembly.js"></script>

    <!-- 以下の1行を追加, Radzen.Blazor.js をインクルード -->
    <script src="_content/Radzen.Blazor/Radzen.Blazor.js"></script>
</body>

</html>

 別のテーマを使いたい場合は、スタイルシートの "standard-base" の部分を変更します。

(例)

<link rel="stylesheet" href="_content/Radzen.Blazor/css/material-base.css">

 これで導入は終了です。

テスト

 Index.razor に RadzenButton を追加して導入されているかテストしてみましょう。

@page "/"

<PageTitle>Index</PageTitle>

<h1>Hello, world!</h1>

Welcome to your new app.

<SurveyPrompt Title="How is Blazor working for you?" />

<!-- 以下を追加 -->
<RadzenButton Click="@ButtonClicked" Icon="account_circle" Text="Test"></RadzenButton>

@code {
    void ButtonClicked()
    {
        //
    }
}

(実行)

UI の例

 UI の例をいくつか載せておきます。ほかの UI については、参考にリンクを載せた公式サイトをご覧ください。

RadzenButton


<RadzenButton Click="@ButtonClicked" Icon="account_circle" Text="Test"></RadzenButton>

<RadzenButton Text="Click me!" class="rz-ripple" />

@code {
    void ButtonClicked()
    {
        //
    }
}
RadzenIcon


    <div><RadzenIcon Icon="facebook" /><span>facebook</span></div>
    <div><RadzenIcon Icon="accessibility" /><span>accessibility</span></div>
    <div><RadzenIcon Icon="3d_rotation" /><span>3d_rotation</span></div>
    <div><RadzenIcon Icon="accessible" /><span>accessible</span></div>
    <div><RadzenIcon Icon="account_balance" /><span>account_balance</span></div>
    <div><RadzenIcon Icon="account_balance_wallet" /><span>account_balance_wallet</span></div>
    <div><RadzenIcon Icon="account_box" /><span>account_box</span></div>
    <div><RadzenIcon Icon="account_circle" /><span>account_circle</span></div>
    <div><RadzenIcon Icon="add_shopping_cart" /><span>add_shopping_cart</span></div>
    <div><RadzenIcon Icon="alarm" /><span>alarm</span></div>
    <div><RadzenIcon Icon="alarm_add" /><span>alarm_add</span></div>
    <div><RadzenIcon Icon="alarm_off" /><span>alarm_off</span></div>
    <div><RadzenIcon Icon="alarm_on" /><span>alarm_on</span></div>
    <div><RadzenIcon Icon="all_out" /><span>all_out</span></div>
    <div><RadzenIcon Icon="android" /><span>android</span></div>
    <div><RadzenIcon Icon="announcement" /><span>announcement</span></div>
    <div><RadzenIcon Icon="aspect_ratio" /><span>aspect_ratio</span></div>
    <div><RadzenIcon Icon="assessment" /><span>assessment</span></div>
    <div><RadzenIcon Icon="assignment" /><span>assignment</span></div>
    <div><RadzenIcon Icon="assignment_ind" /><span>assignment_ind</span></div>
    <div><RadzenIcon Icon="assignment_late" /><span>assignment_late</span></div>
    <div><RadzenIcon Icon="assignment_return" /><span>assignment_return</span></div>
    <div><RadzenIcon Icon="assignment_returned" /><span>assignment_returned</span></div>
    <div><RadzenIcon Icon="assignment_turned_in" /><span>assignment_turned_in</span></div>
    <div><RadzenIcon Icon="autorenew" /><span>autorenew</span></div>
    <div><RadzenIcon Icon="backup" /><span>backup</span></div>
    <div><RadzenIcon Icon="book" /><span>book</span></div>
    <div><RadzenIcon Icon="bookmark" /><span>bookmark</span></div>
    <div><RadzenIcon Icon="bookmark_border" /><span>bookmark_border</span></div>
    <div><RadzenIcon Icon="bug_report" /><span>bug_report</span></div>
    <div><RadzenIcon Icon="build" /><span>build</span></div>
    <div><RadzenIcon Icon="cached" /><span>cached</span></div>
    <div><RadzenIcon Icon="camera_enhance" /><span>camera_enhance</span></div>
    <div><RadzenIcon Icon="card_giftcard" /><span>card_giftcard</span></div>
    <div><RadzenIcon Icon="card_membership" /><span>card_membership</span></div>
    <div><RadzenIcon Icon="card_travel" /><span>card_travel</span></div>
    <div><RadzenIcon Icon="change_history" /><span>change_history</span></div>
    <div><RadzenIcon Icon="check_circle" /><span>check_circle</span></div>
    <div><RadzenIcon Icon="chrome_reader_mode" /><span>chrome_reader_mode</span></div>
    <div><RadzenIcon Icon="class" /><span>class</span></div>
    <div><RadzenIcon Icon="code" /><span>code</span></div>
    <div><RadzenIcon Icon="compare_arrows" /><span>compare_arrows</span></div>
    <div><RadzenIcon Icon="copyright" /><span>copyright</span></div>
    <div><RadzenIcon Icon="credit_card" /><span>credit_card</span></div>
    <div><RadzenIcon Icon="dashboard" /><span>dashboard</span></div>
    <div><RadzenIcon Icon="date_range" /><span>date_range</span></div>
    <div><RadzenIcon Icon="delete" /><span>delete</span></div>
    <div><RadzenIcon Icon="delete_forever" /><span>delete_forever</span></div>
    <div><RadzenIcon Icon="description" /><span>description</span></div>
    <div><RadzenIcon Icon="dns" /><span>dns</span></div>
    <div><RadzenIcon Icon="done" /><span>done</span></div>
    <div><RadzenIcon Icon="done_all" /><span>done_all</span></div>
    <div><RadzenIcon Icon="donut_large" /><span>donut_large</span></div>
    <div><RadzenIcon Icon="donut_small" /><span>donut_small</span></div>
    <div><RadzenIcon Icon="eject" /><span>eject</span></div>
    <div><RadzenIcon Icon="euro_symbol" /><span>euro_symbol</span></div>
    <div><RadzenIcon Icon="event" /><span>event</span></div>
    <div><RadzenIcon Icon="event_seat" /><span>event_seat</span></div>
    <div><RadzenIcon Icon="exit_to_app" /><span>exit_to_app</span></div>
    <div><RadzenIcon Icon="explore" /><span>explore</span></div>
    <div><RadzenIcon Icon="extension" /><span>extension</span></div>
    <div><RadzenIcon Icon="face" /><span>face</span></div>
    <div><RadzenIcon Icon="favorite" /><span>favorite</span></div>
    <div><RadzenIcon Icon="favorite_border" /><span>favorite_border</span></div>
    <div><RadzenIcon Icon="feedback" /><span>feedback</span></div>
    <div><RadzenIcon Icon="find_in_page" /><span>find_in_page</span></div>
    <div><RadzenIcon Icon="find_replace" /><span>find_replace</span></div>
    <div><RadzenIcon Icon="fingerprint" /><span>fingerprint</span></div>
    <div><RadzenIcon Icon="flight_land" /><span>flight_land</span></div>
    <div><RadzenIcon Icon="flight_takeoff" /><span>flight_takeoff</span></div>
    <div><RadzenIcon Icon="flip_to_back" /><span>flip_to_back</span></div>
    <div><RadzenIcon Icon="flip_to_front" /><span>flip_to_front</span></div>
    <div><RadzenIcon Icon="g_translate" /><span>g_translate</span></div>
    <div><RadzenIcon Icon="gavel" /><span>gavel</span></div>
    <div><RadzenIcon Icon="get_app" /><span>get_app</span></div>
    <div><RadzenIcon Icon="gif" /><span>gif</span></div>
    <div><RadzenIcon Icon="grade" /><span>grade</span></div>
    <div><RadzenIcon Icon="group_work" /><span>group_work</span></div>
    <div><RadzenIcon Icon="help" /><span>help</span></div>
    <div><RadzenIcon Icon="help_outline" /><span>help_outline</span></div>
    <div><RadzenIcon Icon="highlight_off" /><span>highlight_off</span></div>
    <div><RadzenIcon Icon="history" /><span>history</span></div>
    <div><RadzenIcon Icon="home" /><span>home</span></div>
    <div><RadzenIcon Icon="hourglass_empty" /><span>hourglass_empty</span></div>
    <div><RadzenIcon Icon="hourglass_full" /><span>hourglass_full</span></div>
    <div><RadzenIcon Icon="http" /><span>http</span></div>
    <div><RadzenIcon Icon="https" /><span>https</span></div>
    <div><RadzenIcon Icon="input" /><span>input</span></div>
    <div><RadzenIcon Icon="invert_colors" /><span>invert_colors</span></div>
    <div><RadzenIcon Icon="label" /><span>label</span></div>
    <div><RadzenIcon Icon="label_outline" /><span>label_outline</span></div>
    <div><RadzenIcon Icon="language" /><span>language</span></div>
    <div><RadzenIcon Icon="launch" /><span>launch</span></div>
    <div><RadzenIcon Icon="lightbulb_outline" /><span>lightbulb_outline</span></div>
    <div><RadzenIcon Icon="line_style" /><span>line_style</span></div>
    <div><RadzenIcon Icon="line_weight" /><span>line_weight</span></div>
    <div><RadzenIcon Icon="list" /><span>list</span></div>
    <div><RadzenIcon Icon="lock" /><span>lock</span></div>
    <div><RadzenIcon Icon="lock_open" /><span>lock_open</span></div>
    <div><RadzenIcon Icon="lock_outline" /><span>lock_outline</span></div>
    <div><RadzenIcon Icon="loyalty" /><span>loyalty</span></div>
    <div><RadzenIcon Icon="markunread_mailbox" /><span>markunread_mailbox</span></div>
    <div><RadzenIcon Icon="motorcycle" /><span>motorcycle</span></div>
    <div><RadzenIcon Icon="note_add" /><span>note_add</span></div>
    <div><RadzenIcon Icon="offline_pin" /><span>offline_pin</span></div>
    <div><RadzenIcon Icon="opacity" /><span>opacity</span></div>
    <div><RadzenIcon Icon="open_in_browser" /><span>open_in_browser</span></div>
    <div><RadzenIcon Icon="open_in_new" /><span>open_in_new</span></div>
    <div><RadzenIcon Icon="open_with" /><span>open_with</span></div>
    <div><RadzenIcon Icon="pageview" /><span>pageview</span></div>
RadzenDatePicker


<div class="rz-p-12 rz-text-align-center">
    <RadzenDatePicker TValue="DateTime?" Value=@value Change="@(args => value = args)" />
</div>

<div class="rz-p-12 rz-text-align-center">
    <RadzenDatePicker @bind-Value=@value Inline="true" />
</div>

@code {
    DateTime? value = DateTime.Now;
}
RadzenSlider


<div class="rz-p-12 rz-text-align-center">
    <RadzenSlider @bind-Value=@value TValue="int" />
</div>

@code {
    int value = 33;
}
RadzenTextArea


<div class="container-fluid">
    <div class="row px-3">
        <div class="col-md-6 col-lg-4 p-3">
            <RadzenCard>
                <RadzenText TextStyle="TextStyle.Subtitle2" TagName="TagName.H3">TextArea</RadzenText>
                <RadzenTextArea Change=@(args => OnChange(args, "TextArea")) class="w-100" />
            </RadzenCard>
        </div>
        <div class="col-md-6 col-lg-4 p-3">
            <RadzenCard>
                <RadzenText TextStyle="TextStyle.Subtitle2" TagName="TagName.H3">TextArea with placeholder</RadzenText>
                <RadzenTextArea Placeholder="Enter here..." Change=@(args => OnChange(args, "TextArea with placeholder")) class="w-100" />
            </RadzenCard>
        </div>
        <div class="col-md-6 col-lg-4 p-3">
            <RadzenCard>
                <RadzenText TextStyle="TextStyle.Subtitle2" TagName="TagName.H3">TextArea with 5 maximum characters</RadzenText>
                <RadzenTextArea MaxLength="5" Change=@(args => OnChange(args, "TextArea with 5 maximum characters")) class="w-100" />
            </RadzenCard>
        </div>
        <div class="col-md-6 col-lg-4 p-3">
            <RadzenCard Style="overflow: scroll">
                <RadzenText TextStyle="TextStyle.Subtitle2" TagName="TagName.H3">TextArea with 3 rows and 30 columns</RadzenText>
                <RadzenTextArea @bind-Value=@value Cols="30" Rows="3" Change=@(args => OnChange(args, "TextArea with 3 rows and 30 columns")) />
            </RadzenCard>
        </div>
        <div class="col-md-6 col-lg-4 p-3">
            <RadzenCard Style="overflow: scroll">
                <RadzenText TextStyle="TextStyle.Subtitle2" TagName="TagName.H3">Disabled TextArea with 3 rows and 30 columns</RadzenText>
                <RadzenTextArea Disabled="true" @bind-Value=@value Cols="30" Rows="3" />
            </RadzenCard>
        </div>
    </div>
</div>


@code {
    string value;

    void OnChange(string value, string name)
    {
        //
    }
}
RadzenChart


@using System.Globalization

<div class="container">
    <div class="row">
        <div class="col-sm-12 my-5">
            <RadzenCard class="w-100 mb-4" Style="display: flex; align-items: center; gap: 0.5rem" >
                <RadzenCheckBox @bind-Value="@smooth" Name="smooth"></RadzenCheckBox>
                <RadzenLabel Text="Smooth" For="smooth" Style="margin-right: 1rem;"/>
                <RadzenCheckBox @bind-Value="@showDataLabels" Name="dataLabels"></RadzenCheckBox>
                <RadzenLabel Text="Show Data Labels" For="dataLabels" />
            </RadzenCard>
            <RadzenChart>
                <RadzenLineSeries Smooth="@smooth" Data="@revenue2019" CategoryProperty="Date" Title="2019" LineType="LineType.Dashed" ValueProperty="Revenue">
                    <RadzenMarkers MarkerType="MarkerType.Square" />
                    <RadzenSeriesDataLabels Visible="@showDataLabels" />
                </RadzenLineSeries>
                <RadzenLineSeries Smooth="@smooth" Data="@revenue2020" CategoryProperty="Date" Title="2020" ValueProperty="Revenue">
                    <RadzenMarkers MarkerType="MarkerType.Circle" />
                    <RadzenSeriesDataLabels Visible="@showDataLabels" />
                </RadzenLineSeries>
                <RadzenCategoryAxis Padding="20" Formatter="@FormatAsMonth" />
                <RadzenValueAxis Formatter="@FormatAsUSD">
                    <RadzenGridLines Visible="true" />
                    <RadzenAxisTitle Text="Revenue in USD" />
                </RadzenValueAxis>
            </RadzenChart>
        </div>
    </div>
</div>

@code {
    bool smooth = false;
    bool showDataLabels = false;

    class DataItem
    {
        public string Date { get; set; }
        public double Revenue { get; set; }
    }

    string FormatAsUSD(object value)
    {
        return ((double)value).ToString("C0", CultureInfo.CreateSpecificCulture("en-US"));
    }

    string FormatAsMonth(object value)
    {
        if (value != null)
        {
            return Convert.ToDateTime(value).ToString("MMM");
        }

        return string.Empty;
    }

    DataItem[] revenue2019 = new DataItem[] {
        new DataItem
        {
            Date = ("2019-01-01"),
            Revenue = 234000
        },
        new DataItem
        {
            Date = ("2019-02-01"),
            Revenue = 269000
        },
        new DataItem
        {
            Date = ("2019-03-01"),
            Revenue = 233000
        },
        new DataItem
        {
            Date = ("2019-04-01"),
            Revenue = 244000
        },
        new DataItem
        {
            Date = ("2019-05-01"),
            Revenue = 214000
        },
        new DataItem
        {
            Date = ("2019-06-01"),
            Revenue = 253000
        },
        new DataItem
        {
            Date = ("2019-07-01"),
            Revenue = 274000
        },
        new DataItem
        {
            Date = ("2019-08-01"),
            Revenue = 284000
        },
        new DataItem
        {
            Date = ("2019-09-01"),
            Revenue = 273000
        },
        new DataItem
        {
            Date = ("2019-10-01"),
            Revenue = 282000
        },
        new DataItem
        {
            Date = ("2019-11-01"),
            Revenue = 289000
        },
        new DataItem
        {
            Date = ("2019-12-01"),
            Revenue = 294000
        }
    };

    DataItem[] revenue2020 = new DataItem[] {
        new DataItem
        {
            Date = ("2019-01-01"),
            Revenue = 334000
        },
        new DataItem
        {
            Date = ("2019-02-01"),
            Revenue = 369000
        },
        new DataItem
        {
            Date = ("2019-03-01"),
            Revenue = 333000
        },
        new DataItem
        {
            Date = ("2019-04-01"),
            Revenue = 344000
        },
        new DataItem
        {
            Date = ("2019-05-01"),
            Revenue = 314000
        },
        new DataItem
        {
            Date = ("2019-06-01"),
            Revenue = 353000
        },
        new DataItem
        {
            Date = ("2019-07-01"),
            Revenue = 374000
        },
        new DataItem
        {
            Date = ("2019-08-01"),
            Revenue = 384000
        },
        new DataItem
        {
            Date = ("2019-09-01"),
            Revenue = 373000
        },
        new DataItem
        {
            Date = ("2019-10-01"),
            Revenue = 382000
        },
        new DataItem
        {
            Date = ("2019-11-01"),
            Revenue = 389000
        },
        new DataItem
        {
            Date = ("2019-12-01"),
            Revenue = 394000
        }
    };
}