ちょっと苦労されているようなので、サンプルを書いてみました。
NuGetでPrism.Core
を入れてあります。
cs
1using System.Collections.ObjectModel;
2using System.ComponentModel;
3using System.Windows;
4using System.Windows.Data;
5using Prism.Commands;
6using Prism.Mvvm;
7
8namespace Questions222623
9{
10 internal class MainViewModel
11 {
12 public class ItemViewModel : BindableBase
13 {
14 private bool _Selected;
15 public bool Selected { get => _Selected; set => SetProperty(ref _Selected, value); }
16
17 private string _Name;
18 public string Name { get => _Name; set => SetProperty(ref _Name, value); }
19 }
20
21 public ObservableCollection<ItemViewModel> Items { get; }
22 public ICollectionView LeftView { get; }
23 public ICollectionView RightView { get; }
24 public DelegateCommand<ItemViewModel> Left2RightCommand { get; }
25 public DelegateCommand<ItemViewModel> Right2LeftCommand { get; }
26
27 public MainViewModel()
28 {
29 Items = new ObservableCollection<ItemViewModel>
30 {
31 new ItemViewModel() { Name = "C1", Selected = true },
32 new ItemViewModel() { Name = "C2", Selected = false },
33 new ItemViewModel() { Name = "C3", Selected = true },
34 new ItemViewModel() { Name = "C4", Selected = true },
35 new ItemViewModel() { Name = "C5", Selected = false },
36 new ItemViewModel() { Name = "C6", Selected = true },
37 };
38
39 var cvs = new CollectionViewSource { Source = Items, };
40 cvs.IsLiveFilteringRequested = true; // 変更があったときにフィルターを即時反映
41 cvs.LiveFilteringProperties.Add(nameof(ItemViewModel.Selected)); // 変更を監視するプロパティ名
42 LeftView = cvs.View;
43 LeftView.Filter = x => (x as ItemViewModel).Selected == true;
44
45 cvs = new CollectionViewSource { Source = Items, };
46 cvs.IsLiveFilteringRequested = true;
47 cvs.LiveFilteringProperties.Add(nameof(ItemViewModel.Selected));
48 RightView = cvs.View;
49 RightView.Filter = x => (x as ItemViewModel).Selected == false;
50
51 Left2RightCommand = new DelegateCommand<ItemViewModel>(Left2rightCommandExecute);
52 Right2LeftCommand = new DelegateCommand<ItemViewModel>((item) => { if(item != null) item.Selected = true; }); // ラムダでもよい
53 }
54
55 private void Left2rightCommandExecute(ItemViewModel item)
56 {
57 if(item != null)
58 item.Selected = false;
59 }
60 }
61
62 public partial class MainWindow : Window
63 {
64 public MainWindow() => InitializeComponent();
65 }
66}
xml
1<Window
2 x:Class="Questions222623.MainWindow"
3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
5 xmlns:local="clr-namespace:Questions222623"
6 Title="MainWindow"
7 Width="800"
8 Height="450">
9 <Window.DataContext>
10 <local:MainViewModel />
11 </Window.DataContext>
12 <Grid>
13 <Grid.ColumnDefinitions>
14 <ColumnDefinition />
15 <ColumnDefinition Width="Auto" />
16 <ColumnDefinition />
17 </Grid.ColumnDefinitions>
18 <ListBox
19 x:Name="listBox"
20 DisplayMemberPath="Name"
21 ItemsSource="{Binding LeftView}" />
22 <StackPanel Grid.Column="1" VerticalAlignment="Center">
23 <Button
24 Margin="5"
25 Padding="5"
26 Command="{Binding Left2RightCommand}"
27 CommandParameter="{Binding SelectedItem, ElementName=listBox}"
28 Content="→" />
29 <Button
30 Margin="5"
31 Padding="5"
32 Command="{Binding Right2LeftCommand}"
33 CommandParameter="{Binding SelectedItem, ElementName=listBox1}"
34 Content="←" />
35 </StackPanel>
36 <ListBox
37 x:Name="listBox1"
38 Grid.Column="2"
39 DisplayMemberPath="Name"
40 ItemsSource="{Binding RightView}" />
41 </Grid>
42</Window>
こういうイメージであっていますでしょうか?
別解としてドラッグ&ドロップでの移動例も作ってみました。
NuGetでPrism.Core
gong-wpf-dragdrop
を入れてあります。
cs
1using System.Collections;
2using System.Collections.ObjectModel;
3using System.Windows;
4using GongSolutions.Wpf.DragDrop;
5using Prism.Mvvm;
6
7namespace Questions222623
8{
9 internal class MainViewModel : IDropTarget
10 {
11 public class ItemViewModel : BindableBase
12 {
13 private string _Name;
14 public string Name { get => _Name; set => SetProperty(ref _Name, value); }
15 }
16
17 public ObservableCollection<ItemViewModel> SelectedItems { get; }
18 public ObservableCollection<ItemViewModel> UnselectedItems { get; }
19
20 private readonly DefaultDropHandler defaultDropHandler = new DefaultDropHandler();
21
22 public MainViewModel()
23 {
24 SelectedItems = new ObservableCollection<ItemViewModel>
25 {
26 new ItemViewModel() { Name = "C1", },
27 new ItemViewModel() { Name = "C3", },
28 new ItemViewModel() { Name = "C4", },
29 new ItemViewModel() { Name = "C6", },
30 };
31 UnselectedItems = new ObservableCollection<ItemViewModel>
32 {
33 new ItemViewModel() { Name = "C2", },
34 new ItemViewModel() { Name = "C5", },
35 };
36 }
37
38 void IDropTarget.DragOver(IDropInfo dropInfo)
39 {
40 if(dropInfo.Data is ItemViewModel)
41 {
42 dropInfo.DropTargetAdorner = DropTargetAdorners.Insert;
43 dropInfo.Effects = DragDropEffects.Move;
44 }
45 }
46 void IDropTarget.Drop(IDropInfo dropInfo)
47 {
48 if(dropInfo.Data is ItemViewModel item)
49 {
50 if(dropInfo.DragInfo.SourceCollection != dropInfo.TargetCollection)
51 {
52 ((IList)dropInfo.DragInfo.SourceCollection).Remove(item);
53 ((IList)dropInfo.TargetCollection).Insert(dropInfo.InsertIndex, item);
54 }
55 else
56 {
57 defaultDropHandler.Drop(dropInfo);
58 }
59 }
60 }
61 }
62 public partial class MainWindow : Window
63 {
64 public MainWindow() => InitializeComponent();
65 }
66}
xml
1<Window
2 x:Class="Questions222623.MainWindow"
3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
5 xmlns:dd="urn:gong-wpf-dragdrop"
6 xmlns:local="clr-namespace:Questions222623"
7 Title="MainWindow"
8 Width="800"
9 Height="450">
10 <Window.DataContext>
11 <local:MainViewModel />
12 </Window.DataContext>
13 <Grid>
14 <Grid.ColumnDefinitions>
15 <ColumnDefinition />
16 <ColumnDefinition />
17 </Grid.ColumnDefinitions>
18 <ListBox
19 dd:DragDrop.DropHandler="{Binding}"
20 dd:DragDrop.IsDragSource="True"
21 dd:DragDrop.IsDropTarget="True"
22 DisplayMemberPath="Name"
23 ItemsSource="{Binding SelectedItems}" />
24 <ListBox
25 Grid.Column="1"
26 dd:DragDrop.DropHandler="{Binding}"
27 dd:DragDrop.IsDragSource="True"
28 dd:DragDrop.IsDropTarget="True"
29 DisplayMemberPath="Name"
30 ItemsSource="{Binding UnselectedItems}" />
31 </Grid>
32</Window>
コードが長くなると本質がわかりにくくなるため、CollectionViewSource
を使わずシンプルにSelectedItems
UnselectedItems
と2つに分けましたが、もちろん使っても構いません。