読者です 読者をやめる 読者になる 読者になる

かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

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

UWP

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>();
        }
    }
}

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