如何将 ListBox 中的多个选定项目移回另一个 ListBox?
How to move multiple selected items in a ListBox back to another ListBox?
我已成功将 LeftListBox 中的多个项目移动到 RightListBox。现在,我想将它们从 RightListBox 移回 LeftListBox。但是,它给了我 "System.NullReferenceException"。这是我的代码:
MainWindow.xaml.cs
using ListBoxMoveAll.Model;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Data;
namespace ListBoxMoveAll
{
public partial class MainWindow : Window
{
ObservableCollection<TestModel> testItem = new ObservableCollection<TestModel>();
public MainWindow()
{
InitializeComponent();
testItem.Add(new TestModel("Test_1"));
testItem.Add(new TestModel("Test_2"));
testItem.Add(new TestModel("Test_3"));
LeftListBox.ItemsSource = testItem;
CollectionViewSource.GetDefaultView(LeftListBox.ItemsSource).Filter =
(tm) => !RightListBox.Items.Cast<TestModel>().Any(x => x.Equals(tm as TestModel));
CollectionViewSource.GetDefaultView(RightListBox.ItemsSource);
}
private void Add_Button_Click(object sender, RoutedEventArgs e)
{
foreach (var item in LeftListBox.SelectedItems)
{
RightListBox.ItemsSource = null;
RightListBox.Items.Add(item);
}
CollectionViewSource.GetDefaultView(LeftListBox.ItemsSource).Refresh();
}
private void Remove_Button_Click(object sender, RoutedEventArgs e)
{
foreach (var item in RightListBox.SelectedItems)
{
LeftListBox.ItemsSource = null;
LeftListBox.Items.Add(item);
}
CollectionViewSource.GetDefaultView(RightListBox.ItemsSource).Refresh();
}
}
}
MainWindow.xaml
<Window x:Class="ListBoxMoveAll.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:ListBoxMoveAll"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="80" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ListBox x:Name="LeftListBox" Grid.Column="0" Grid.Row="1" Grid.RowSpan="3"
SelectionMode="Extended" DisplayMemberPath="TestItem">
</ListBox>
<ListBox x:Name="RightListBox" Grid.Column="2" Grid.Row="1" Grid.RowSpan="3" DisplayMemberPath="TestItem" />
<StackPanel Grid.Column="1" Grid.Row="1" VerticalAlignment="Center">
<Button Content="Add" x:Name="Add_Button" Click="Add_Button_Click"/>
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="3" VerticalAlignment="Center">
<Button Content="Remove" x:Name="Remove_Button" Click="Remove_Button_Click"/>
</StackPanel>
</Grid>
</Window>
Model/TestModel.cs
namespace ListBoxMoveAll.Model
{
public class TestModel
{
public TestModel(string _testItem)
{ TestItem = _testItem; }
public string TestItem { get; set; }
}
}
我加了RightListBox.ItemsSource = null;
。我认为我对 CollectionViewSource.GetDefaultView 的用法有问题,但我想不通。
请帮我。提前谢谢你。
问题是您在 null 上调用 CollectionViewSource.GetDefaultView。 RightListBox.ItemsSource 为空,因为您在 Add_Button_Click 处理程序中将其设置为空。
解决办法是LeftListBox只引用ItemsSource(因为你在构造函数中设置了),RightListBox引用Items。
然后您将得到如下代码:
public partial class MainWindow : Window
{
ObservableCollection<TestModel> testItem = new ObservableCollection<TestModel>();
public MainWindow()
{
InitializeComponent();
testItem.Add(new TestModel("Test_1"));
testItem.Add(new TestModel("Test_2"));
testItem.Add(new TestModel("Test_3"));
LeftListBox.ItemsSource = testItem;
CollectionViewSource.GetDefaultView(LeftListBox.ItemsSource).Filter = (tm) => !RightListBox.Items.Cast<TestModel>().Any(x => x.Equals(tm as TestModel));
}
private void Add_Button_Click(object sender, RoutedEventArgs e)
{
foreach (TestModel item in LeftListBox.SelectedItems)
RightListBox.Items.Add(item);
CollectionViewSource.GetDefaultView(LeftListBox.ItemsSource).Refresh();
}
private void Remove_Button_Click(object sender, RoutedEventArgs e)
{
foreach (TestModel item in RightListBox.SelectedItems.OfType<TestModel>().ToList())
RightListBox.Items.Remove(item);
CollectionViewSource.GetDefaultView(LeftListBox.ItemsSource).Refresh();
}
}
但是您应该记住,LeftListBox 的 ItemsSource 始终包含所有值,它只是根据右侧列表中的 Items 在视觉上进行过滤。
如果您希望 LeftListBox 和 RightListBox 的 ItemsSource 相互改变,您应该考虑如下更改 xaml:
<ListBox
x:Name="LeftListBox"
Grid.Row="1"
Grid.RowSpan="3"
Grid.Column="0"
DisplayMemberPath="TestItem"
ItemsSource="{Binding LeftListBoxItems}"
SelectionMode="Extended" />
<ListBox
x:Name="RightListBox"
Grid.Row="1"
Grid.RowSpan="3"
Grid.Column="2"
DisplayMemberPath="TestItem"
ItemsSource="{Binding RightListBoxItems}" />
你的代码如下:
public partial class MainWindow : Window
{
public ObservableCollection<TestModel> LeftListBoxItems { get; } = new ObservableCollection<TestModel>();
public ObservableCollection<TestModel> RightListBoxItems { get; } = new ObservableCollection<TestModel>();
public MainWindow()
{
InitializeComponent();
DataContext = this;
LeftListBoxItems.Add(new TestModel("Test_1"));
LeftListBoxItems.Add(new TestModel("Test_2"));
LeftListBoxItems.Add(new TestModel("Test_3"));
}
private void Add_Button_Click(object sender, RoutedEventArgs e)
{
foreach (TestModel item in LeftListBox.SelectedItems.OfType<TestModel>().ToList())
{
LeftListBoxItems.Remove(item);
RightListBoxItems.Add(item);
}
}
private void Remove_Button_Click(object sender, RoutedEventArgs e)
{
foreach (TestModel item in RightListBox.SelectedItems.OfType<TestModel>().ToList())
{
RightListBoxItems.Remove(item);
LeftListBoxItems.Add(item);
}
}
}
我已成功将 LeftListBox 中的多个项目移动到 RightListBox。现在,我想将它们从 RightListBox 移回 LeftListBox。但是,它给了我 "System.NullReferenceException"。这是我的代码:
MainWindow.xaml.cs
using ListBoxMoveAll.Model;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Data;
namespace ListBoxMoveAll
{
public partial class MainWindow : Window
{
ObservableCollection<TestModel> testItem = new ObservableCollection<TestModel>();
public MainWindow()
{
InitializeComponent();
testItem.Add(new TestModel("Test_1"));
testItem.Add(new TestModel("Test_2"));
testItem.Add(new TestModel("Test_3"));
LeftListBox.ItemsSource = testItem;
CollectionViewSource.GetDefaultView(LeftListBox.ItemsSource).Filter =
(tm) => !RightListBox.Items.Cast<TestModel>().Any(x => x.Equals(tm as TestModel));
CollectionViewSource.GetDefaultView(RightListBox.ItemsSource);
}
private void Add_Button_Click(object sender, RoutedEventArgs e)
{
foreach (var item in LeftListBox.SelectedItems)
{
RightListBox.ItemsSource = null;
RightListBox.Items.Add(item);
}
CollectionViewSource.GetDefaultView(LeftListBox.ItemsSource).Refresh();
}
private void Remove_Button_Click(object sender, RoutedEventArgs e)
{
foreach (var item in RightListBox.SelectedItems)
{
LeftListBox.ItemsSource = null;
LeftListBox.Items.Add(item);
}
CollectionViewSource.GetDefaultView(RightListBox.ItemsSource).Refresh();
}
}
}
MainWindow.xaml
<Window x:Class="ListBoxMoveAll.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:ListBoxMoveAll"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="80" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ListBox x:Name="LeftListBox" Grid.Column="0" Grid.Row="1" Grid.RowSpan="3"
SelectionMode="Extended" DisplayMemberPath="TestItem">
</ListBox>
<ListBox x:Name="RightListBox" Grid.Column="2" Grid.Row="1" Grid.RowSpan="3" DisplayMemberPath="TestItem" />
<StackPanel Grid.Column="1" Grid.Row="1" VerticalAlignment="Center">
<Button Content="Add" x:Name="Add_Button" Click="Add_Button_Click"/>
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="3" VerticalAlignment="Center">
<Button Content="Remove" x:Name="Remove_Button" Click="Remove_Button_Click"/>
</StackPanel>
</Grid>
</Window>
Model/TestModel.cs
namespace ListBoxMoveAll.Model
{
public class TestModel
{
public TestModel(string _testItem)
{ TestItem = _testItem; }
public string TestItem { get; set; }
}
}
我加了RightListBox.ItemsSource = null;
。我认为我对 CollectionViewSource.GetDefaultView 的用法有问题,但我想不通。
请帮我。提前谢谢你。
问题是您在 null 上调用 CollectionViewSource.GetDefaultView。 RightListBox.ItemsSource 为空,因为您在 Add_Button_Click 处理程序中将其设置为空。
解决办法是LeftListBox只引用ItemsSource(因为你在构造函数中设置了),RightListBox引用Items。
然后您将得到如下代码:
public partial class MainWindow : Window
{
ObservableCollection<TestModel> testItem = new ObservableCollection<TestModel>();
public MainWindow()
{
InitializeComponent();
testItem.Add(new TestModel("Test_1"));
testItem.Add(new TestModel("Test_2"));
testItem.Add(new TestModel("Test_3"));
LeftListBox.ItemsSource = testItem;
CollectionViewSource.GetDefaultView(LeftListBox.ItemsSource).Filter = (tm) => !RightListBox.Items.Cast<TestModel>().Any(x => x.Equals(tm as TestModel));
}
private void Add_Button_Click(object sender, RoutedEventArgs e)
{
foreach (TestModel item in LeftListBox.SelectedItems)
RightListBox.Items.Add(item);
CollectionViewSource.GetDefaultView(LeftListBox.ItemsSource).Refresh();
}
private void Remove_Button_Click(object sender, RoutedEventArgs e)
{
foreach (TestModel item in RightListBox.SelectedItems.OfType<TestModel>().ToList())
RightListBox.Items.Remove(item);
CollectionViewSource.GetDefaultView(LeftListBox.ItemsSource).Refresh();
}
}
但是您应该记住,LeftListBox 的 ItemsSource 始终包含所有值,它只是根据右侧列表中的 Items 在视觉上进行过滤。
如果您希望 LeftListBox 和 RightListBox 的 ItemsSource 相互改变,您应该考虑如下更改 xaml:
<ListBox
x:Name="LeftListBox"
Grid.Row="1"
Grid.RowSpan="3"
Grid.Column="0"
DisplayMemberPath="TestItem"
ItemsSource="{Binding LeftListBoxItems}"
SelectionMode="Extended" />
<ListBox
x:Name="RightListBox"
Grid.Row="1"
Grid.RowSpan="3"
Grid.Column="2"
DisplayMemberPath="TestItem"
ItemsSource="{Binding RightListBoxItems}" />
你的代码如下:
public partial class MainWindow : Window
{
public ObservableCollection<TestModel> LeftListBoxItems { get; } = new ObservableCollection<TestModel>();
public ObservableCollection<TestModel> RightListBoxItems { get; } = new ObservableCollection<TestModel>();
public MainWindow()
{
InitializeComponent();
DataContext = this;
LeftListBoxItems.Add(new TestModel("Test_1"));
LeftListBoxItems.Add(new TestModel("Test_2"));
LeftListBoxItems.Add(new TestModel("Test_3"));
}
private void Add_Button_Click(object sender, RoutedEventArgs e)
{
foreach (TestModel item in LeftListBox.SelectedItems.OfType<TestModel>().ToList())
{
LeftListBoxItems.Remove(item);
RightListBoxItems.Add(item);
}
}
private void Remove_Button_Click(object sender, RoutedEventArgs e)
{
foreach (TestModel item in RightListBox.SelectedItems.OfType<TestModel>().ToList())
{
RightListBoxItems.Remove(item);
LeftListBoxItems.Add(item);
}
}
}