【WPF】WebAPIをコールしてる間に「読み込み中」のインジケータを表示する [XamBusyIndicator]

# はじめに
時間のプロセスが実行中であることや、現在の進捗などをユーザに知らせるために、「読み込み中」のインジケーターの表示は、アプリケーションにおいてもよくある機能ですよね。
当記事では、[XamBusyIndicator](https://jp.infragistics.com/products/wpf/interactions/busy-indicator)を活用して、非同期処理の実装方法などをご紹介します！

# サンプルアプリケーション
WebAPIのURLを入力したものをテキストボックスに展開するサンプルアプリケーションを用意しました。
URLテキストボックスにWebAPIのURLを入力し、データを取得している間は「読み込み中」のインジケータを表示しています。
![Capture5.gif](https://qiita-image-store.s3.amazonaws.com/0/48623/11300c9f-9de4-e6dc-5b74-49b5bed50a82.gif)


# サンプルコード
GitHub
https://github.com/furugen/wpf-samples-busyindicator

```xml:MainWindow.xaml
<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:wpf_samples_busyindicator"
        xmlns:ig="http://schemas.infragistics.com/xaml" x:Class="wpf_samples_busyindicator.MainWindow"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">

    <UserControl >
        <ig:XamBusyIndicator x:Name="xamBusyIndicator">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"></RowDefinition>
                    <RowDefinition Height="*"></RowDefinition>
                </Grid.RowDefinitions>

                <StackPanel Grid.Row="0">
                    <StackPanel Margin="0,0,0,10">
                        <TextBlock>URL</TextBlock>
                        <TextBox x:Name="jsonUrl" >https://jsondata.okiba.me/v1/json/Y24yt190328044851</TextBox>
                        <Button Click="Button_Click">JSON読込</Button>
                    </StackPanel>
                </StackPanel>

                <Grid Grid.Row="1">
                    <TextBox x:Name="textJson" ></TextBox>
                </Grid>
            </Grid>
        </ig:XamBusyIndicator>
    </UserControl>
</Window>

```

```csharp:MainWindow.xaml.cs
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        private HttpClient client = new HttpClient();

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            xamBusyIndicator.IsBusy = true;
            this.Dispatcher.BeginInvoke((Action)(async () =>
            {
                this.textJson.Text = await GetRequest(this.jsonUrl.Text);
                xamBusyIndicator.IsBusy = false;
            }));
        }

        private async Task<string> GetRequest(string url)
        {
            HttpResponseMessage response = await client.GetAsync(url);
            if (response.IsSuccessStatusCode)
            {
                return await response.Content.ReadAsStringAsync();
            }

            return null;
        }
    }
```

# サンプルコードの解説

## WebAPI呼び出しと非同期制御
WebAPIは、HttpClientにてWebAPIをGet形式で呼び出しています。
※ちなみにお試し用APIとして、[JSON OKIBA](https://json.okiba.me/)さんのサービスを利用してます。
WebAPIを呼び出すまえにインジケーター表示(IsBusy = true)し、WebAPIを呼び出す際には、画面がフリーズしないように非同期(async/await)にしてWebAPIの返却を待ち、処理が終わったらインジケーターを非表示(IsBusy = false)にしています。

```csharp:MainWindow.xaml.cs
private void Button_Click(object sender, RoutedEventArgs e)
{
    xamBusyIndicator.IsBusy = true;
    this.Dispatcher.BeginInvoke((Action)(async () =>
    {
        this.textJson.Text = await GetRequest(this.jsonUrl.Text);
        xamBusyIndicator.IsBusy = false;
    }));
}

private async Task<string> GetRequest(string url)
{
    HttpResponseMessage response = await client.GetAsync(url);
    if (response.IsSuccessStatusCode)
    {
        return await response.Content.ReadAsStringAsync();
    }

    return null;
}
```


## インジケータの表示・非表示の切り替え
IsBusyプロパティ(bool)の切り替えにより、表示・非表示を切り替えることができます。

```csharp:MainWindow.xaml.cs
// 表示
xamBusyIndicator.IsBusy = true;
// 非表示
xamBusyIndicator.IsBusy = false;
```


# Tips
## 画面全体ではなく、一部の画面エリアをUIロック
サンプルアプリケーションでは画面全体のUIロックしましたが、囲む箇所を変えることにより部分的にインジケーターの配下の領域を変えることができます。

```xml:MainWindow.xaml
...省略...
                <Grid Grid.Row="1">
                    <ig:XamBusyIndicator x:Name="xamBusyIndicator">
                        <TextBox x:Name="textJson" ></TextBox>
                    </ig:XamBusyIndicator>
                </Grid>
...省略...
```

##
他にも様々なスタイルやアニメーションもありますのでご活用ください！
![image.png](https://qiita-image-store.s3.amazonaws.com/0/48623/f5dda4bb-7335-2b83-52bb-0b8ee77b1e9d.png)


# まとめ
XamBusyIndicatorは他にも様々なスタイルやアニメーションが用意してますし、進捗状況の表示や、途中キャンセルなども可能です。
ぜひご検討くださいませ～。!