CarouselViewでコマンド呼出時はBindingContext.HogeCommandで実装しよう

Xamarin.Forms 5.0でstableになったCarouselViewを使ったろ！
CarouselViewの中でTapGestureRecognizer使ったろ！
あれ？動かん…
これはバグだあああ！
早速Issue作ったろ！
実は自分の実装が間違ってただけでしたー(^p^)

ということがあったので、供養するために記事を書きます。

# 先に結論

CarouselViewの中で任意のコマンドを使用する場合、以下のように実装すればコマンド実行可能です。

```xaml
<TapGestureRecognizer Command="{Binding Path=BindingContext.NextCommand, Source={x:Reference mainPage}}" />
```

# 環境

|使用ライブラリ|バージョン|
|:---|:---|
|Xamarin.Forms|v5.0.0.2012|


# 詳細

コマンドが実行できずに困っていたNGソースと、実行できるOKソースを以下に記載しています。
条件反射的に`Command="{Binding NextCommand}"`と実装していました。

```xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="CarouselViewTest.Views.MainPage"
             x:Name="mainPage"
             Title="{Binding Title}">

    <Grid RowDefinitions="*, *">
        <CarouselView ItemsSource="{Binding NgItems}" PeekAreaInsets="30">
            <CarouselView.ItemTemplate>
                <DataTemplate>
                    <ContentView>
                        <Grid RowDefinitions="Auto, *" Margin="20">
                            <!-- NG -->
                            <Grid.GestureRecognizers>
                                <TapGestureRecognizer Command="{Binding NextCommand}" />
                            </Grid.GestureRecognizers>
                            <Label Grid.Row="0" Text="{Binding Name}" />
                            <Image Grid.Row="1" BackgroundColor="{Binding Color}" />
                        </Grid>
                    </ContentView>
                </DataTemplate>
            </CarouselView.ItemTemplate>
        </CarouselView>

        <CarouselView Grid.Row="1" ItemsSource="{Binding OkItems}" PeekAreaInsets="30">
            <CarouselView.ItemTemplate>
                <DataTemplate>
                    <ContentView>
                        <Grid RowDefinitions="Auto, *" Margin="20">
                            <!-- OK -->
                            <Grid.GestureRecognizers>
                                <TapGestureRecognizer Command="{Binding Path=BindingContext.NextCommand, Source={x:Reference mainPage}}" />
                            </Grid.GestureRecognizers>
                            <Label Grid.Row="0" Text="{Binding Name}" />
                            <Image Grid.Row="1" BackgroundColor="{Binding Color}" />
                        </Grid>
                    </ContentView>
                </DataTemplate>
            </CarouselView.ItemTemplate>
        </CarouselView>
    </Grid>

</ContentPage>
```

ちなみに、NGコードで動作確認した際、以下のようなログが出力されました。
CarouselViewのItemsSourceプロパティに設定しているインスタンスのクラス内にコマンドが定義されてないよ、って怒られてます。
そりゃあ定義してないですもん…

```log
[0:] Binding: 'NextCommand' property not found on 'CarouselViewTest.Models.Item', target property: 'Xamarin.Forms.TapGestureRecognizer.Command'
```

使う人がいるかはわかりませんが、一応動作確認に使ったソースをGitHubに上げています。
[CarouselViewTest](https://github.com/takapi-Jr/CarouselViewTest)

# まとめ

CarouselView内でコマンド実行時には`BindingContext.HogeCommand`で実装しましょう。
作成したIssueは、もちろん可能な範囲で調査しよう。もう一度公式のドキュメントに立ち返ろう。そして自分を疑え。

# 参考リンク

[CarouselView コンテキストメニュー](https://docs.microsoft.com/ja-jp/xamarin/xamarin-forms/user-interface/carouselview/populate-data#context-menus)