エレガントは言い過ぎ&タイトル長い上&ダイマでごめんなさい。
KAMISHIBAI for Xamarin.FormsとXamarin.Forms.BehaviorsPackの合わせ技でこんな簡単にListViewで選択されて画面遷移してパラメーター渡しするのが簡単に書けますよという紹介です。
こんな感じのありがちなやつですが、これを至極簡単に書ける方法を紹介します。
サンプルの全コードはこちらのStylishListViewSampleをご覧ください。
さて、まず初期画面のViewModelをつぎのように記述します。
public class FruitsListPageViewModel : ViewModelBase
{
public IReadOnlyList<Fruit> Fruits { get; }
= FruitsRepository.Fruits;
public NavigationRequestCommand<Fruit> RequestDetail { get; }
= new NavigationRequestCommand<Fruit>();
}
NavigationRequestCommandはICommandを実装したINavigationRequestの実装クラスです。
Command実行の受付と、画面遷移要求の発行を同時に行うやつです。
ユーザー操作から画面遷移までに、すべきことが少ない場合に使えます。(Actionをコンストラクタで登録して、簡単な処理を遷移前に実行する事も可能です。)
そしてXAMLをこんな感じで書きます。
xml version="1.0" encoding="utf-8"
<ContentPage ...>
<ContentPageBindingContext>
<viewModelsFruitsListPageViewModel/>
</ContentPageBindingContext>
<ContentPageBehaviors>
<mvvmPushAsync Request="{Binding RequestDetail}"
xTypeArguments="views:FruitDetailPage" />
</ContentPageBehaviors>
<ListView ItemsSource="{Binding Fruits}">
<ListViewBehaviors>
<behaviorsPackSelectedItemBehavior
Command="{Binding RequestDetail}"/>
</ListViewBehaviors>
<ListViewItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Name}" TextColor="{Binding Color}"/>
</DataTemplate>
</ListViewItemTemplate>
</ListView>
</ContentPage>
ListViewのBehaviorsに登録されているSelectedItemBehaviorをまず見てください。
<behaviorsPackSelectedItemBehavior Command="{Binding RequestDetail}"/>
SelectedItemBehaviorは行が選択された時に、良い感じで選択されたアイテムを渡しつつCommandを実行してくれる自分的にはうれしい奴です(再選択問題なんかも対応してありますよ)。
ListViewで行が選択されたら、選択された行にBindされているFruitを引数に、RequestDetailのExecuteを呼び出してくれます。
つづいてPageのBehaviorsを見てください。
<mvvmPushAsync Request="{Binding RequestDetail}"
xTypeArguments="views:FruitDetailPage" />
RequestDetailの要求を受けてFruitDetailPageにPushAsyncで遷移してね、と宣言されています。
これでListViewでいずれかが選択されたら、選択されたFruitを渡して画面遷移します。
あとは受け取る側を次のように実装します。
public class FruitDetailPageViewModel
: ViewModelBase, IPageInitializeAware<Fruit>
{
public void OnInitialize(Fruit fruit) => Fruit = fruit;
OnInitializeメソッドのパラメーターとして型安全に受け取れます。受け取り後、このコードではFruitプロパティに値を設定しています。
良くないですか?
…ん?良くない?パラメーターはID渡しして、遷移先で値は取り直したいと?
OK、そのパターンを紹介しましょう。
初期画面のViewModelを次のように修正します。
public NavigationRequestCommand<int> RequestDetail { get; }
= new NavigationRequestCommand<int>();
型パラメーターをFruitからintに変更しただけです。
そして、XAMLのSelectedItemBehaviorでFruitのIdをCommandに渡すよう、次のように修正します。
before
<behaviorsPack:SelectedItemBehavior
Command="{Binding RequestDetail}"/>
after
<!--
<behaviorsPack:SelectedItemBehavior
Command="{Binding RequestDetail}" PropertyPath="Id"/>
最期に、受け取るところを受け取ったIdから値を再取得するように修正しましょう。
public class FruitDetailPageViewModel
: ViewModelBase, IPageInitializeAware<int>
{
public void OnInitialize(int id) =>
Fruit = FruitsRepository.FindById(id);
これでOKです。
いや~、Xamarin.Forms.BehaviorsPackと紙芝居便利だな~(棒
続きを読む