Retrieving WPF ListBox.SelectedItems was surprisingly difficult

3 minute read

(Added on 2020/09/17)
In the comments, you can find what made me smarter. I’ll leave the content of this article as it is for my later studies, but please take a look at the comments. @soi Thank you for pointing out and commenting.

(Added on 2020/09/18)
I came up with a way to reduce the amount of code when there are multiple list boxes, so I wrote it in [here] [].
[Here]: https://qiita.com/Michio029/items/fd597470cc62cfa79ed7 “Method to get ListBox.SelectedItems” that can be reused in WPF

(Added on 2020/09/26)
[Comment in another article] [] gave me the easiest way to get ListBox.SelectedItems that I know.

background

The SelectedItem of the ListBox provided in WPF is easy to retrieve, but it was a little difficult to retrieve the SelectedItem “s”, so it is a memorandum.

I wrote in [Separate article] [] how to retrieve SelectedItem (single selection).
[Separate article]: https://qiita.com/Michio029/items/a12a9bac3b7df24397ee “Get ListBox.SelectedItem of Class item in WPF”

Preparation

Prepare the ListBox and its contents
image.png

MainWindow.xaml


<Window><!--Window details are omitted-->
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="50"/>
        </Grid.RowDefinitions>
        
        <ListBox Grid.Row="0" Name="ExampleList" Margin="10" SelectionMode="Extended" ScrollViewer.VerticalScrollBarVisibility="Auto">
            <!-- SelectionMode="Extended" :ctrl,shift+Multiple selections can be made by clicking-->
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding Id, StringFormat=ID is{0} :}"/>
                        <TextBlock Text="{Binding Name, StringFormat=Name is{0} :}"/>
                        <TextBlock Text="{Binding Age, StringFormat=Age is{0}}"/>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        <Button Grid.Row="1" Name="Btn" Content="button" Margin="100,10,100,10" Click="Btn_Click"/>
    </Grid>
</Window>

<textblock text="{binding id, stringformat=id is{0} :}"/>
You can read more about how to write the format of the string in this area here.
https://qiita.com/koara-local/items/815eb5146b3ddc48a8c3

c#:MainWindow.xaml.cs


public partial class MainWindow : Window
{
    List<ExampleClass> list = new List<ExampleClass>();
    public MainWindow()
    {
        InitializeComponent();

        list.Add(new ExampleClass() { Id = 0, Name = "aaa", Age = 10 });
        list.Add(new ExampleClass() { Id = 1, Name = "bbb", Age = 20 });
        list.Add(new ExampleClass() { Id = 2, Name = "ccc", Age = 30 });
        list.Add(new ExampleClass() { Id = 3, Name = "ddd", Age = 40 });
        list.Add(new ExampleClass() { Id = 4, Name = "eee", Age = 50 });
        ExampleList.ItemsSource = list;
    }

    private void Btn_Click(object sender, RoutedEventArgs e)
    {

    }
}
class ExampleClass
{
    public int Id { get; set; }
    public string Name { get; set; }
    public byte Age { get; set; }
}

Take a look at the contents of the selected state

I want to know what is happening when multiple selections are made, so I will set a breakpoint when I press the button.
image.png
Press the button to break.
image.png
Apparently, SelectedItems themselves are an array, and the contents are the same as SelectedItems.
Count seems to start at 1 instead of 0. Since 3 are being selected, 3.

Looking at this, I feel that I can retrieve it if I do the same thing as when fetching SelectedItem (single selection) in foreach.

Extract SelectedItems

Add the operation to the button

    private void Btn_Click(object sender, RoutedEventArgs e)
    {
        //The selection item is 0=>Exit the method
        if (ExampleList.SelectedItems.Count == 0)
            return;

        //Declare an empty array
        int[] _id = new int[0];
        string[] _name = new string[0];
        byte[] _age = new byte[0];

        int i = 0;

        //Extract the contents of Selected Items
        foreach (var oneItemLine in ExampleList.SelectedItems)
        {
            //Increase the array box by one
            int reLength = _id.Length + 1;
            Array.Resize(ref _id, reLength);
            Array.Resize(ref _name, reLength);
            Array.Resize(ref _age, reLength);

            //Extract as ExampleClass
            ExampleClass item = oneItemLine as ExampleClass;
            _id[i] = item.Id;
            _name[i] = item.Name;
            _age[i] = item.Age;
            i++;
        }

        //There are three selections (SelectedItems).Count=If 3), I want you to loop 3 times (n)=0,1,2) so n< SelectedItems.count
        for (int n = 0; n < ExampleList.SelectedItems.Count; n++)
        {
            Console.WriteLine("Id:「{0}」 Name:「{1}」 Age:「{2}」", _id[n], _name[n], _age[n]);
        }
    }



Try to run and press the button

Id:「0」 Name:「aaa」 Age:「10」
Id:「1」 Name:「bbb」 Age:「20」
Id:「2」 Name:「ccc」 Age:「30」

I got it.

Apparently the items are in the selected order.

Id:「4」 Name:「eee」 Age:「50」
Id:「2」 Name:「ccc」 Age:「30」
Id:「0」 Name:「aaa」 Age:「10」