4
7

More than 5 years have passed since last update.

Xamarin.FormsでListViewのイベントをViewModelにバインドする

Posted at

ListView には Command プロパティが無いみたいで、タップ時のイベントをどうやって ViewModel で処理するのか分かりませんでした。

しかし、なんとかやり方が判明したのでメモを残しておきます。

コード

Behavior というものを定義して、それをXAML経由で ListView に割り当てるようです。
Command をバインド可能プロパティにしておかないと、実行時に"そんなプロパティ無い"と言われます。

あと、Behavior の BindingContext にイベント発生元(ListView)の BindindContext を指定しておきます。
こうしておかないと XAMLでバインドした Command が Behavior まで渡ってきません。

Behavior
using System.Windows.Input;
using Xamarin.Forms;

namespace MyApp.Behaviors
{
    public class ItemTappedBehavior : Behavior<ListView>
    {
        public static BindableProperty CommandProperty = BindableProperty.Create(
            "Command", typeof(ICommand), typeof(ItemTappedBehavior), null
        );

        public ICommand Command
        {
            get { return (ICommand)GetValue(CommandProperty); }
            set { SetValue(CommandProperty, value); }
        }

        protected override void OnAttachedTo(ListView bindable)
        {
            base.OnAttachedTo(bindable);

             // ↓↓↓ これ重要  
            bindable.BindingContextChanged += (sender, e) => {
                this.BindingContext = ((ListView)sender).BindingContext;
            };
             // ↑↑↑ これ重要  

            bindable.ItemTapped += (sender, e) => {
                this.Command.Execute(e.Item);
            };
        }
    }
}
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"
    xmlns:vm="clr-namespace:MyApp.ViewModels"
    xmlns:b="clr-namespace:MyApp.Behaviors"
    Padding="30"
    x:Class="MyApp.Views.MainPage">

    <ContentPage.BindingContext>
        <vm:MainPageViewModel />
    </ContentPage.BindingContext>

    <ListView ItemsSource="{Binding Items}">
        <ListView.Behaviors>
            <b:ItemTappedBehavior Command="{Binding ItemTappedCommand}"/>
        </ListView.Behaviors>
    </ListView>

</ContentPage>
ViewModel
using System.Collections.Generic;
using System.Windows.Input;

using Xamarin.Forms;

namespace MyApp.ViewModels
{
    public class MainPageViewModel
    {
        public List<string> Items { protected set; get; } = new List<string>();

        public ICommand ItemTappedCommand { get; set; }

        public MainPageViewModel()
        {
            Items.Add("First Item");
            Items.Add("Second Item");

            this.ItemTappedCommand = new Command<string>((item) => {
                System.Diagnostics.Debug.WriteLine(item);
            });
        }
    }
}

結果

タップしたセルの内容がログに出力されました。
OKなようですね。

output.png

とりあえずは以上です。

こちらを参考にしました

http://blog.okazuki.jp/entry/2016/12/14/170430
https://forums.xamarin.com/discussion/44900/bind-to-bindable-property-in-behaviour

4
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
7