Xamarn.FormsのListViewなどを使用している際、ViewModel内のプロパティをBindしたい時があったりするかと思います。ItemsSourceのモデル内にBind用のプロパティを持たせ、1つ1つに値を入れていくといったやり方だとスマートではありません。
そういった実装をしなくてもViewModelのプロパティを直接Bindする方法があるので、今回はその方法について説明します。
例えばテキストとボタンがあるリストを例とすると、データバインドしてリストを表示するとなると、Viewはこのような感じで、
<ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Test.Hoge">
<ListView
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
ItemsSource="{Binding Persons}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout
HorizontalOptions="FillAndExpand"
HeightRequest="50">
<Label
Text="{Binding Name}"/>
<Button
WidthRequest="100"
HeightRequest="20"
Text="Click"
Command="{Binding ClickCommand}"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
下記のようなデータバインド用のモデルを準備し、
public class Person {
public string Name {get; set;}
public string ClickCommand {get; set;}
}
ViewModelは
public class HogeViewModel {
public ObservableCollection<Person> Persons { get; set; }
public Command ListClickCommand => new Command(() => { System.Diagnostics.Debug.Write("Click!"); });
public HogeViewModel() {
Persons = new ObservableCollection<Person>() {
new Person() { Name = "田中", ClickCommand = ListClickCommand },
new Person() { Name = "山田", ClickCommand = ListClickCommand },
new Person() { Name = "佐藤", ClickCommand = ListClickCommand }
};
}
}
↑のような感じになります。
PersonクラスのClickCommandにViewModelのListClickCommandを1つ1つ代入していますが、ListClickCommandをそのままBindできたら楽ですよね。
それを実現する方法が下記です。
<ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Test.Hoge"
x:Name="This">
<ListView
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
ItemsSource="{Binding Persons}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout
HorizontalOptions="FillAndExpand"
HeightRequest="50">
<Label
Text="{Binding Name}"/>
<Button
WidthRequest="100"
HeightRequest="20"
Text="Click"
Command="{Binding Source={x:Reference This}, Path=BindingContext.ListClickCommand}"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
ViewのContentPageにx:Nameで名前をつけ、
{Binding Source={x:Reference This}, Path=BindingContext.ListClickCommand}
↑このようにしてつけた名前を参照し、PathをBindingContext.プロパティ名で指定してあげると、ViewModelのプロパティを直でBindすることが可能になります。