かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

UWPのListView/GridViewでSelectedItemsをViewModelに渡したい

SelectedItemsってDependencyPropertyじゃないっぽいのでバインド出来ないんですよね。ということで、ベタな方法ですがView → ViewModelの1方向でいいなら以下のような方法が使えます。

まず、ViewModelとListViewに表示するアイテムのクラスを作ります。

using System;
using System.Collections.Generic;
using System.Linq;
using Windows.UI.Popups;

namespace App66
{
    public class MainPageViewModel
    {
        public IEnumerable<Person> SelectedItems { get; set; } = Enumerable.Empty<Person>();

        public async void Dump()
        {
            var message = $"{string.Join(", ", this.SelectedItems.Select(x => x.Name).ToArray())} selected.";
            var dlg = new MessageDialog(message);
            await dlg.ShowAsync();
        }
    }

    public class Person
    {
        public string Name { get; set; }

        public override string ToString()
        {
            return this.Name;
        }
    }
}

ViewModelのSelectedItemsに選択された項目を突っ込むようにします。 やり方は、ListViewのSelectionChangedで突っ込むだけ。

<Page
    x:Class="App66.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App66"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:System="using:System"
    mc:Ignorable="d">
    <Page.DataContext>
        <local:MainPageViewModel />
    </Page.DataContext>
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Button Content="Dump"
                HorizontalAlignment="Stretch"
                Click="{x:Bind ViewModel.Dump}" />
        <ListView x:Name="ListView"
                  Grid.Row="1"
                  SelectionMode="Multiple"
                  SelectionChanged="ListView_SelectionChanged">
            <local:Person Name="Tanaka" />
            <local:Person Name="Kimura" />
            <local:Person Name="Ohta" />
            <local:Person Name="Homuhomu" />
        </ListView>
    </Grid>
</Page>
using System.Linq;
using Windows.UI.Xaml.Controls;

// 空白ページのアイテム テンプレートについては、http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409 を参照してください

namespace App66
{
    /// <summary>
    /// それ自体で使用できる空白ページまたはフレーム内に移動できる空白ページ。
    /// </summary>
    public sealed partial class MainPage : Page
    {
        public MainPageViewModel ViewModel => this.DataContext as MainPageViewModel;

        public MainPage()
        {
            this.InitializeComponent();
        }

        private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            this.ViewModel.SelectedItems = this.ListView.SelectedItems.Cast<Person>();
        }
    }
}

多用するならビヘイビア化してもいいかもですね。