Sort or delete ListBox Item Wpf
Posted by austinslik on February 23, 2010
This example will show a simple way to delete or sort listbox selectedItem using WPF C#.
Let’s start with creating xaml mark-up that includes a button, a combobox and a listbox. It should look like this
<Window x:Class="CommandBinding.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorLib" xmlns:local="clr-namespace:CommandBinding" Title="Window1" Height="308" Width="194" WindowStartupLocation="CenterScreen"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="20"/> <RowDefinition Height="*" /> <RowDefinition Height="20" /> </Grid.RowDefinitions> <StackPanel Orientation="Horizontal" Grid.Row="0"> <ComboBox Width="100" x:Name="_comboBox" SelectedIndex="0" SelectionChanged="_comboBox_SortBySelection" > <sys:String>Id</sys:String> <sys:String>FirstName</sys:String> <sys:String>LastName</sys:String> </ComboBox> </StackPanel> <ListBox x:Name="_listBox" Grid.Row="1"> </ListBox> </Grid> </Window>
Notice that the combobox has
<sys:String>Id</sys:String> <sys:String>FirstName</sys:String> <sys:String>LastName</sys:String>
This is because it’s a small sample. It can also be done by binding the combobox to an enum.
The
SelectionChanged="_comboBox_SortBySelection"
will be explained shortly. So let’s move on to code behind.
Here we need some data to work with so we’ll start by creating a person object that looks like this
class Person
{
private readonly int _id;
private readonly string _firstName;
private readonly string _lastName;
public Person(int id, string firstName, string lastName)
{
_id = id;
_firstName = firstName;
_lastName = lastName;
}
public int Id { get{return _id; }}
public string FirstNam { get{return _firstName; }}
public string LastName { get{return _lastName;}}
}
And a collection class that will inherit observable collection to collect our person object we’ve just created. It looks like this
class PersonsCollection:ObservableCollection<Person>
{
public PersonsCollection()
{
Add(new Person(5, "A", "B"));
Add(new Person(3, "A", "B"));
Add(new Person(2, "A", "B"));
Add(new Person(6, "A", "B"));
Add(new Person(1, "A", "B"));
Add(new Person(4, "A", "B"));
}
}
You can fill the “A”,”B” with any name of your choice.
Notice the observable collection has the person class in its greater and less than bracket<Person> which in original definition ObservableCollection<T> The T means generic which means we can throw any object in there and it will hold it and allow add,delete, etc more about observableCollection.
So now that we have some data we need to bind it to our listbox i.e. we need to modify our xaml mark-up a little but first we need supply the listboxItemsource with some data in the constructor(this can also done in xaml but i prefer c#) like this
_listBox.ItemsSource = new PersonsCollection();
and in the listbox marp-up would look like this
<ListBox x:Name="_listBox" Grid.Row="1">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" >
<TextBlock Text="{Binding Path=Id}" xml:space="preserve"/>
<TextBlock Text="{Binding Path=FirstName}" xml:space="preserve"/>
<TextBlock Text="{Binding Path=LastName}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Binding is beyond the scope of this tutorial. At this stage if you hit key Ctrl+F5 you should get
Now we see our data but can’t sort or delete. Let’s start with sorting by initializing a new instance of the System.Window.Input.RoutedUICommand class which takes some information as parameter e.g.
public static RoutedUICommand = new RoutedUICommand(descriptive text for the command,the declared name of the command for serialization, type that is registering the command (which is the class where is’s being instantiated)).
The code will look like this
public static RoutedUICommand SortPerson = new RoutedUICommand("SortPerson","SortPerson", typeof(Window1));
then in the constructor we’ll call on a property commandbindings from a CommadbingsCollection initialized in UIElement class. It is a collection that gets all the CommandBinding objects (that can be executed) associated with the element SortPerson we created. The code looks like this:
CommandBindings.Add(System.Windows.Input.CommandBinding(SortPerson, SortEventEventArgs)).
Notice SortEventEventArgs in the bracket; this is an ExecutedRoutedEventArgs function that is associated with SortPerson. So let’s go ahead and create it
private void SortEventEventArgs(object sender, ExecutedRoutedEventArgs e)
{
ListCollectionView view =
(ListCollectionView)CollectionViewSource.GetDefaultView
(_listBox.ItemsSource);
view.SortDescriptions.Clear();
view.SortDescriptions.Add(
new SortDescription(e.Parameter.ToString(),ListSortDirection.Ascending));
}
Notice the ListCollectionView. Brief explanation: it provides us the features like Navigation, Sorting, Filtering and Grouping. You can see that the listboxItemSource is added to the listcollectionview… that will supply the listcollectionview with data so that we can navigate, sort, filter or group them. Now the last thing we need to do for sorting is to send a command to listcollectionview with a sort criteria to sort with and that can be done by adding a SelectionChanged to combobox and in the event function we will create the command. In xaml mark-up of combobox we will add something like this SelectionChanged=”_comboBox_SortBySelection” which we’ve already done above. Now in the code behind we’ll create an event function that looks like this
private void _comboBox_SortBySelection(object sender, SelectionChangedEventArgs e)
{
ICommand comand = SortPerson;
comand.Execute(e.AddedItems[0]);
}
Inside the this function we created a command by creating an instance of ICommand Class and initialized it with the element SortPerson which is an instance of RoutedUICommand. Now we can use its Execute method to pass a sort criteria as a parameter. If an item is selected then the combobox selectionChanged will trigger this command (Comman.Execute(e.AddedItems[0])) to pass the newly selected item to listcollectionview as string to sort with that coloumn. At this point if you hit key Ctrl+F5 you would be able to sort the listbox items.
Now that we can sort the listbox let’s start with delete. Here we don’t have to do much, first create the same kind of RoutedUICommand like the one we created earlier like this
public static RoutedUICommand DeletePerson =
new RoutedUICommand("DeletePerson", "DeletePerson", typeof(Window1))
and create an event function just like we did above like this
private void DeleteEventArgs(object sender, ExecutedRoutedEventArgs e)
{
Person selectedItem = (Person)e.Parameter;
dataSource.Remove(selectedItem);
}
Now what we are doing here in the function is just casting the received object back to person object (to the type datasource recognises ) so we can remove it from our datasource, don’t forget our data source is the class PersonCollection. We need to add the above function to Commandbindings like we deed with sorting like this
CommandBindings.Add(new System.Windows.Input.CommandBinding(DeletePerson, DeleteEventArgs, CanExecuteEventHandler))
the third parameter “CanExecuteEventHandler” will be explained shortly. Next we will go and modify our xaml a little so the button we created will do something when its clicked and we can achieve by binding (believe me in wpf anything can be bind). In the button mark-up add
Command="local:Window1.DeletePerson" CommandParameter="{Binding ElementName=_listBox, Path=SelectedItem}"
where Window1 is the name of the project class. The button mark-up would look like this
<Button Grid.Row="2" Content="Delete" x:Name="_deleteButton"
Command="local:Window1.DeletePerson"
CommandParameter="{Binding ElementName=_listBox, Path=SelectedItem}"/>
To be able to bind the RoutedIUCommand instance we create in the code behind to Command, we have to import the projects
namespace like this xmlns:local="clr-namespace:CommandBinding"
and CommandParameter is to specify the element the command is going to work with and the path(what to notice in the given element ) to selected item. the listbox and its selected item. That’s all to it. Now we can also delete.
Since this Wpf gave us some nice features like CanExecuteRoutedEventArgs which helps to decide if a command can be executed(it’s a Boolean property that returns true or false) lets add it to the delete button so that its only enable when you click on the listboxitem you would like to delete and after that it disables automatically unless an item is selected. So, lets create a function called CanExecuteEventHandler (used as a parameter in commandbindings above) like this
private void CanExecuteEventHandler(object sender, CanExecuteRoutedEventArgs e)
{
if ((e.CanExecute = e.Parameter != null) && (e.Parameter is Person))
e.Handled = true;
}
The if statement checks if something is been selected and the selected item is persons object, (that means the command associated to this element can execute) then the handle which if true will enable the element its associated to else false which means the associated element will remain disabled.
That’s all to it.
Full Source code here





