Method to get ListBox.SelectedItems that can be reused in WPF

7 minute read

(Added on 2020/09/22)
By using the “generic method”, I found that the caller can specify the part of List <T> that corresponds to ```` ``. It is described as Method-kun ② to get the contents of the list box and the final code as a whole ②. Thank you, @MinoruSanou.

(Added on 2020/09/26)
I wrote a long article, but @ TN8001’s [Comment here] [] posted the code to get the simplest ListBox.SelectedItem I know at the moment. Thank you TN8001.
[Comment here]: https://qiita.com/Michio029/items/fd597470cc62cfa79ed7#comment-e4c149eb4e00ada84c49

background

Previously I wrote how to retrieve the contents of ListBox.SelectedItems in here. However, when there are multiple ListBoxes, the amount of code is large and it gets in the way, so I thought of a dedicated method to get the contents.

Preparation

Make multiple lists (two this time) in WPF.
Set list items in c #

image.png

MainWindow.xaml


<Window>
    <Grid>
        <!--Divided into two parts-->
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!--Upper half-->
        <Grid Grid.Row="0">
            <Grid.RowDefinitions>
                <RowDefinition Height="25"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="25"/>
            </Grid.RowDefinitions>

            <Label Grid.Row="0" Content="List box 1"/>
            <ListBox Grid.Row="1" Name="ExampleList1" 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="2" Name="Btn1" Content="Button 1" Margin="50,0,50,0" Click="Btn1_Click"/>
        </Grid>

        <!--Lower half-->
        <Grid Grid.Row="1">
            <Grid.RowDefinitions>
                <RowDefinition Height="25"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="25"/>
            </Grid.RowDefinitions>

            <Label Grid.Row="0" Content="List box 2" Grid.ColumnSpan="2"/>
            <ListBox Grid.Row="1" Name="ExampleList2" Margin="10" SelectionMode="Extended" ScrollViewer.VerticalScrollBarVisibility="Auto" Grid.ColumnSpan="2">
                <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="2" Name="Btn2" Content="Button 2" Margin="50,0,50,0" Click="Btn2_Click" Grid.ColumnSpan="2"/>
        </Grid>
    </Grid>
</Window>

c#:MainWindow.xaml.cs


/// <summary>
/// MainWindow.xaml interaction logic
/// </summary>
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 });
        ExampleList1.ItemsSource = list;
        ExampleList2.ItemsSource = list;
    }

    private void Btn1_Click(object sender, RoutedEventArgs e)
    {
        //Extract the selected item in list box 1
    }

    private void Btn2_Click(object sender, RoutedEventArgs e)
    {
        //Extract the selected item in list box 2
    }
}
class ExampleClass
{
    public int Id { get; set; }
    public string Name { get; set; }
    public byte Age { get; set; }
}

Method to get the contents of the list box

This is the main subject. Call this method wherever you want to know the list selection item.

c#:MainWindow.xaml.cs


    //!Method to retrieve the contents of SelectedItems
    private List<ExampleClass> GetSelectedItems(ListBox listBox)
    {
        List<ExampleClass> selItems = new List<ExampleClass>();
        foreach (var oneItemLine in listBox.SelectedItems)
        {
            ExampleClass item = oneItemLine as ExampleClass;
            selItems.Add(item);
        }
        return selItems;
    }



Call from each button.
I referred to [here] [2] for how to find the target control.
[2]: https://qiita.com/7of9/items/2dd05738a66a71bb3c11 “Visual Studio | WPF> Find Control by Name> FindName ()”

c#:MainWindow.xaml.cs


    //!Show selected items in list box 1
    private void Btn1_Click(object sender, RoutedEventArgs e)
    {
        //Control to operate
        string controlName = "ExampleList1";

        //Find the list box
        object controlObj = FindName(controlName);
        ListBox listBox = (ListBox)controlObj;

        //The selection item is 0=>Exit the method
        if (listBox.SelectedItems.Count == 0)
            return;

        //Get the selected item
        List<ExampleClass> selItems = GetSelectedItems(listBox);

        //What to display in the message box
        string message = "";
        foreach (var line in selItems)
        {
            message = message + string.Format("\r\nId:「{0}」 Nmae:「{1}」 Age:「{2}」", line.Id, line.Name, line.Age);
        }
        message = string.Format($"{controlName}The item selected in\r\n{message}\r\n\r\is n");

        MessageBox.Show(message);
    }

    //!Display the selected item in list box 2
    private void Btn2_Click(object sender, RoutedEventArgs e)
    {
        //Almost the same as Listing 1. Just change the Contorol Name.
    }

When you press button 1
image.png
The selected item has been retrieved. The same is true for button 2.
But the codes for buttons 1 and 2 are almost the same, so I’d like to summarize them. The final code I put together is at the end.

The whole final code

ExampleClass has not changed, so it will be omitted.

c#:MainWindow.xaml.cs


