I have a multiselection listbox. I want to see the last selected item (which the user just selected). I can't find any way to do this googling..

Thanks in advance.

Here's a solution. Version 2 code has been tested.

Create a new class called "ItemInfo". Replace with the following code:

ItemInfo:

    public class ItemInfo
    {
        public string Name { get; set; }
        public string SelectionType { get; set; }
    }

In your form, (ex: Form1.cs), do the following:

Create a list to hold the previously selected items and an instance of ItemInfo.

    public partial class Form1 : Form
    {
        List<string> previousSelectedItemsList = new List<string>();
        ItemInfo lastItem = new ItemInfo();

        public Form1()
        {
            InitializeComponent();
        }
    }

Then we create a method to find the last selected item:

Version 1
(keeps track of last selected item):

private void getLastItemChanged(ref ListBox lb)
{
    List<string> lastItemSelected;


    List<string> currentSelectedItemsList = new List<string>();

    //put selected items into a list
    //so we can use list.except

    for (int i = 0; i < lb.SelectedItems.Count; i++)
    {
        //add selected items to list
        currentSelectedItemsList.Add(lb.SelectedItems[i].ToString());

        //Console.WriteLine("item: " + lb.SelectedItems[i]);
    }//for

    //get last item selected as a list
    //by comparing the current list
    //to the previous list

    lastItemSelected = currentSelectedItemsList.Except(previousSelectedItemsList).ToList();

    //if last item was selected count > 0
    //else if last item was de-selected 
    //lastItemSelected.Count = -1

    if (lastItemSelected.Count > 0)
    {
        lastItem.Name = lastItemSelected[0].ToString();
        lastItem.SelectionType = "selected";
    }//if


     Console.WriteLine(lastItem.Name + " : " + lastItem.SelectionType);

     //updated previousSelectedItems before returning
     previousSelectedItemsList = currentSelectedItemsList;
}//getLastItemChanged

Version 2
(keeps track of last item - selected OR de-selected):

private void getLastItemChanged(ref ListBox lb)
{
    List<string> lastItemSelected;
    List<string> lastItemDeSelected;

    List<string> currentSelectedItemsList = new List<string>();

    //put selected items into a list
    //so we can use list.Except
    for (int i = 0; i < lb.SelectedItems.Count; i++)
    {
        //add selected items to list
        currentSelectedItemsList.Add(lb.SelectedItems[i].ToString());

        //Console.WriteLine("item: " + lb.SelectedItems[i]);
    }//for

    //get last item selected as a list
    //by comparing the current list
    //to the previous list

    lastItemSelected = currentSelectedItemsList.Except(previousSelectedItemsList).ToList();

    //if last item was selected count > 0
    //else if last item was de-selected 
    //lastItemSelected.Count = -1

    if (lastItemSelected.Count > 0)
    {
        lastItem.Name = lastItemSelected[0].ToString();
        lastItem.SelectionType = "selected";
    }//if
    else
    {
        //if item was deselected, switch the order
        //compare previous list to current list
        lastItemDeSelected = previousSelectedItemsList.Except(currentSelectedItemsList).ToList();

        //if > 0, last item was de-selected
        if (lastItemDeSelected.Count > 0)
        {
            lastItem.Name = lastItemDeSelected[0].ToString();
            lastItem.SelectionType = "de-selected";
        }//if
     }//else

     Console.WriteLine(lastItem.Name + " : " + lastItem.SelectionType);

     //updated previousSelectedItems before returning
     previousSelectedItemsList = currentSelectedItemsList;
}//getLastItemChanged

Then in the ListBox SelectedValueChanged event handler (ex: listBox1_SelectedValueChanged), we call "getLastItemChanged":

private void listBox1_SelectedValueChanged(object sender, EventArgs e)
{
    getLastItemChanged(ref listBox1);
}

List.Except code adapted from here.

Edited 2 Years Ago by cgeier

I re-worked the above code to create a version that allows you to specify if you want the last "Selected" item, the last "De-selected" item, or last item that was changed (either "Selected" or "De-selected").

Create a new class called "ItemInfo". Replace the code with the following:
ItemInfo:

public class ItemInfo
{
    public string Name { get; set; }
    public string SelectionType { get; set; }
}

In the form (Form1), create a list, a new instance of ItemInfo, and an enum as seen below:

