如何将列表框中的多个选定项移回另一个列表框?

问题描述 投票:0回答:1

我已成功将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的使用有问题,但我无法弄清楚。请帮我。预先谢谢你。

c# wpf listbox collectionviewsource
1个回答
0
投票

问题是您在null上调用CollectionViewSource.GetDefaultView。 RightListBox.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);
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.