Blazorでコードビハインドでロジックとビューを分離して記述する

# 概要
Blazorのコンポーネントでロジックとビューを分離して記載する方法のメモ。

**2020/05/27: Partialクラスによる分離方法を追記しました。**
**2020/08/12: Partialクラスによるクラス継承を追記しました。**

# よくある記載例
Blazorのサンプルコードの多くは、下記のようにrazorファイルの中にHTML要素とバインドするC#コードを合わせて記載しています。


```csharp:counter.razor
@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
    }
}
```

このような手法とは別に、razorコンポーネントとC#コードを分離して記載するコードビハインドといった記載も可能です。今回はその方法を紹介します。


# コードビハインドでの記載方法

## モデル(C#コード)

まずは元となるC#側のコードを作成します。

```csharp:CounterModel.cs
    public class CounterModel : ComponentBase
    {
        public int CurrentCount { get; private set; }

        public void IncrementCount()
        {
            CurrentCount++;
        }
    }
```

分離しない場合の変更点としては下記になります。

- ComponentBaseクラスを継承したクラスとする。(Microsoft.AspNetCore.Components)
- ビューからバインドする変数及び関数をprivateからpublicにする。

## ビュー(razorコンポーネント)

次にrazorコンポーネント側を作成します。

```csharp:Counter.razor
@page "/counter"
@inherits CounterModel

<h1>Counter</h1>

<p>Current count: @CurrentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

```

分離しない場合のrazorコンポーネントとの違いは下記になります。

- C#コードの代わりにデータバインドするモデルクラス名をinheritsで記載する。

## DIの方法
Inject属性を付与したプロパティを使用することで依存性の注入が可能になります。
(具体的なクラスの指定は通常通りStarup.csから指定する。)

```csharp:CounterModel.cs
    public class CounterModel : ComponentBase
    {
        [Inject]
        protected IDataAccess DataRepository { get; set; }

        public int CurrentCount { get; private set; }

        public void IncrementCount()
        {
            CurrentCount++;
        }
    }
```

# Partialクラスによる分離 (2020/05/27追記)

現在のBlazorでは上記の方法とは別に分離が可能になっています。
raozrファイルと対になるようにcsのファイルを作成するだけです。

Counter.razor
**Counter.razor.cs(追加)**

razor側は、codeブロックを除いたものを記載します。

```csharp:Counter.razor
@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
```

C#コード側は、クラスをpartialクラスにする必要があります。
それ以外はrazor側に書いていた場合と同じように記載できます。
(変数やメソッドはprivateで対応可能)

```csharp:Counter.razor.cs

    public partial class Counter
    {
        private int currentCount = 0;

        private void IncrementCount()
        {
            currentCount++;
        }
    }
```
## Partialクラスによる継承 (2020/08/12追記)

基底のクラスを作り、継承させたい場合には下記の2つの対応が必要です。

- razor側はinheritsで継承
- cs側はクラスを継承

```csharp:Counter.razor
@page "/counter"
@inherits ComponentBase

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
```

```csharp:Counter.razor.cs

    public partial class Counter : ComponentBase
    {
        private int currentCount = 0;

        private void IncrementCount()
        {
            currentCount++;
        }
    }
```


# まとめ
簡単にですが、Blazorにおけるコードビハインドの方法を紹介しました。
ロジックとビューを分離することで、下記のようなメリットなどが得られます。

- ロジックに対するUnitTestの記載が可能
- 基底のコンポーネントクラスの作成などによる共通処理の作成

# 参考資料


https://www.telerik.com/blogs/using-a-code-behind-approach-to-blazor-components
https://docs.microsoft.com/ja-jp/aspnet/core/blazor/dependency-injection?view=aspnetcore-3.0
https://gunnarpeipman.com/blazor-code-behind/