WPFのListBox.SelectedItems(複数選択)を取り出すのが意外と大変だった

（2020/09/17追記）
私が掲載した内容をよりスマートにして頂いた内容が、 [コメント] にあります。私の後学のために本記事の内容はそのままにしますが、是非コメントにも目を通してみて下さい。@soi さんご指摘、解説ありがとうございます。

[コメント]:https://qiita.com/Michio029/items/3b531acd46bb1f81f7d7#comment-68d8a5dd4c53b995290c

（2020/09/18追記）
リストボックスが複数ある場合に、コード量をもっと少なくする方法を思いついたので、[こちら][] に書きました。
[こちら]:https://qiita.com/Michio029/items/fd597470cc62cfa79ed7 "WPFで使いまわしができる「ListBox.SelectedItemsを取得するメソッド」"

（2020/09/26追記）
僕が知る中で一番簡単な ```ListBox.SelectedItems``` を取得する方法を [別記事のコメント][] に頂きました。 

[別記事のコメント]:https://qiita.com/Michio029/items/fd597470cc62cfa79ed7#comment-e4c149eb4e00ada84c49

#背景
WPF に用意されている ListBox の SelectedItem は簡単に取り出せるのですが SelectedItem"s" を取り出すのに少し苦労したのでその備忘録です。

SelectedItem（単体選択）の取り出し方は [別記事][] に書きました。
[別記事]:https://qiita.com/Michio029/items/a12a9bac3b7df24397ee "WPFで中身がClassアイテムのListBox.SelectedItemを取得する"


#準備
ListBoxとその中身を用意します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/301115/474b3fae-e8ef-9e33-ca72-f94a8898d3cd.png)


```xml:MainWindow.xaml
<Window><!-- Windowの細かいのは省略 -->
    <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+クリックで複数選択可能 -->
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding Id, StringFormat=IDは{0}　：}"/>
                        <TextBlock Text="{Binding Name, StringFormat= Nameは{0}　：}"/>
                        <TextBlock Text="{Binding Age, StringFormat= Ageは{0}}"/>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        <Button Grid.Row="1" Name="Btn" Content="ボタン" Margin="100,10,100,10" Click="Btn_Click"/>
    </Grid>
</Window>

```

```<TextBlock Text="{Binding Id, StringFormat=IDは{0}　：}"/>```
この辺の文字列のフォーマットの書き方についてはこちらで詳しく解説してくれています。
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; }
}
```

#選択状態の中身を見てみる
複数選択時の中身がどうなっているのか知りたいので、ボタンを押すところでブレークポイントを設定してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/301115/e27421d6-4b36-4431-e4fc-4ec150b817b3.png)
ボタンを押してブレークします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/301115/01dac01e-8f80-9a51-1b6e-0d1971573bbe.png)
どうやら SelectedItems 自体は配列になっていて、その中身が SelectedItem と同じっぽいです。
Count は 0 からではなく 1 から始まるみたいですね。3つ選択中なので3。

これを見ると foreach の中で SelectedItem（単体選択） を取り出すときと同じことをしたら取り出せる気がします。

#SelectedItems（複数選択）を取り出す
ボタンに動作を追記します

```c#
    private void Btn_Click(object sender, RoutedEventArgs e)
    {
        // 選択項目が0 => メソッドを出る
        if (ExampleList.SelectedItems.Count == 0)
            return;

        // 空の配列を宣言
        int[] _id = new int[0];
        string[] _name = new string[0];
        byte[] _age = new byte[0];

        int i = 0;

        // SelectedItemsの中身を取り出す
        foreach (var oneItemLine in ExampleList.SelectedItems)
        {
            // 配列の箱を一つ増やす
            int reLength = _id.Length + 1;
            Array.Resize(ref _id, reLength);
            Array.Resize(ref _name, reLength);
            Array.Resize(ref _age, reLength);

            // ExampleClassとして取り出す
            ExampleClass item = oneItemLine as ExampleClass;
            _id[i] = item.Id;
            _name[i] = item.Name;
            _age[i] = item.Age;
            i++;
        }

        // 三つ選択がある（SelectedItems.Count=3）としたら、3回ループして欲しい（n=0,1,2）ので 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]);
        }
    }
```

<br>
実行してボタンを押してみます

```
Id:「0」 Name:「aaa」　Age:「10」
Id:「1」 Name:「bbb」　Age:「20」
Id:「2」 Name:「ccc」　Age:「30」
```
取れました。

どうやら項目は選択した順に入っていくようです。

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