public partial class Form1 : Form
{
    //holds previously selected items
    List<string> previousSelectedItemsList = new List<string>();

    //holds the last selected and/or de-selected item
    ItemInfo lastItem = new ItemInfo();

    //create an enumeration 
    enum SelectionType { Deselected, Either, Selected }; 

    public Form1()
    {
        InitializeComponent();
    }
}

Now, we will create a method that will compare our lists and return an ItemInfo object:

private ItemInfo findExcludedItemInList(List<string> list1, List<string> list2)
{
    ItemInfo item = new ItemInfo();

    //get list of items in list1 that aren't in list2
    var lastItemList1 = list1.Except(list2).ToList();

    if (lastItemList1.Count > 0)
    {
        //there should only be 1 item in the list
        item.Name = lastItemList1[0].ToString();
        item.SelectionType = "Selected";
    }//if
    else
    {
        //get list of items in list2 that aren't in list1
        var lastItemList2 = list2.Except(list1).ToList();

        if (lastItemList2.Count > 0)
        {
            //there should only be 1 item in the list
            item.Name = lastItemList2[0].ToString();
            item.SelectionType = "Deselected";
        }//if
    }//else

    return item;
}//findExcludedItemInList

Next, we will create a method "getLastItemChanged" that will use "findExcludedItemInList".

private void getLastItemChanged(ref ListBox lb,  ref ItemInfo lastItem, ref List<string> previousSelectedItemsList, SelectionType sType)
{

    List<string> currentSelectedItemsList = new List<string>();

    //put selected items into a list
    //so we can use list.Except
    for (int i = 0; i < lb.SelectedItems.Count; i++)
    {
        currentSelectedItemsList.Add(lb.SelectedItems[i].ToString());
        //Console.WriteLine("item: " + lb.SelectedItems[i]);
    }//for

    if (sType.Equals(SelectionType.Either))
    {
        lastItem = findExcludedItemInList(currentSelectedItemsList, 
                                          previousSelectedItemsList);

        Console.WriteLine(lastItem.Name + " : " + lastItem.SelectionType);
    }//if
    else if (sType.Equals(SelectionType.Selected))
    {
        //get last item selected as a list
        //by comparing the current list
        //to the previous list

        if (String.Compare(findExcludedItemInList(currentSelectedItemsList,
                           previousSelectedItemsList).SelectionType, "Selected", true) == 0)
        {
            lastItem = findExcludedItemInList(currentSelectedItemsList,
                                              previousSelectedItemsList);

            Console.WriteLine(lastItem.Name + " : " + lastItem.SelectionType);
        }//if
    }//else if
    else if (sType.Equals(SelectionType.Deselected))
    {
        //if item was deselected, switch the order
        //compare previous list to current list

        //if > 0, last item was de-selected
        if (String.Compare(findExcludedItemInList(currentSelectedItemsList, 
                           previousSelectedItemsList).SelectionType, "Deselected", true) == 0)
        {
            lastItem = findExcludedItemInList(currentSelectedItemsList, 
                                              previousSelectedItemsList);

            Console.WriteLine(lastItem.Name + " : " + lastItem.SelectionType);
        }//if
    }//else if


    //updated previousSelectedItems before returning
    previousSelectedItemsList = currentSelectedItemsList;
}//getLastItemChanged

Then in the ListBox SelectedValueChanged event handler (ex: listBox1_SelectedValueChanged), we call "getLastItemChanged":

private void listBox1_SelectedValueChanged(object sender, EventArgs e)
{
    //get only last selected item
    //getLastItemChanged(ref listBox1, ref lastItem, ref previousSelectedItemsList, SelectionType.Selected);

    //get only last Deselected item
    //getLastItemChanged(ref listBox1, ref lastItem, ref previousSelectedItemsList, SelectionType.Deselected);

    //get last changed item - Selected or Deselected
    getLastItemChanged(ref listBox1, ref lastItem, ref previousSelectedItemsList, SelectionType.Either);

    Console.WriteLine("lastItem: " + lastItem.Name + " Type: " + lastItem.SelectionType);
}

Edited 2 Years Ago by cgeier

Comments
Bad coding standards, numerous ref used unnecessarily. No SoC. "But it works" is not something you should aim for.
Great effort

There is no need to pass any of that stuff by reference, remove it all. You mix modes (windows controls writing to the console). Your methods have overly complicated signatures and almost all that code (if not all of it) should be inside a different class, not in your form. It is a ListBox monitor, code it as such.

