简体   繁体   English

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

[英]How to move multiple selected items in a ListBox back to another ListBox?

I've succeeded to move multiple items in LeftListBox to RightListBox.我已成功将 LeftListBox 中的多个项目移动到 RightListBox。 Now, I'd like to move them back from RightListBox to LeftListBox.现在,我想将它们从 RightListBox 移回 LeftListBox。 However, it gives me "System.NullReferenceException".但是,它给了我“System.NullReferenceException”。 Here is my code:这是我的代码:

MainWindow.xaml.cs主窗口.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主窗口.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模型/TestModel.cs

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

        public string TestItem { get; set; }
    }
}

I added RightListBox.ItemsSource = null;我添加了RightListBox.ItemsSource = null; . . I think my usage of CollectionViewSource.GetDefaultView is something wrong, but I can't figure it out.我认为我对 CollectionViewSource.GetDefaultView 的使用有问题,但我无法弄清楚。 Please help me.请帮我。 Thank you in advance.先感谢您。

The problem is you call CollectionViewSource.GetDefaultView on null.问题是您在 null 上调用 CollectionViewSource.GetDefaultView。 RightListBox.ItemsSource is null because you set it to null in Add_Button_Click handler. RightListBox.ItemsSource 是 null 因为您在 Add_Button_Click 处理程序中将其设置为 null。

The solution is to only refer to ItemsSource for LeftListBox (because you set it in the constructor) and to refer to Items for RightListBox.解决方案是 LeftListBox 仅引用 ItemsSource(因为您在构造函数中设置了它)并为 RightListBox 引用 Items。

Then you will end up with code like below:然后你会得到如下代码:

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();
    }
}

However you should keep in mind that the ItemsSource of the LeftListBox always contains all the values, it is just visually filtered based on the Items in the right list.但是您应该记住,LeftListBox 的 ItemsSource 始终包含所有值,它只是根据右侧列表中的 Items 进行视觉过滤。

If you wanted the ItemsSource of the LeftListBox and the RightListBox to change in relation to each other you should consider changing your xaml as below:如果您希望 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}" />

and your code behind as below:您的代码如下:

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);
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM