(.NET MAUI) DelegateCommandの説明と第二引数の省略

# DelegateCommandについて

DelegateCommandは、.NET MAUIでのアプリケーション開発において、MVVMパターンを実装するために使用されるクラスの一つです。DelegateCommandは、ICommandを実装したクラスであり、コマンドの実行処理をデリゲートとして受け取ります。本記事では、DelegateCommandについて詳しく解説していきます。

# ICommandについて

ICommandは、コマンドパターンを実装するためのインターフェースです。ICommandは、以下の2つのメソッドを持っています。

1. Executeメソッド
2. CanExecuteメソッド

Executeメソッドは、コマンドの実行処理を行います。CanExecuteメソッドは、コマンドが実行可能かどうかを判定するためのメソッドです。

# DelegateCommandとは

DelegateCommandは、ICommandを実装したクラスであり、コマンドの実行処理をデリゲートとして受け取ります。DelegateCommandは、以下のように定義されています。

```csharp
public class DelegateCommand : ICommand
{
    public DelegateCommand(Action executeMethod);
    public DelegateCommand(Action executeMethod, Func<bool> canExecuteMethod);

    public void Execute(object parameter);
    public bool CanExecute(object parameter);
    public event EventHandler CanExecuteChanged;
}
```

DelegateCommandの第1引数には、コマンドの実行処理を行うActionを指定します。第2引数には、コマンドが実行可能かどうかを判定するFuncを指定します。

## 第２引数を省略すると常に実行扱いになる

DelegateCommandのコンストラクターの第2引数であるcanExecuteMethodを省略した場合、コマンドは常に実行可能となります。この場合、CanExecuteメソッドを常にtrueを返すように実装されます。

以下は、DelegateCommandのコンストラクターを使用し、canExecuteMethodを省略した例です。

```cs
public DelegateCommand MyCommand { get; }

public MyViewModel()
{
    MyCommand = new DelegateCommand(ExecuteMethod);
}

private void ExecuteMethod()
{
    // コマンドが実行されたときの処理
}
```

# DelegateCommandの実用例
## 非ラムダ式

以下は、DelegateCommandを使用した、非ラムダ式の実装例です。この例では、ボタンをクリックしたときに、メッセージボックスを表示するコマンドを実装しています。

```csharp
public class MainViewModel : ViewModelBase
{
    private DelegateCommand _showMessageCommand;
    public ICommand ShowMessageCommand
    {
        get
        {
            if (_showMessageCommand == null)
            {
                _showMessageCommand = new DelegateCommand(ShowMessage);
            }
            return _showMessageCommand;
        }
    }

    private void ShowMessage()
    {
        Application.Current.MainPage.DisplayAlert("Title", "Message", "OK");
    }
}
```

この例では、MainViewModelクラスにShowMessageCommandプロパティを定義し、そのプロパティにDelegateCommandを返すようにしています。DelegateCommandのコンストラクタには、ShowMessageメソッドを渡しています。ShowMessageメソッドは、ボタンがクリックされたときに実行され、メッセージボックスを表示する処理が記述されています。

### DelegateCommandの第２引数を省略しない場合

CanShowMessageメソッドに引数としてstring型のmessageを受け取り、その文字列が空白でないかどうかを判定しています。

```csharp
public class MainViewModel : ViewModelBase
{
    private DelegateCommand<string> _showMessageCommand;
    public ICommand ShowMessageCommand
    {
        get
        {
            if (_showMessageCommand == null)
            {
                _showMessageCommand = new DelegateCommand<string>(ShowMessage, CanShowMessage);
            }
            return _showMessageCommand;
        }
    }

    private void ShowMessage(string message)
    {
        Application.Current.MainPage.DisplayAlert("Title", message, "OK");
    }

    private bool CanShowMessage(string message)
    {
        return !string.IsNullOrWhiteSpace(message);
    }
}
```

## ラムダ式

DelegateCommandを使用する際、ラムダ式を利用することもできます。以下は、DelegateCommandを使用した、ラムダ式の実装例です。この例では、ボタンをクリックしたときに、Viewのプロパティを変更するコマンドを実装しています。

```csharp
public class MainViewModel : ViewModelBase
{
    public DelegateCommand ChangeTextCommand { get; }

    public MainViewModel()
    {
        ChangeTextCommand = new DelegateCommand(() =>
        {
            Text = "Hello, DelegateCommand!";
        });
    }

    private string _text;
    public string Text
    {
        get => _text;
        set => SetProperty(ref _text, value);
    }
}
```

この例では、MainViewModelクラスにChangeTextCommandプロパティを定義し、そのプロパティにDelegateCommandを返すようにしています。DelegateCommandのコンストラクタには、ラムダ式を渡しています。ラムダ式では、Textプロパティの値を変更しています。

### DelegateCommandの第２引数を省略しない場合

CanSetTextメソッドに引数としてstring型のtextを受け取り、その文字列が空白でないかどうかを判定しています。

```csharp
public class MainViewModel : ViewModelBase
{
    public DelegateCommand<string> SetTextCommand { get; }

    public MainViewModel()
    {
        SetTextCommand = new DelegateCommand<string>(text =>
        {
            Text = text;
        }, CanSetText);
    }

    private string _text;
    public string Text
    {
        get => _text;
        set => SetProperty(ref _text, value);
    }

    private bool CanSetText(string text)
    {
        return !string.IsNullOrWhiteSpace(text);
    }
}
```


# まとめ

DelegateCommandは、ICommandを実装したクラスであり、コマンドの実行処理をデリゲートとして受け取ります。DelegateCommandの第二引数は省略可能であり、省略した場合はTrueとなります。DelegateCommandを使用することで、シンプルなコマンドの実装が可能になり、ラムダ式を利用することで、コードの簡略化が可能になります。