Hello all!

I am in the process of creating a restaurant application that lets the user select an item from a menu list (a listbox) and on a press of a button the selected item from the listbox transfers to to my current orders list (multicolumn listview, 3 columns; foodname, quantity and price [per item price*quantity]). After which the preceding calculations and quantity input functions are done in order to fill in the other columns of the selected index.

So for a little error handling what I would like to do is if ever the user selects an item from the listbox that is already present in the listview, I would just update the duplicate of the item in the listview with the proper data. That is, if he selects foodA from the listbox, while foodA was already present in my listview, I would just update the quantity and current price of the item.

With that in mind I just thought of using the finditemwithtext method.

After implementation I think I was successful in searching for the item but my problem now is how do I select the index (or the item itself) of the item that was found so that I could just overwrite it and redo the calculations again?

Rephrasing the previous paragraph: What I thought of was just to search the listview if the current item exists, if the method returns true, I would just select the index of the item found to be a duplicate and implement the calculations.

Here is a snippet of the searching code:

string currentItem = Convert.ToString(menuList.SelectedItem);

if (currentItem == Convert.ToString(orderList.FindItemWithText(currentItem)))
                    {
                                                //whatnow?
                     }

Recommended Answers

All 10 Replies

I'm not sure your code will work. The Convert.ToString function works differently with ListviewItem and ListboxItem. You would get something like:
Convert.ToString(menuList.SelectedItem) = "FoodA"
Convert.ToString(orderList.FindItemWithText(currentItem)) = "ListViewItem: {FoodA}"

FindItemWithText returns a ListViewItem, which has an Index property. I would use something like this:

private void menuList_SelectedIndexChanged(object sender, EventArgs e)
        {
            int Index;
            ListViewItem item = orderList.FindItemWithText(menuList.Items[menuList.SelectedIndex].ToString());
            if (item == null)
            {
                orderList.Items.Add(menuList.Items[menuList.SelectedIndex].ToString());
                Index = orderList.Items.Count - 1;
            }
            else
            {
                Index = item.Index;
            }
            MessageBox.Show("..Process changes to item at index " + Index.ToString());
        }

NOTE: You can replace menuList.Items[menuList.SelectedIndex] with menuList.SelectedItem.
The way i do it is a quirk of mine. If i'm processing a SelectedIndexChanged event i prefer to work with the SelectedIndex. That way i can be sure i'm using the newly selected value.
Not really necessary, possibly even bad form, but its jsut the way i work :)

Thank you for the reply!

EDIT:
LOL hope you haven't read this one before I edited it.

I ask, if my statement:

Convert.ToString(orderList.FindItemWithText(currentItem))

yields to a result like:

"ListViewItem: {FoodA}"

does this mean I am not really matching/finding the item? Because it has a "ListVietItem: " suffix to the string to it?

Still understanding your code, having a little trouble grasping it..

ok disregard my previous post, lol. I get it now. I'm implementing the code as of this writing. Thank you for the insight ryshad!

No problem. Just to clarify for anyone else who might read this:

The reason the results of Convert.ToString() are different is to do with how the object you are converting implements the .ToString() Method .

ListviewItem has the following:

public override string ToString() {
            return "ListViewItem: {" + Text + "}"; 
        }

Whilst a Listbox's Items is a collection of objects so it doesnt implement its own .ToString method and uses the default one.

Oh, so my first understanding is correct? I mean am I correct by thinking that the return value of the finditemwithtext method will be "ListViewItem: {" + Text + "}" ? Or just the index?

Or is my second one the correct one? In the sense that the method will return an "item" of datatype listviewitem?

Sorry for being such a noob now.

Oh and how do I access an item from a multicolumn listview with my index? Is it by:

orderList.Items[founditem.index].SubItems.[indexofcolumn]

is this correct?

Oh and as I was reading this, I came across trouble:
http://msdn.microsoft.com/en-us/library/y3h4x385.aspx

I quote:

The text parameter can specify a substring of the desired matching text. In addition, this method will return the first item that starts with the specified text. For example, if a ListView contains two list items—the first item's text set to "angle bracket" and the second item's text set to "bracket"—a call to FindItemWithText passing brack as the parameter will return the item whose text is "bracket".

This part here can be a little troublesome for me...

Since some of my items in the multicolumn listview have the same starting names (i.e. FoodA, FoodB; both of which starting with Food). What I would just be doing is I would just access the first instance that an item with a prefix string of Food from the list, irregardless if it matched the precise string that I wanted to find. (i.e. I searched for FoodB among items in the listview that contain FoodA and FoodB, and what I jjust did was access FoodA and not FoodB because it was the first instance that the method found it)

I finished my project but was still not able to do the updating of duplicate entries, any input guys?

This shouldnt cause a problem unless you have something like:

-FoodAB
-FoodA


If you search for FoodA it would return FoodAB.

You can avoid this problem by giving your items a unique ID.
Create a class to store each Item in your Listbox.
Remove all the items from the listbox in the designer, you are going to populate it at runtime with objects of your new class.

Try this:

public partial class Form1 : Form
    {
        private void Form1_Load(object sender, EventArgs e)
        {
            listItem item = new listItem();
            item.ID = "0";
            item.Text = "FoodABC";
            menuList.Items.Add(item);

            item = new listItem();
            item.ID = "1";
            item.Text = "FoodAB";
            menuList.Items.Add(item);

            item = new listItem();
            item.ID = "2";
            item.Text = "FoodA";
            menuList.Items.Add(item);

            item = new listItem();
            item.ID = "3";
            item.Text = "FoodB";
            menuList.Items.Add(item);

            //etc...
        }


        private void menuList_SelectedIndexChanged(object sender, EventArgs e)
        {
            //retrieve the item selected
            listItem selected = menuList.SelectedItem as listItem;

            int Index;

            //Items.Find returns a collection of items that have the given string as their name
            //this removes the problem of searching by text since each item has a unique ID as its name
            ListViewItem[] matches = orderList.Items.Find(selected.ID, false);

            //if no matches are found then add the item
            if (matches.Length == 0)
            {
                ListViewItem item = new ListViewItem(menuList.Items[menuList.SelectedIndex].ToString());
                item.Name = selected.ID;//unique ID from selected listItem as its name
                item.SubItems.Add("1"); //i have used fixed values for quantity and price
                item.SubItems.Add("3");//use your own implementation to fill these values
                orderList.Items.Add(item);
                Index = orderList.Items.Count - 1;
            }
            else
            {
                Index = matches[0].Index;
            }
            MessageBox.Show("..Process changes to item at index " + Index.ToString());
        }
    }

    //create class to fill your menulist
    public class listItem
    {
        public string ID { get; set; }
        public string Text { get; set; }

        //this is important. The objects ToString method is used to output text to the listbox
        //if you dont override it you will get something like "projectname.listItem.cs"
        public override string ToString()
        {
            return Text;
        }
    }
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.