Only one item appearing on Listview - c#

I need to make a list of products with their respective icons above but it only appears one item. There are 20 products total. How can I insert the other 19 items?
Code:
ImageList imageList = new ImageList();
prodview.LargeImageList = imageList;
while (i < 20)
{
var json = c.DownloadString(url + (i + 1).ToString());
var image = c.DownloadData(urlicon + (i + 1).ToString());
var dataDict = JsonConvert.DeserializeObject<List<Data>>(json);
ListViewItem item = new ListViewItem();
foreach (var data in dataDict)
item.Text = data.name;
imageList.ImageSize = new Size(100, 100);
imageList.Images.Add(i.ToString(), new Bitmap(new MemoryStream(image)));
item.ImageIndex = i;
prodview.Items.Add(item);
i++;
}
This version of the code already works. Answer below.

Your logic has issues
for i = 0 to 19 ..
download data/string create new list item create new image list
foreach item in datadict set item.text
add 1 image to imagelist
for all items currently in image list (aka 1) add it to prodview
rpt.
so you only end up with 1 item, as you remade item list each time, and each variable each time.
you almost certainly want something like:
ImageList imageList = new ImageList();
to be before the while loop. The below doesnt need to be in a loop either - otherwise its repeating.
prodview.LargeImageList = imageList;
item.ImageIndex = i;
prodview.Items.Add(item);
There maybe other issues - such as im not convinced about the images but.. start there
Adjusting my code some..
Your code probably should end up like
ImageList imageList = new ImageList();
prodview.LargeImageList = imageList;
while(i <20)
{
var json = c.DownloadString(url + (i + 1).ToString());
var image = c.DownloadData(urlicon + (i + 1).ToString());
var dataDict = JsonConvert.DeserializeObject<List<Data>>(json);
ListViewItem item = new ListViewItem();
// not sure what you were trying to do here as it would always end up with the last name..
// foreach (var data in dataDict)
// item.Text = data.name;
item.Text = "item "+i; // giving it a name
imageList.ImageSize = new Size(100, 100);
imageList.Images.Add(i.ToString(), new Bitmap(new MemoryStream(image)));
item.ImageIndex = i;
prodview.Items.Add(item);
i++;
}

Related

Dynamic Listview with multiple items