/// <summary>
/// MainWindow.xaml interaction logic
/// </summary>
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 });
        ExampleList1.ItemsSource = list;
        ExampleList2.ItemsSource = list;
    }

    //!Show selected items in list box 1
    private void Btn1_Click(object sender, RoutedEventArgs e)
    {
        //Control to operate
        string controlName = "ExampleList1";

        ItemShow(controlName);
    }

    //!Display the selected item in list box 2
    private void Btn2_Click(object sender, RoutedEventArgs e)
    {
        //Control to operate
        string controlName = "ExampleList2";

        ItemShow(controlName);
    }

    //Extract the contents of SelectedItems-Message display method
    private void ItemShow(string controlName)
    {
        //Find the list box
        object controlObj = FindName(controlName);
        ListBox listBox = (ListBox)controlObj;

        //The selection item is 0=>Exit the method
        if (listBox.SelectedItems.Count == 0)
            return;

        //Get the selected item
        List<ExampleClass> selItems = GetSelectedItems(listBox);

        //What to display in the message box
        string message = "";
        foreach (var line in selItems)
        {
            message = message + string.Format("\r\nId:「{0}」 Nmae:「{1}」 Age:「{2}」", line.Id, line.Name, line.Age);
        }
        message = string.Format($"{controlName}The item selected in\r\n{message}\r\n\r\is n");

        MessageBox.Show(message);
    }

    //!Method to retrieve the contents of SelectedItems
    private List<ExampleClass> GetSelectedItems(ListBox listBox)
    {
        List<ExampleClass> selItems = new List<ExampleClass>();
        foreach (var oneItemLine in listBox.SelectedItems)
        {
            ExampleClass item = oneItemLine as ExampleClass;
            selItems.Add(item);
        }
        return selItems;
    }
}

image.png
image.png
image.png
Items are acquired in the order in which they are clicked.

Method to get the contents of the list box ②

The following is a postscript of 2020/09/22.
You can specify T in the caller by using a generic method. This improves usability. The return value selItems is of type List ` ``.

python


public List<T> GetSelectedItems<T>(ListBox listBox) where T : class
{
    var selItems = new List<T>();
    foreach (var oneItemLine in listBox.SelectedItems)
    {
        var item = oneItemLine as T;
        selItems.Add(item);
    }
    return selItems;
}



You can write this in MainWindow.xaml.cs as it is, but since the degree of freedom of reuse has increased, I would like to make it an independent class.

GetSelectedItems.cs


class GetSelectedItems<T> where T : class
{
    ListBox listBox;

    public GetSelectedItems(ListBox listBox)
    {
        this.listBox = listBox;
    }

    //!Method to retrieve the contents of SelectedItems
    public List<T> Get()
    {
        var selItems = new List<T>();
        foreach (var oneItemLine in listBox.SelectedItems)
        {
            var item = oneItemLine as T;
            selItems.Add(item);
        }
        return selItems;
    }
}



You can retrieve the contents of SelectedItems by writing the following in the caller. Var selItems is of type List ` `` and contains the selected list box items.

    //Find the list box
    object controlObj = FindName(controlName);
    ListBox listBox = (ListBox)controlObj;

    //Get the selected item
    GetSelectedItems<ExampleClass> g = new GetSelectedItems<ExampleClass>(listBox);
    var selItems = g.Get();

The whole final code ②

Since the content has increased, I will write the entire description of c #.

c#:MainWindow.xaml.cs


/// <summary>
/// MainWindow.xaml interaction logic
/// </summary>
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 });
        ExampleList1.ItemsSource = list;
        ExampleList2.ItemsSource = list;
    }

    //!Show selected items in list box 1
    private void Btn1_Click(object sender, RoutedEventArgs e)
    {
        //Control to operate
        string controlName = "ExampleList1";

        ItemShow(controlName);
    }

    //!Display the selected item in list box 2
    private void Btn2_Click(object sender, RoutedEventArgs e)
    {
        //Control to operate
        string controlName = "ExampleList2";

        ItemShow(controlName);
    }

    //Extract the contents of SelectedItems-Message box display method
    private void ItemShow(string controlName)
    {
        //Find the list box
        object controlObj = FindName(controlName);
        ListBox listBox = (ListBox)controlObj;

        //The selection item is 0=>Exit the method
        if (listBox.SelectedItems.Count == 0)
            return;

        //Get the selected item
        GetSelectedItems<ExampleClass> g = new GetSelectedItems<ExampleClass>(listBox);
        var selItems = g.Get();

        //What to display in the message box
        string message = "";
        foreach (var line in selItems)
        {
            message = message + string.Format("\r\nId:「{0}」 Nmae:「{1}」 Age:「{2}」", line.Id, line.Name, line.Age);
        }
        message = string.Format($"{controlName}The item selected in\r\n{message}\r\n\r\is n");

        MessageBox.Show(message);
    }
}

ExampleClass.cs


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

GetSelectedItems.cs


class GetSelectedItems<T> where T : class
{
    ListBox listBox;

    public GetSelectedItems(ListBox listBox)
    {
        this.listBox = listBox;
    }

    //!Method to retrieve the contents of SelectedItems
    public List<T> Get()
    {
        var selItems = new List<T>();
        foreach (var oneItemLine in listBox.SelectedItems)
        {
            var item = oneItemLine as T;
            selItems.Add(item);
        }
        return selItems;
    }
}