CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 5 of 5
  1. #1
    Join Date
    Dec 2009
    Posts
    596

    How do I Load a Listbox with a returned dataset?

    Hello everybody. Longtime no be here. I have a class that has a function that returns a dataset. In form load of a form I want to load a listbox with what is returned from the function but I don't know how to do it. Can someone please give me a hand with some helper snippet code that I can apply to this problem super please? This the function in the class named DataDB.

    Code:
      public DataSet GetAllPetStarters()
            {
                SqlDataAdapter da = default(SqlDataAdapter);
                DataSet ds = null;
                try
                {
                    SqlCommand cm = new SqlCommand("p_GetAllPetStarters", connection);
                    cm.CommandType = CommandType.StoredProcedure;
                    da = new SqlDataAdapter(cm);
                    ds = new DataSet();
                    connection.Open();
                    da.Fill(ds);
                    connection.Close();
                }
                catch (Exception ex)
                {
                    ds = null;
                }
                return ds;
            }
    this is where I'm stuck trying to load the listbox from the Contacts form. Eventually it's a ListView that needs this data but I figured it would be best and easiest to know what I'm doing after I am able to load a listbox.
    Code:
      private void frmContacts_Load(object sender, EventArgs e)
            {
                DataDB dbOjb = new DataDB();
                DataSet ds = dbOjb.GetAllPetStarters();
                lstBox1 //needs data from ds somehow
                
            }
    Last edited by viperbyte; August 2nd, 2012 at 03:12 PM.

  2. #2
    Join Date
    Jan 2010
    Posts
    1,133

    Re: How do I Load a Listbox with a returned dataset?

    See this: How to: Bind a Windows Forms ComboBox or ListBox Control to Data.
    Code:
    lstBox1.DataSource = ds.Tables[table_name_or_index];
    lstBox1.DisplayMember = "column_name";

  3. #3
    Join Date
    Dec 2009
    Posts
    596

    Re: How do I Load a Listbox with a returned dataset?

    Thanks but apparently this binding style solution will only be good for one column of data. The stored procedure is returning firstname, lastname, email, state and zip. I need all the values and I need to be able to load this into a ListView after I am able to get this to work with the listbox. The binding won't work with a ListView...I don't think. What if I changed the reuturn type to something other than dataset? Would that help you guys be able to offer a suggestion as a way for me to be able to loop and load listboxes and listviews?

  4. #4
    Join Date
    Jan 2010
    Posts
    1,133

    Re: How do I Load a Listbox with a returned dataset?

    I see. Well, in the list box case, you first need to decide on the format you want to use to display your data, since ListBox is not a table-like control. In the attachment below, I simply used a string to represent each row in a table, in the format "col1 | col2 | col3 | ... | colN".

    Theoretically, the code snippet in my previous post can be used to bind to entire rows, since the DisplayMember property, if what is specified is not a table column, will try to bind to a correspondingly named property of the data source object. Something like this:
    Code:
    lstBox1.DataSource = ds.Tables["MyTable"];
    lstBox1.DisplayMember = "Rows";
    However, ListBox doesn't "know" how to handle this, so it will simply call ToString() on each DataRow object, which will return generic fully qualified type name, and not the data itself.

    Internally, controls maintain BindingManagerBase-derived class instances, which actually handle the details of the binding. There are two derived classes: one is called PropertyManager, which is used for simple, one_property-to-one_property bindings; the other is called CurrencyManager and is used for more complicated bindings involving lists and tables - and this is what you need.

    The binding model of windows forms is somewhat convoluted, but using CurrencyManager a custom binding logic can be created in a relatively simple way. A note: CurrencyManager uses the terms "list" and "item" to denote the data source, and the current item, respectively (thus "currency" manager). For list-like structures this is straightforward, but for tables, the term "list" denotes the table, and "item" a table row.

    Now, the CurrencyManager class defines two events of importance: ListChanged - fired when the list/table is replaced, and ItemChanged - fired when the list item / table row is somehow changed.

    EDIT: Been reading MSDN docs - turns out that ListChanged is fired when the individual items are edited as well, and that you can use the e.ListChangedType property to find out what kind of a change it was (docs). I re-attached the modified code taking advantage of this.

    What I did in the test code I attached was: I created a small helper class (one for the ListBox, one for the ListView) which I use to obtain the currency manager, and then handle these events in a way that's appropriate for the associated control.

    Code:
            private void Bind()
            {
                if (ListView != null && Table != null)
                {
                    CurrencyManager cm = (CurrencyManager)ListView.BindingContext[Table];
    
                    if (_rebind)
                    {
                        cm.ListChanged += OnListChanged;
                        cm.ItemChanged += OnItemChanged;
                    }
    
                    SetListViewItems();
                    _rebind = false;
                }
            }
    A note about this code: The BindingContext property of the ListView object returns a BindingManagerBase associated with the data source specified inside the [], or creates one if it doesn't already exist. Also, it appears that the BindingContext is not control-specific, but shared, so I maintain the _rebind flag, which I set when I change the ListBox/ListView, or the Table (I alsocall Bind() at that time). OnListChanged simply calls SetListBoxItems() / SetListViewItems(). OnItemChanged uses control-specific properties to update the data row.

    You can also take a look at this tutorial I found at codeproject.com, but I find it to be a bit hackish, relying on the Tag property.

    A final note about the attachment: The UI presents you with a list box, and a list view, and generates a random table, binding each control to it. At the bottom there are two buttons: "Change Item" will randomly change a column in a random row (replacing it with a string starting with "N", standing for "New", so that you can see it); "Change Table" will generate a new, random table, and cause the controls to rebind.
    Code:
            private void BtnChangeTable_Click(object sender, EventArgs e)
            {
                DataTable table = GetRandomTable();
    
                _listBoxBinder.Table = table;
                _listViewBinder.Table = table;
    
                // ...
            }
    The important code is in the ListBoxBinder and ListViewBinder classes - the helper classes I was talking about. The intent is that these are specifically designed to help bind the corresponding controls to a DataTable, and so don't provide support for other kinds of data sources.

    P.S. Note that you can extend the functionality of the Binder classes to provide means to access the currently selected row, if you want to make edits and such.
    Also, ListView is a little awkward when working with tables, since it uses item-subitems model to display columns; like in Windows Explorer - the file is the main Item, and file properties are it's subitems. Have you considered using a DataGridView instead? Unless there is a specific purpose for using a list view?
    Attached Files Attached Files
    Last edited by TheGreatCthulhu; August 3rd, 2012 at 09:26 PM.

  5. #5
    Join Date
    Jul 2012
    Posts
    90

    Re: How do I Load a Listbox with a returned dataset?

    Although the above data binding technique will work well. To present an alternative method...

    You can also programmatically load the data into the Listbox as follows:

    Code:
                DataDB dbObj = new DataDB();
                DataSet ds = dbObj.GetAllPetStarters();
                DataTable table = ds.Tables["table_name_or_index"];
                foreach (DataRow row in table.Rows)
                {
                    StringBuilder sb = new StringBuilder();
                    foreach (object item in row.ItemArray)
                    {
                        if (item.GetType().ToString() != "System.String")
                        {
                            sb.Append(item.ToString());
                        }
                        else
                        {
                            sb.Append(item);
                        }
                        sb.Append(" | ");
                    }
                    lstBox1.Items.Add(sb.ToString().Remove(sb.ToString().Length - 3));
                }
    Personnaly I prefer to use a DataReader for this, but if what you have is a DataSet this will work.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured