How to select multiple items from the list box, and display these in a DataTable?
-
2012年8月21日 下午 10:44
Hey everyone! I’m trying to learn C# better. I know some things, but obviously not enough, because I just got stuck on a new project. Basically, I am trying to load data into a ListBox (works fine). Then, I want to be able to select multiple items from the list box, and display these in a DataTable (not working fine). Below is my code. I think I am close, but I can’t seem to get this working for some reason.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
DataSet ds = new DataSet();
SqlDataAdapter daOrders = new SqlDataAdapter();
SqlDataAdapter daOrder_Details = new SqlDataAdapter();
SqlConnection cs = new SqlConnection("Data Source=EXCEL-PC;Initial Catalog=NORTHWIND.MDF;Integrated Security=True");
SqlDataAdapter da = new SqlDataAdapter("Select Distinct CompanyName From Customers Order By CompanyName", cs);
DataTable dt = new DataTable();
da.Fill(dt);
for (int i = 0; i < listBox1.SelectedItems.Count; i++)
{
string item = listBox1.SelectedItems[i].ToString();
ds.Tables["Customers"].DefaultView.RowFilter = "CustomerID = " + listBox1.SelectedItems[i];
dataGridView1.DataSource = ds.Tables["Customers"];
}
}
private void Form1_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the '_NORTHWIND_MDFDataSet.Customers' table. You can move, or remove it, as needed.
this.customersTableAdapter.Fill(this._NORTHWIND_MDFDataSet.Customers);
SqlConnection cs = new SqlConnection("Data Source=EXCEL-PC;Initial Catalog=NORTHWIND.MDF;Integrated Security=True");
SqlDataAdapter da = new SqlDataAdapter("Select Distinct CompanyName From Customers Order By CompanyName", cs);
DataTable dt = new DataTable();
da.Fill(dt);
for (int i = 0; i < dt.Rows.Count; i++)
{
listBox1.Items.Add(dt.Rows[i]["CompanyName"]);
}
}
}
}
Ryan Shuell
- 已編輯 ryguy72 2012年8月21日 下午 10:47
所有回覆
-
2012年8月22日 上午 03:41
Hi ryguy72<abbr class="affil"></abbr>,
You are adding CompanyName to the ListBox, while attempting to read the CompanyID in the button click.
If you are using the same table for both ListBox & DataGridView - you can use the same table - just store it in a Form variable - you do not have to re-load it every time you click a button.
It might be preferable to DataBind the ListBox, similar to the following:
listBox1.DataSource = dt; listBox1.DisplayMember = "CompanyName"; listBox1.ValueMember = "CompanyID"; listBox1.DataBind();
And then on the button click you can construct the filter similar to the following:
var ids = new List<int>(); foreach (var item in listBox1.SelectedItems) ids.Add((int)item.Value); // now set the filter // - below is .Net 4 syntax, let me know if you need prior version
string filter = (ids.Count != 0) ? "CustomerID in (" + string.Join(",", ids) + ")" : "CustomerID=CustomerID+1"; // the second condition is always false var view = new DataView(dt); view.RowFilter = filter; dataGridView1.DataSource = view;
- 已編輯 Sergey Poberezovskiy 2012年8月22日 上午 03:42
- 已標示為解答 ryguy72 2012年8月28日 下午 02:06
-
2012年8月22日 上午 04:15
Thanks, Sergey. I implemented your suggestion. Maybe I missed something, but I couldn't get that working. This is what I have now:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
DataSet ds = new DataSet();
SqlDataAdapter daOrders = new SqlDataAdapter();
SqlDataAdapter daOrder_Details = new SqlDataAdapter();
SqlConnection cs = new SqlConnection("Data Source=EXCEL-PC;Initial Catalog=NORTHWIND.MDF;Integrated Security=True");
SqlDataAdapter da = new SqlDataAdapter("Select Distinct CompanyName From Customers Order By CompanyName", cs);
listBox1.DataSource = da;
listBox1.DisplayMember = "CompanyName";
listBox1.ValueMember = "CompanyID";
//listBox1.DataBind();
DataTable dt = new DataTable();
da.Fill(dt);
var ids = new List<int>();
for (int i = 0; i < listBox1.SelectedItems.Count; i++)
ids.Add((int)items.Value);
// now set the filter
string filter = (ids.Count != 0) ? "CustomerID in (" + string.Join(",", ids) + ")" : "CustomerID=CustomerID+1"; // the second condition is always false
var view = new DataView(dt);
view.RowFilter = filter;
dataGridView1.DataSource = view;
//for (int i = 0; i < listBox1.SelectedItems.Count; i++)
//{
// string item = listBox1.SelectedItems[i].ToString();
// ds.Tables["Customers"].DefaultView.RowFilter = "CustomerID = " + listBox1.SelectedItems[i];
// dataGridView1.DataSource = ds.Tables["Customers"];
//}
}
private void Form1_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the '_NORTHWIND_MDFDataSet.Customers' table. You can move, or remove it, as needed.
this.customersTableAdapter.Fill(this._NORTHWIND_MDFDataSet.Customers);
SqlConnection cs = new SqlConnection("Data Source=EXCEL-PC;Initial Catalog=NORTHWIND.MDF;Integrated Security=True");
SqlDataAdapter da = new SqlDataAdapter("Select Distinct CompanyName From Customers Order By CompanyName", cs);
DataTable dt = new DataTable();
da.Fill(dt);
for (int i = 0; i < dt.Rows.Count; i++)
{
listBox1.Items.Add(dt.Rows[i]["CompanyName"]);
}
}
}
}
On this line:
ids.Add((int)items.Value);
There is a red squiggle line under items.
Message is: 'The name 'items' does not exist in the current context'
Now, I get this massive error that looks like this:
Any thoughts on what to do for the next step, or next steps???
Thanks!!
Ryan Shuell
- 已提議為解答 Tobias Ehling 2012年8月22日 下午 02:27
- 已取消提議為解答 Tobias Ehling 2012年8月23日 下午 07:45
- 已標示為解答 ryguy72 2012年8月28日 下午 02:06
-
2012年8月22日 上午 07:06
should be item.Value - my bad- 已提議為解答 Tobias Ehling 2012年8月22日 下午 02:27
- 已取消提議為解答 Tobias Ehling 2012年8月23日 下午 07:45
- 已標示為解答 ryguy72 2012年8月28日 下午 02:06
-
2012年8月22日 下午 02:13
Dear RyGuy72,
Sergeys reply should solve your problem completely.
you wrote that you are learning c# atm . If I may make an additional suggestion regarding your further studies:
While stepping into more complex subjects you should try to apply some kind of "Separation of Concerns" (SOC) to your projects. Maybe you noticed that this relatively simple piece of "DataBinding and UserInteraction" produces an decent amount of code. Although its not fully applicable to "WinForm Applications" you may have a look at some kind of "Model-View-Controller"- / "Model-View-Presenter"- Patterns. It would increase modularity, readability and sustainability of your projects significally. I have to admit that this way of developing applications does not reduce the amount of code initially, so it depends on your project wether its useful or not.
Have a nice day,
Tobias Ehling
- 已編輯 Tobias Ehling 2012年8月22日 下午 02:25
- 已標示為解答 ryguy72 2012年8月28日 下午 02:07
-
2012年8月22日 下午 11:00
Sorry for being so thick here, guys, but it is still not working. I tried Sergey's code sample; couldn't get it running. I did some research on the web, modified the code a bit, and came up with this:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
DataSet ds = new DataSet();
SqlDataAdapter daOrders = new SqlDataAdapter();
SqlDataAdapter daOrder_Details = new SqlDataAdapter();
SqlConnection cs = new SqlConnection("Data Source=EXCEL-PC;Initial Catalog=NORTHWIND.MDF;Integrated Security=True");
SqlDataAdapter da = new SqlDataAdapter("Select Distinct CompanyName From Customers Order By CompanyName", cs);
DataTable dt = new DataTable();
da.Fill(dt);
string text = "";
foreach (var item in listBox1.SelectedItems)
{
text += item.ToString() + " ";
}
dataGridView1.DataSource = text;
}
private void Form1_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the '_NORTHWIND_MDFDataSet.Customers' table. You can move, or remove it, as needed.
this.customersTableAdapter.Fill(this._NORTHWIND_MDFDataSet.Customers);
SqlConnection cs = new SqlConnection("Data Source=EXCEL-PC;Initial Catalog=NORTHWIND.MDF;Integrated Security=True");
SqlDataAdapter da = new SqlDataAdapter("Select Distinct CompanyName From Customers Order By CompanyName", cs);
DataTable dt = new DataTable();
da.Fill(dt);
listBox1.DataSource = dt;
listBox1.DisplayMember = "CompanyName";
listBox1.ValueMember = "CompanyID";
//listBox1.DataBind();
for (int i = 0; i < dt.Rows.Count; i++)
{
listBox1.Items.Add(dt.Rows[i]["CompanyName"]);
}
}
}
}This looks ok to me, but when I click the button, nothing is displayed in the DateGridView1.
I don't get any errors, but I can tell that there is a problem with this line:
foreach (var item in listBox1.SelectedItems)
A couple things are very bizarre. For one thing, the 'listBox1.SelectedItems' doesn't loop at all; it always shows only the FIRST selected item. It's like the foreach loop doesn't loop. Also, the Immediate Window doesn't let me find the value of this, or any variable. I can see the value of the 'listBox1.SelectedItems' only by hovering my mouse over the variable. I've been programming VBA for about 10 years. I'll say for sure, the Immediate Window is INVALUABLE. In VBA, it always shows the values of whatever variables you select. In C#, if the Immediate Window does not allow the user to see values of variables, and it is completely frozen, it is completely useless!!
Ryan Shuell
- 已編輯 ryguy72 2012年8月22日 下午 11:03
-
2012年8月23日 上午 12:50
Shift + F9, when debugging will help you to see what you need.
And about your problem that your gridview doesnt show anything, probably this is happening because you are passing a string as a DataSource.Web Developer
-
2012年8月23日 上午 02:24
Thanks! That Shift + F9 is a neat trick. I'll remember that one for sure.
Now, the Immediate Window is working like it should.
I'm seeing this in the Immediate Window:
?listBox1.SelectedItems
{System.Windows.Forms.ListBox.SelectedObjectCollection}
Count: 2
IsReadOnly: true?item.ToString()
"System.Data.DataRowView"The Count is correct. I don't really care about the ReadOnly thing. I think, instead of "System.Data.DataRowView" being passed to the DataGridView, the two items that I selected should be passed to the dataGridView1.DataSource. Right now, what is being passed is this: ""
Ryan Shuell
-
2012年8月23日 上午 05:37
Could you try:
public partial class Form1 : Form
{private DataTable _table; private void button1_Click(object sender, EventArgs e) { var ids = new List<int>(); for (int i = 0; i < listBox1.SelectedItems.Count; i++) ids.Add((int)item.Value); // now set the filter string filter = (ids.Count != 0) ? "CustomerID in (" + string.Join(",", ids) + ")" : "CustomerID=CustomerID+1"; var view = new DataView(_table); view.RowFilter = filter; dataGridView1.DataSource = view; } private void Form1_Load(object sender, EventArgs e) { SqlConnection cs = new SqlConnection("Data Source=EXCEL-PC;Initial Catalog=NORTHWIND.MDF;Integrated Security=True"); SqlDataAdapter da = new SqlDataAdapter("Select Distinct CompanyName From Customers Order By CompanyName", cs); _table = new DataTable(); da.Fill(_table); listBox1.DataSource = _table; listBox1.DisplayMember = "CompanyName"; listBox1.ValueMember = "CompanyID"; } }
- 已標示為解答 ryguy72 2012年8月28日 下午 02:07
-
2012年8月23日 下午 12:04
No, now I'm back to the 'Item does not exist in the current context' error message
ids.Add((int)item.Value); // now set the filter
It doesn't exist, I get it. Ok. C# should really give you tools to help you debug these problems. In VBA, I'd have this running in 5 minutes or less. Now, I'm in the C# world, and I've spent a couple days on this, and it still doesn't work! LOL!!
It doesn't matter whether I change the 'SelectedItems' to 'SelectedItem'
for (int i = 0; i < listBox1.SelectedItems.Count; i++)
It still doesn't work.
If I leave the 'SelectedItems' and change the 'item' to 'items'
ids.Add((int)items.Value);
IT STILL DOESN'T WORK!!
I wish C# had some decent debugging tools!!
Now, I'm just seeing this message:
I get that all the time, for all kinds of projects. Build > Build Solution should take care of that, but of course it doesn't.
Ryan Shuell
-
2012年8月23日 下午 01:27
Hi Ryan,
change your code like this:
public partial class Form1 : Form{ private DataTable _table; private void button1_Click(object sender, EventArgs e) { var ids = new List<int>(); for (int i = 0; i < listBox1.SelectedItems.Count; i++) ids.Add((int)listBox1.SelectedItems[i].Value); // now set the filter string filter = (ids.Count != 0) ? "CustomerID in (" + string.Join(",", ids) + ")" : "CustomerID=CustomerID+1"; var view = new DataView(_table); view.RowFilter = filter; dataGridView1.DataSource = view; } private void Form1_Load(object sender, EventArgs e) { SqlConnection cs = new SqlConnection("Data Source=EXCEL-PC;Initial Catalog=NORTHWIND.MDF;Integrated Security=True"); SqlDataAdapter da = new SqlDataAdapter("Select Distinct CompanyName From Customers Order By CompanyName", cs); _table = new DataTable(); da.Fill(_table); listBox1.DataSource = _table; listBox1.DisplayMember = "CompanyName"; listBox1.ValueMember = "CompanyID"; } }greetings,
Tobi
- 已標示為解答 ryguy72 2012年8月28日 下午 02:07
-
2012年8月23日 下午 07:21
Thanks dude! As soon as I get out of the office, I'll go over to the library, fire up my laptop, and try your code sample. I don't have VS on my office computer.
This must have something to do with variable scopes. That's all I can think of. I'll post back soon.
Thanks again!!
Ryan Shuell
-
2012年8月23日 下午 09:41
Just tried this code. This is the message that I get now:
'object' does not contain a definition for 'Value' and no extension method 'Value' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)
I guess it has something to do with the CustomerID being passed to the DataGridView, instead of the CustomerName. That should be fine, I think, and even preferable, over passing a CustomerName, because different customers can certainly have the same name. I still don't know how to resolve this.
I found this, which seems to be helpful:
http://www.codeproject.com/Questions/118912/listbox-multiple-selected-values
I'm not sure how to convert that to my project though.
Ryan Shuell
-
2012年8月23日 下午 10:14
Hi Ryan,
it was my fault. Not its because listbox1.selecteditems[i] returns an object. Youre query returns just CompanyName, so well take it as it is in the following code, but you should also return the CompanyID.
public partial class Form1 : Form{ private DataTable _table; private void button1_Click(object sender, EventArgs e) { var names = new List<string>(); for (int i = 0; i < listBox1.SelectedItems.Count; i++) names.Add(listBox1.SelectedItems[i].ToString()); // now set the filter string filter = (names.Count != 0) ? "CustomerName in (" + string.Join(",",names) + ")" : "0=1"; var view = new DataView(_table); view.RowFilter = filter; dataGridView1.DataSource = view; } private void Form1_Load(object sender, EventArgs e) { SqlConnection cs = new SqlConnection("Data Source=EXCEL-PC;Initial Catalog=NORTHWIND.MDF;Integrated Security=True"); SqlDataAdapter da = new SqlDataAdapter("Select Distinct CompanyName From Customers Order By CompanyName", cs); _table = new DataTable(); da.Fill(_table); listBox1.DataSource = _table; listBox1.DisplayMember = "CompanyName"; listBox1.ValueMember = "CompanyName"; } }
- 已編輯 Tobias Ehling 2012年8月23日 下午 10:16
- 已標示為解答 ryguy72 2012年8月28日 下午 02:07
-
2012年8月24日 上午 01:21
Thanks for sticking through this, man. I really appreciate it. Now, the error is gone. However, I have a new problem now. I'm posting this question, because I've encountered this before, and I never figured it out. Can you walk me through this last issue.
Basically, I have a Form (the first image) that looks a certain way in 'View Designer' and it looks totally different when I hit F5 (the second image).
Ryan Shuell
-
2012年8月24日 上午 05:37
Hi Ryan,
youre welcome. Check if your program.cs looks like:
Check further if under "Project->Properties->Application" the field "startup object" (or something like that, using a localized version of Visual Studio) is set to "undefined".static class Program { /// <summary> /// Der Haupteinstiegspunkt für die Anwendung. /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } }
If youve got several projects in your Solution Explorer, make sure your current project is marked as
startup object as well(Solution Explorer-> RightClick your project -> define as startup project).
Tobi
- 已標示為解答 ryguy72 2012年8月28日 下午 02:07
-
2012年8月24日 下午 12:19
I tried all of these things. Still, I get the new small Form popping up, not the original Form, with all of my Objects. Maybe I'll just rebuild everything and pop your code in and try that. That will probably work. I don't know why I always have to copy code, rebuild projects from scratch, and paste the code into the new project. I doesn't make sense. I don't think most developers work this way. Nevertheless, that's the only thing that works for me.
Thanks for all the help with this. When I get to the library this afternoon, I'll rebuild everything from scratch, and feed back with the details of the outcome.
Ryan Shuell

