次の方法で共有


MVVMパターンでListBoxの複数選択状態をViewとViewModel間で同期させる方法について

質問

2016年3月27日日曜日 15:31

MVVMパターンを用いてViewのコードビハインドを用いず題意を満たすためのスマートな方法を教えて下さい。

すべての返信 (7)

2016年3月27日日曜日 16:03 ✅回答済み

こんにちは。

簡単なのは以下のようにViewModelのリスト要素に選択状態を保持させることだと思います。

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication1"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:MainWindowViewModel />
    </Window.DataContext>
    <Grid>
        <ListBox ItemsSource="{Binding Items}" 
                 DisplayMemberPath="Name"
                 SelectionMode="Multiple">
            <ListBox.ItemContainerStyle>
                <Style TargetType="ListBoxItem">
                    <Setter Property="IsSelected" Value="{Binding Selected}" />
                </Style>
            </ListBox.ItemContainerStyle>
        </ListBox>
    </Grid>
</Window>
public class MainWindowViewModel : BindableBase
{
    private ObservableCollection<ItemViewModel> _Items;
    public ObservableCollection<ItemViewModel> Items
    {
        get
        {
            return _Items;
        }
        set
        {
            SetProperty(ref _Items, value);
        }
    }

    public MainWindowViewModel()
    {
        Items = new ObservableCollection<ItemViewModel>();
        Items.Add(new ItemViewModel() { Name = "AAA", Selected = true });
        Items.Add(new ItemViewModel() { Name = "BBB", Selected = false });
        Items.Add(new ItemViewModel() { Name = "CCC", Selected = true });
    }
}

public class ItemViewModel : BindableBase
{
    private bool _Selected;
    public bool Selected
    {
        get { return _Selected; }
        set
        {
            SetProperty(ref _Selected, value);
        }
    }

    private string _Name;
    public string Name
    {
        get { return _Name; }
        set
        {
            SetProperty(ref _Name, value);
        }
    }
}

もし、選択状態を保持させたくないのであれば、以下のようにView側へ多少のコード追加を行って、
SelectedItemsプロパティを活用することになると思います。(SelectedItemsプロパティは依存関係プロパティではないので…)

http://tnakamura.hatenablog.com/entry/20100217/silverlight_listbox_selecteditems


2016年3月28日月曜日 4:21

SelectedItemsプロパティって無かったっけ?と思って検索してみました。
http://gushwell.ldblog.jp/archives/52333865.html

自分で試してないのですが、こんな感じでいかがですか?


2016年3月28日月曜日 4:52

SelectedItemsプロパティって無かったっけ?と思って検索してみました。

SelectedItemsプロパティは依存関係プロパティではないので単純にバインド出来ません。
そしてご提示のURLは私がコードで回答した内容とほぼ同じでSelectedItemsプロパティは使ってません。
※ViewModel上に同名のプロパティがあるだけです。

SelectedItemsプロパティを使う方法は
最後にURLで示したリンク先に記載されています。


2016年3月28日月曜日 12:23

IBindableBaseとは何ですか?


2016年3月28日月曜日 12:26

すみません、暗黙的に使ってしまっていました。

MVVMのインフラにPrism WPF 6 を使ってます。(NuGet)
Prismを使わない場合は、INotifyPropertyChangedを実装したViewModelの基底クラスだと読み替えてください。


2016年3月28日月曜日 15:08

ありがとうごうざいました

まだあまり理解していませんが一応動いているので良いと思います


2016年3月29日火曜日 1:46

BindableBaseに関しては、Prismを使っていない場合の例をgekkaさんが示されているので、参考になると思います。

DataGrid上で列の新規作成や編集がしたい
https://social.msdn.microsoft.com/Forums/ja-JP/bd16371b-4d56-4446-897e-3b4789875ad3/datagrid?forum=wpfja

★良い回答には回答済みマークを付けよう! MVP - .NET  http://d.hatena.ne.jp/trapemiya/