如何将ListBox中的多个选定项移回另一个ListBox



我已经成功地将LeftListBox中的多个项移动到RightListBox。现在,我想将它们从RightListBox移回LeftListBox。然而,它给了我"System.NullReferenceException"。这是我的代码:

主窗口.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();
}
}
}

主窗口.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>

型号/测试型号.cs

namespace ListBoxMoveAll.Model
{
public class TestModel
{
public TestModel(string _testItem) 
{ TestItem = _testItem; }
public string TestItem { get; set; }
}
}

我添加了RightListBox.ItemsSource = null;。我认为我使用CollectionViewSource。GetDefaultView有问题,但我想不通。请帮帮我。提前谢谢你。

问题在于调用CollectionViewSource。GetDefaultView为null。右侧列表框。ItemsSource为null,因为您在Add_Button_Click处理程序中将其设置为null。

解决方案是只引用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);
}
}
}

最新更新