So, i have been working in a school project and i need to create and add things to a listview dynamically the 1st adds without any problem, but when it's about to add the 2nd one it crashes.
here is the code:
lvwCarros.Columns.Clear();
ListViewItem lvi = new ListViewItem();
int idx, idx2;
lvwCarros.Columns.Add("Carro", 80, HorizontalAlignment.Center);
lvwCarros.Columns.Add("Ano", 60, HorizontalAlignment.Center);
lvwCarros.Columns.Add("Stand", 60, HorizontalAlignment.Center);
lvwCarros.Columns.Add("Localização do Stand", 120, HorizontalAlignment.Center);
for (idx = 0; idx < Program.Carros.Count ; idx++)
{
lvi.Text = Program.Carros[idx].Marca + " " + Program.Carros[idx].Modelo;
for (idx2 = 0; idx2 < Program.Matriculas.Count ; idx2++)
{
if (Program.Carros[idx].Matricula == Program.Matriculas[idx2].ID_Matricula)
{
lvi.SubItems.Add(Program.Matriculas[idx2].Ano_Emissão.ToString());
for (int idx3 = 0; idx3 < Program.Stands.Count; idx3++)
{
if (Program.Carros[idx].Proprietario == Program.Stands[idx3].ID_Stand)
{
lvi.SubItems.Add(Program.Stands[idx3].Nome_Stand);
lvi.SubItems.Add(Program.Stands[idx3].Local_Stand);
}
lvwCarros.Items.Add(lvi);
}
}
}
}
lvwCarros.Visible = true;
lvwCarros.Enabled = true;
Thank you very much in advance :)
Essentially your problem is that your lvi needs to be a new object every time you call lvwCarros.Items.Add(). Try putting an "lvi = new ListViewItem(first subitem);" in there at the top of that innermost for loop. You can only add each ListViewItem object to the ListView once--this is why you're getting your exception.
Here is the running code. There were two problems in this code:
Each List item to be added should be instantiated in the for loop as it will create a new item. Otherwise, you will be adding the same item again and again and modifying the value of all the items if one item is changed as they will point to same item. Hence move the line ListViewItem lvi = new ListViewItem(); in the for loop if you want to create different list view items.
You are adding the listview item lvi in the internal for loop which is causing it to add the each listitem multiple time. Thats why you are getting the error. Move this line in the outermost for loop and the error will go away.
lvwCarros.Columns.Clear();
int idx, idx2;
lvwCarros.Columns.Add("Carro", 80, HorizontalAlignment.Center);
lvwCarros.Columns.Add("Ano", 60, HorizontalAlignment.Center);
lvwCarros.Columns.Add("Stand", 60, HorizontalAlignment.Center);
lvwCarros.Columns.Add("Localização do Stand", 120, HorizontalAlignment.Center);
for (idx = 0; idx < Program.Carros.Count ; idx++)
{
/* You should initiate a new item in the loop if you want to add more*/
ListViewItem lvi = new ListViewItem();
lvi.Text = Program.Carros[idx].Marca + " " + Program.Carros[idx].Modelo;
for (idx2 = 0; idx2 < Program.Matriculas.Count ; idx2++)
{
if (Program.Carros[idx].Matricula == Program.Matriculas[idx2].ID_Matricula)
{
lvi.SubItems.Add(Program.Matriculas[idx2].Ano_Emissão.ToString());
for (int idx3 = 0; idx3 < Program.Stands.Count; idx3++)
{
if (Program.Carros[idx].Proprietario == Program.Stands[idx3].ID_Stand)
{
lvi.SubItems.Add(Program.Stands[idx3].Nome_Stand);
lvi.SubItems.Add(Program.Stands[idx3].Local_Stand);
}
}
}
}
/*Moving it to outermost for loop*/
lvwCarros.Items.Add(lvi);
}
lvwCarros.Visible = true;
lvwCarros.Enabled = true;

listview thumbnails repeating c#

