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

回答

  • こんにちは。

    簡単なのは以下のように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月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月27日 16:03
    モデレータ
  • SelectedItemsプロパティって無かったっけ?と思って検索してみました。
    http://gushwell.ldblog.jp/archives/52333865.html

    自分で試してないのですが、こんな感じでいかがですか?
    2016年3月28日 4:21
  • SelectedItemsプロパティって無かったっけ?と思って検索してみました。

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

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


    2016年3月28日 4:52
    モデレータ
  • IBindableBaseとは何ですか?
    2016年3月28日 12:23
  • すみません、暗黙的に使ってしまっていました。

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

    2016年3月28日 12:26
    モデレータ
  • ありがとうごうざいました

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

    2016年3月28日 15:08
  • 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/

    2016年3月29日 1:46
    モデレータ