Method to get ListBox.SelectedItems that can be reused in WPF
(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 ```
(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 #
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
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;
}
}
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
//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;
}
}