I'm trying to populate a listview box with thumbnails you can select to bring up a preview.
The listview populates with the correct amount of images, tagged with the correct filepath, but the thumbnail for each is a repetition of the first indexed image in the linked imagelist. (see attached code)
private void PopulateList()
{
DirectoryInfo dir = new DirectoryInfo(#"C:\Temp\Snapshots");
this.listImages.View = View.LargeIcon;
this.imageList1.ImageSize = new Size(140, 100);
this.listImages.LargeImageList = this.imageList1;
int j = 0;
foreach (FileInfo file in dir.GetFiles())
{
try
{
ListViewItem item = new ListViewItem();
item.ImageIndex = j;
item.Tag = file.FullName;
this.imageList1.Images.Add(Image.FromFile(file.FullName));
this.listImages.Items.Add(item);
j = j++;
//fixed by changing above line to
//j = (j+1);
}
catch
{
}
}
}
Any assistance would be greatly appreciated, I feel like I'm missing something really simple...
Thanks.
EDIT: Fix in code as comment

accessing dynamically created controls C#

I have been reading for a bit and found some things close, but not anything works in my case. The user has a settings file that they use and I read it into the Windows form. One tab has 2 standard columns but then there can be any number more after those two which have different labels and listbox names that are based on the label (i.e. if the label is "portland" the corresponding listbox is "lstportland" but these names WILL vary). There are created in the is part of the settings file import method, on the fly:
for (int i = 3; i < (lastColumn); i++)
{
//creates new list box and names it the column name with a "lst" infront of it
var cellVal = squidSheet.Cells[1, i].Value;
string convertString = cellVal.ToString();
string listBoxName = "lst" + convertString;
int lbLocation = new int();
/*where to place the next label/listbox on the sheet based on a placement point if its the first one
*it is placed in a specific spot, then each subsequent one is placed equidistant from the last.*/
if (i==3)
{ lbLocation = 382; }
else
{ lbLocation = 382 + (115*(i-3)); }
//create the properties for the new listbox and label in its proper place on the "Run Tab"
ListBox listBox1 = new ListBox();
Label label1 = new Label();
listBox1.Name = listBoxName;
listBox1.Height = 316;
listBox1.Width = 94;
listBox1.Location = new Point(lbLocation, 30);
label1.Location = new Point(lbLocation, 14);
label1.Text = convertString;
label1.Name = "lbl" + convertString;
label1.Font = new Font("Microsoft Sans Serif", 8, FontStyle.Regular);
//add the new listbox and label to the Form
tabPage4.Controls.Add(listBox1);
tabPage4.Controls.Add(label1);
//fill the new list box
string colIdString = TestCase((i-1).ToString());
fillListBox(listBox1, lastRowRunList, squidSheet, colIdString);
}
In a Later method, I need to read the items of each listbox created on the fly, into its own array or somehow access the items in the listbox itself. I have sketched the following but it doesn't work. Any ideas?
for (int l = 2; l < (listBoxNames.Count); l++)
{
string variableNameString = labelText[l].ToString();
string variableNames = "#" + variableNameString + "#";
ListBox listboxTest = Controls[("lst" + variableNameString)] as ListBox;
string variableValues = listboxTest.Items[(l-1)].ToString();
readText = readText.Replace(variableNames, variableValues);
}
The control isn't being found because you are searching the Form's Controls() collection, instead of its actual container, tabPage4.
Change:
ListBox listboxTest = Controls[("lst" + variableNameString)] as ListBox;
To:
ListBox listboxTest = tabPage4.Controls[("lst" + variableNameString)] as ListBox;
Or search for the control as in the link provided by drzounds in the comments.

Remove a checkbox that is being created dynamically in a loop

I have a bunch of code that dynamicly creates some controls. It looks in a folder and lists the filenames in it. For each file in the folder it creates a checklistbox item, listbox item and two checkboxes. This is working great and as intended:
private void getAllFiles(string type)
{
try
{
string listPath = "not_defined";
if (type == "internal_mod")
{
int first_line = 76;
int next_line = 0;
int i = 0;
CheckBox[] chkMod = new CheckBox[100];
CheckBox[] chkTool = new CheckBox[100];
listPath = this.internalModsPath.Text;
string[] filesToList = System.IO.Directory.GetFiles(listPath);
foreach (string file in filesToList)
{
if (!internalModsChkList.Items.Contains(file))
{
internalModsChkList.Items.Add(file, false);
string fileName = Path.GetFileName(file);
internalModNameList.Items.Add(fileName);
//-----------------
// Draw Checkboxes
//-----------------
chkMod[i] = new CheckBox(); chkTool[i] = new CheckBox();
chkMod[i].Name = "modChk" + i.ToString(); chkTool[i].Name = "modChk" + i.ToString();
//chkMod[i].TabIndex = i; //chkTool[i].TabIndex = i;
chkMod[i].Anchor = (AnchorStyles.Left | AnchorStyles.Top); chkTool[i].Anchor = (AnchorStyles.Left | AnchorStyles.Top);
chkMod[i].Checked = true; chkTool[i].Checked = false;
chkMod[i].AutoCheck = true; chkTool[i].AutoCheck = true;
chkMod[i].Bounds = new Rectangle(549, first_line + next_line, 15, 15); chkTool[i].Bounds = new Rectangle(606, first_line + next_line, 15, 15);
groupBox7.Controls.Add(chkMod[i]); groupBox7.Controls.Add(chkTool[i]);
//-----------------
next_line += 15;
i++;
}
}
}
Now my problem is that I also want the user to be able to delete all these thing again based on the checklistbox' checked items.. I have no problems deleting the items in the checklistbox or the items in the listbox, but I want to remove the two checkboxes I create too ..
This is what I got to remove the items in the checklistbox, and the listbox
private void internalModListDel_btn_Click(object sender, EventArgs e)
{
int count = internalModsChkList.Items.Count;
for (int index = count; index > 0; index--)
{
if (internalModsChkList.CheckedItems.Contains(internalModsChkList.Items[index - 1]))
{
internalModsChkList.Items.RemoveAt(index - 1);
internalModNameList.Items.RemoveAt(index - 1);
groupBox7.Controls.Remove(modChk[index - 1]);
}
}
}
As you can see I have also tried to write something to remove the checkbox but it doesn't work and I have no idea how to make it work
Can you assist ?
Try using UserControls.
Use the ListBox controller to show those UserControls,
The user control can be built with those checkboxes, and the labels you want .
Another suggestion is to bind this list to an ObservableCollection which will contain the UserContorols you have created.
This way, it will be much more simlpe to add/remove/change the items inside.

GetEnumerator problem in c#

i got this GetEnumerator problem.. here's my situation
Panel eachPanel = new Panel();
eachPanel.Size = new Size(pnlProcessCon.Width - 27, 24);
eachPanel.Location = new Point(5, startPoint);
eachPanel.BackColor = (defaultColor == alterColor[0]) ? alterColor[1] : alterColor[0];
TextBox txtProcess = new TextBox();
txtProcess.Size = new Size(50, 20);
txtProcess.Location = new Point(2,2);
txtProcess.TextAlign = HorizontalAlignment.Center;
txtProcess.Text = "P" + Convert.ToString(startProcess);
TextBox txtBurstTime = new TextBox();
txtBurstTime.Size = new Size(50, 20);
txtBurstTime.Location = new Point(txtProcess.Right + 70, 2);
txtBurstTime.TextAlign = HorizontalAlignment.Center;
TextBox txtPriority = new TextBox();
txtPriority.Size = new Size(50, 20);
txtPriority.Location = new Point(txtBurstTime.Right + 70, 2);
txtPriority.TextAlign = HorizontalAlignment.Center;
eachPanel.Controls.Add(txtProcess);
eachPanel.Controls.Add(txtBurstTime);
eachPanel.Controls.Add(txtPriority);
pnlProcessCon.Controls.Add(eachPanel);
but when i call each of their text and add to dictionary, i got this error..
Error 1 foreach statement cannot operate on variables of type 'System.Windows.Forms.Panel' because 'System.Windows.Forms.Panel' does not contain a public definition for 'GetEnumerator' C:\Users\vrynxzent#yahoo.com\Documents\Visual Studio 2008\Projects\Scheduler\Scheduler\Form1.cs 68 13 Scheduler
and got my error here..
foreach (var each in pnlProcessCon)
{
String[] temp = new String[3];
foreach (var process in each)
{
temp = process.Text;
}
}
There are a few issues there.
First, you should enumerate the Controls collections. Second, you will have to cast each control to TextBox before you can retrieve the text. Third, you declared temp as an array, so you can't directly assign a string to it. Fourth (as Henk Holterman pointed out), you should use actual types and not var in the foreach loops.
I'm going to take a stab at working code here. Feel free to adjust for your own needs.
TextBox txtProcess = new TextBox();
txtProcess.Name = "Process";
//configure other textboxes, add to panels, etc.
foreach (Panel each in pnlProcessCon.Controls)
{
String[] temp = new String[3];
foreach (Control control in each.Controls)
{
if(control.Name == "Process")
{
temp[0] = ((TextBox)control).Text;
}
}
}
This would be the general idea (note: no var)
foreach (Panel p in pnlProcessCon.Controls)
{
foreach (Control process in p.Controls)
{
}
}
But make sure pnlProcessCon only contains Panels.

Categories

Resources