Comments

Tough crowd. The Console.WriteLine statements were for debugging. I left them in so that one could verify the results. They should be removed when finished debugging.

Here is an updated version:
The concept of the code is the same. However, I moved the majority of the code to it's own class: ListBoxMonitor. "getLastItemChanged" now returns an "ItemInfo" object. I removed some parameters from "getLastItemChanged" and made them private variables in class ListBoxMonitor. I've also made ListBoxMonitor static.

Create a new class called "ListBoxMonitor.cs" and replace with the following code:

    public static class ListBoxMonitor
    {
        //holds the last item that was changed
        //based on SelectionType chosen by user
        private static ItemInfo lastItem = new ItemInfo();

        //holds the previously selected list items
        private static List<string> previousSelectedItemsList = new List<string>();

        //create an enumeration 
        public enum SelectionType { Deselected, Either, Selected }; 


        public static ItemInfo getLastItemChanged(System.Windows.Forms.ListBox lb, SelectionType sType)
        {

            List<string> currentSelectedItemsList = new List<string>();

            //put selected items into a list
            //so we can use list.Except
            for (int i = 0; i < lb.SelectedItems.Count; i++)
            {
                currentSelectedItemsList.Add(lb.SelectedItems[i].ToString());
            }//for

            if (sType.Equals(SelectionType.Either))
            {
                lastItem = findExcludedItemInList(currentSelectedItemsList,
                                                  previousSelectedItemsList);
            }//if
            else if (sType.Equals(SelectionType.Selected))
            {
                //get last item selected as a list
                //by comparing the current list
                //to the previous list

                if (String.Compare(findExcludedItemInList(currentSelectedItemsList,
                    previousSelectedItemsList).SelectionType, "Selected", true) == 0)
                {
                    lastItem = findExcludedItemInList(currentSelectedItemsList,
                               previousSelectedItemsList);
                }//if
            }//else if
            else if (sType.Equals(SelectionType.Deselected))
            {
                //if item was deselected, switch the order
                //compare previous list to current list

                //if > 0, last item was de-selected
                if (String.Compare(findExcludedItemInList(currentSelectedItemsList,
                    previousSelectedItemsList).SelectionType, "Deselected", true) == 0)
                {
                    lastItem = findExcludedItemInList(currentSelectedItemsList,
                                                      previousSelectedItemsList);
                }//if
            }//else if



            //updated previousSelectedItems before returning
            previousSelectedItemsList = currentSelectedItemsList;

            return lastItem;
        }//getLastItemChanged

        private static ItemInfo findExcludedItemInList(List<string> list1, List<string> list2)
        {
            ItemInfo item = new ItemInfo();

            //get list of items in list1 that aren't in list2
            var lastItemList1 = list1.Except(list2).ToList();

            if (lastItemList1.Count > 0)
            {
                //there should only be 1 item in the list
                item.Name = lastItemList1[0].ToString();
                item.SelectionType = "Selected";
            }//if
            else
            {
                //get list of items in list2 that aren't in list1
                var lastItemList2 = list2.Except(list1).ToList();

                if (lastItemList2.Count > 0)
                {
                    //there should only be 1 item in the list
                    item.Name = lastItemList2[0].ToString();
                    item.SelectionType = "Deselected";
                }//if
            }//else

            return item;
        }//findExcludedItemInList

    }//class

Usage:

    public partial class Form1 : Form
    {

        ItemInfo lastItem = null;

        public Form1()
        {
            InitializeComponent();
        }


        private void listBox1_SelectedValueChanged(object sender, EventArgs e)
        {
            //get only last selected item
            //lastItem = ListBoxMonitor.getLastItemChanged(listBox1, ListBoxMonitor.SelectionType.Selected);

            //get only last Deselected item
            //lastItem = ListBoxMonitor.getLastItemChanged(listBox1, ListBoxMonitor.SelectionType.Deselected);

            //get last changed item - Selected or Deselected
            lastItem = ListBoxMonitor.getLastItemChanged(listBox1, ListBoxMonitor.SelectionType.Either);

        }
    }

Edited 2 Years Ago by cgeier

I remembered that I can use CheckedBox instead.
Thanks all and I studied your code and learned new things.

This question has already been answered. Start a new discussion instead.