System.argumentoutofrangeexception while invoke Listviewitems using iterators - c#

I have an application which must contain the items in large quantities and continuously into listviews control:
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
deg_loadfile load = new deg_loadfile(loadfile);
load.BeginInvoke(new AsyncCallback(loadcallback),null);
}
void countfile() {
int listcount = listView1.Items.Count;
for (int x = 0; x < listcount; x++) {
listView1.BeginInvoke((MethodInvoker)delegate {
listView1.Items[x].SubItems[1].Text = "ok";
listView1.Items[x].SubItems[2].Text = "ok";
listView1.Items[x].SubItems[3].Text = "done";
},x);
}
}
void countcallback(IAsyncResult ae) {
MessageBox.Show("count finished");
}
delegate void deg_count();
void loadcallback(IAsyncResult ae) {
MessageBox.Show("finished");
}
delegate void deg_loadfile();
void loadfile() {
string file = File.ReadAllText("hughlist.txt");
string[] files = Regex.Split(file,"\n");
foreach (string str in files) {
listView1.BeginInvoke((MethodInvoker)delegate {
ListViewItem item = new ListViewItem(str);
item.SubItems.Add("");
item.SubItems.Add("");
item.SubItems.Add("");
listView1.Items.Add(item);
},str);
}
}
private void button2_Click(object sender, EventArgs e)
{
deg_count count = new deg_count(countfile);
count.BeginInvoke(new AsyncCallback(countcallback),null);
}
The code above throws system.argumentoutofrangeexception (please see image below)
link image: http://i.stack.imgur.com/WJ7sA.png
The iteration has exceeded the conditions that I have given, why did it happen (note:in my case, i must use "for" instead of "foreach" or other enumeration) ?
thx
UPDATE:
thx to #saruman for the answer (keyword is "access to modified closure"), i've updated the code as below
for (int x = 0; x < listcount; x++) {
var x1=x;
listView1.BeginInvoke((MethodInvoker)delegate
{
listView1.Items[x1].SubItems[1].Text = "ok";
listView1.Items[x1].SubItems[2].Text = "ok";
listView1.Items[x1].SubItems[3].Text = "done";
}, x1); }

Look up access to modified closure
Try this
var listcount = listView1.Items.Count;
for (var x = 0; x < listcount; x++)
{
var x1 = x;
listView1.BeginInvoke((MethodInvoker)delegate
{
listView1.Items[x1].SubItems[1].Text = "ok";
listView1.Items[x1].SubItems[2].Text = "ok";
listView1.Items[x1].SubItems[3].Text = "done";
});
}

Related

How can I select and Deselect all items by checkbox in dynamically added check _list_box in c#?

I wanted to do select/ deselect with one checkbox. I have tried to get the index of the selected item. I haven't been able to get this, so I tried to change the name of the box. Still no success.
foreach (var item in DATAsetname_INIlist)
{
checkedListBox2.Items.Add(item);
}
if (checkedListBox2.Items.Count != 0)
{
checkedListBox2.Items.Add("Select all");
}
private void checkedListBox2_SelectedIndexChanged(object sender, EventArgs e)
{
if (checkedListBox2.Items.Count != 0)
{
if (checkedListBox2.SelectedItem.ToString() == "Select all")
{
for (int i = 0; i < checkedListBox2.Items.Count; i++)
{
checkedListBox2.SetItemChecked(i, true);
}
string changed = "Deselect all";
checkedListBox2.SelectedItem =changed;
}
if (checkedListBox2.SelectedItem.ToString() == "Deselect all")
{
for (int i = 0; i < checkedListBox2.Items.Count; i++)
{
checkedListBox2.SetItemChecked(i, false);
}
string changed = "Select all";
checkedListBox2.SelectedItem = changed;
}
}
}
can you please help on this ? thank you
Have done quick exercise. Please modify your code accordingly.
/// <summary>
/// Check all check boxes and vice versa
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ChkSelectAll_CheckedChanged(object sender, EventArgs e)
{
//Declare your checkedListBox2 count
iCount = checkedListBox2.Items.Count;
if (sender != null)
{
for (int i = 1; i <= iCount; i++)
{
CheckBox ck = null;
Control[] chkTest = this.Controls.Find("chkDrive" + i, true);
if (chkTest.Length > 0)
{
if (chkSelectAll.Checked)
{
for (int j = 0; j < chkTest.Length; j++)
{
ck = (CheckBox)chkTest[j];
ck.Checked = true;
}
}
else
{
for (int j = 0; j < chkTest.Length; j++)
{
ck = (CheckBox)chkTest[j];
ck.Checked = false;
}
}
}
}
}
}
can you try this.
try
{
checkedListBox1.SelectedIndexChanged -= checkedListBox1_SelectedIndexChanged;
if (checkedListBox1.Items.Count != 0)
{
if (checkedListBox1.SelectedItem.ToString() == "Select all")
{
for (int i = 0; i < checkedListBox1.Items.Count; i++)
{
checkedListBox1.SetItemChecked(i, true);
}
string changed = "Deselect all";
checkedListBox1.Items[checkedListBox1.SelectedIndex] = changed;
}
else if (checkedListBox1.SelectedItem.ToString() == "Deselect all")
{
for (int i = 0; i < checkedListBox1.Items.Count; i++)
{
checkedListBox1.SetItemChecked(i, false);
}
string changed = "Select all";
checkedListBox1.Items[checkedListBox1.SelectedIndex] = changed;
}
}
}
catch (Exception ex)
{
}
finally
{
checkedListBox1.SelectedIndexChanged += checkedListBox1_SelectedIndexChanged;
}
If this is C# based, windows application.
Search form collection and find all check box on form, using for each.
Code
foreach(CheckBox item in Form.Control)
{
Item.Checked=true;
}
For check list box
for(int i;I<checklistbox.items.count;I++)
{
checklistbox.SetItemChecked(I,true);
}
When i work with c# i had litle simillar problem in my case was enought was to replace if(string==string) by string.equals(string)
Btw few questions:
checkedListBox2.SelectedItem.ToString() what is value in here where comparing?
Does your listener work at all?
Not better way to check which checkBox is taken comparing sender in switch?
How u declare checkedListBox2
By checkedListBox2.Items.Add(item); i suspect u create checkBoxes by hand can u show it? meybe something is there wrong
This part added after Lian comment
foreach(var item in DATAsetname_INIlist)
{
checkedListBox2.Items.Add(item);
}
if (checkedListBox2.Items.Count != 0) {
checkedListBox2.Items.Add("Select all");
}
private void checkedListBox2_SelectedIndexChanged (object sender, EventArgs e)
{
if (checkedListBox2.Items.Count != 0 && checkedListBox2.SelectedItem.ToString().equals("Select all")) {
changeStateOfSelectedItem("Deselect all", true);
} else if (checkedListBox2.SelectedItem.ToString().equals("Deselect all")) {
changeStateOfSelectedItem("Select all", false);
}
}
private void changeStateOfSelectedItem (String state, bolean stateToReplace){
for (int i = 0; i < checkedListBox2.Items.Count; i++) {
checkedListBox2.SetItemChecked(i, stateToReplace);
}
string changed = state;
checkedListBox2.SelectedItem = changed;

How can i improve performance of my application?

I have three different function which i call based on the condition. When data is lesser my application performance is good. However, i have around 11000 rows of data my application taking 1-2 hour to complete the process.
I have some logic written in my functions which filters data and add into collection. Is there is any way i can improve the performance of my application using multi-threading or parallel processing. so that my function runs parallel and performance get improved.
I created a sample of my requirement below:
private void button1_Click(object sender, EventArgs e)
{
String[] AllData = new String[7];
AllData[0] = "1";
AllData[1] = "2";
AllData[2] = "3";
AllData[3] = "1";
AllData[4] = "2";
AllData[5] = "3";
AllData[6] = "1";
for (int i = 0; i < AllData.Length; i++)
{
CommonFunction(AllData[i]);
}
}
private void CommonFunction(String AllData)
{
if (AllData == "1")
{
Function1(1);
}
else if (AllData == "2")
{
Function2(2);
}
else
{
Function3(3);
}
}
private void Function1(int ID)
{
for (int i = 0; i < 10; i++)
{
}
}
private void Function2(int ID)
{
for (int i = 0; i < 10; i++)
{
}
}
private void Function3(int ID)
{
for (int i = 0; i < 10; i++)
{
}
}
Any help is highly appreciated.
Instead of sequential for loop, you can try to use Parallel.ForEach.
for (int i = 0; i < AllData.Length; i++)
{
CommonFunction(AllData[i].ToString());
}
can be converted to
Parallel.ForEach(AllData, someData =>
{
CommonFunction(someData);
});

how i do create find similar excel?

i want create search in form similar EXCEL , find and put (row) in listview
this my form :
and my code :
private int searchIndex = -1;
private void button1_Click(object sender, EventArgs e)
{
button1.Text = "Find Next";
try
{
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
searchIndex = (searchIndex + 1) % dataGridView1.Rows.Count;
DataGridViewRow row = dataGridView1.Rows[searchIndex];
if (row.Cells["Product"].Value == null)
{
continue;
}
if (row.Cells["Product"].Value.ToString().Trim().StartsWith(textBox1.Text) || row.Cells["Product"].Value.ToString().Trim().Contains(textBox1.Text))
{
ListViewItem lvi = new ListViewItem(row.Cells["Product"].Value.ToString());
lvi.SubItems.Add(row.Cells["Product"].Value.ToString());
listView1.Items.Add(lvi);
dataGridView1.CurrentCell = row.Cells["Product"];
dataGridView1.FirstDisplayedScrollingRowIndex = dataGridView1.Rows[row.Index].Index;
row = dataGridView1.Rows[i];
return;
}
}
}
catch { }
}
and in textbox1_textchanged :
searchIndex = -1;
button1.Text = "Find";
listView1.Clear();
I want when search end, send message ...
thanks
Mimicking the Find All functionality, populating your ListView will be very similar to the Find Next functionality. Here's an example if it were a separate button from Find Next:
public Form1()
{
InitializeComponent();
listView1.View = View.Details;
listView1.Columns.Add("Column");
listView1.Columns.Add("Row");
listView1.Columns.Add("Value");
}
private void button2_Click(object sender, EventArgs e)
{
button2.Text = "Find All";
int tempIndex = -1;
listView1.Items.Clear();
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
tempIndex = (tempIndex + 1) % dataGridView1.Rows.Count;
DataGridViewRow row = dataGridView1.Rows[tempIndex];
if (row.Cells["Foo"].Value == null)
{
continue;
}
if (row.Cells["Foo"].Value.ToString().Trim().StartsWith(textBox1.Text) || row.Cells["Foo"].Value.ToString().Trim().Contains(textBox1.Text))
{
DataGridViewCell cell = row.Cells["Foo"];
ListViewItem lvRow = new ListViewItem(new string[] { cell.ColumnIndex.ToString(), cell.RowIndex.ToString(), cell.Value.ToString() });
listView1.Items.Add(lvRow);
}
}
MessageBox.Show("Search ended."); // Or whatever message you intend to send.
}

Run time adding control in C#

I am making an application in which I want to add buttons on panel from my main form dynamically. If I have 10 items in List then that many buttons will be generate on panel from main form. But when I try to do that one then it shows me error that Control.Invoke required.
Please anyone suggest me how to add controls...??
private void CheckOrderListEntry(Workorder workorder)
{
int ticketID = workorder.TicketID;
int index = 0;
int lastIndex = _workorderList.Count;
bool isExist = false;
for (index = 0; index < lastIndex; index++)
{
int existingTicektId = _workorderList[index].TicketID;
if (ticketID == existingTicektId)
{
_workorderList[index] = workorder;
isExist = true;
break;
}
}
if (!isExist)
{
_workorderList.Add(workorder);
}
ListEventChangeHandler();
}
public void ListEventChangeHandler()
{
_orderBtn = new Button[_workorderList.Count];
int index = 0;
int lastIndex = _orderBtn.Length;
for (; index < lastIndex; index++)
{
Workorder workorder = _workorderList[index];
_orderBtn[index] = new Button();
_orderBtn[index].Name = String.Format("{0}", index);
_orderBtn[index].Text = String.Format("Order #: {0} Source: {1} Desination: {2}", workorder.TicketID, workorder.PickupAddress, workorder.DropoffAddress);
_orderBtn[index].BackColor = Color.SteelBlue;
_orderBtn[index].ForeColor = Color.White;
_orderBtn[index].Font = new Font("Tahoma", 16, FontStyle.Regular);
_orderBtn[index].Click += new EventHandler(OrderBtnClick);
}
UpdatePanel(_orderBtn);
}
public delegate void UpdateAcceptOrderPanel(Button[] btn);
public void UpdatePanel(Button[] btn)
{
try
{
if (this.InvokeRequired)
{
UpdateAcceptOrderPanel updateMyPanel = new UpdateAcceptOrderPanel(UpdatePanel);
this.Invoke(updateMyPanel, btn);
}
else
{
AddButtonOnPanel(btn);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
public void AddButtonOnPanel(Button[] btn)
{
for (int index = 0; index < btn.Length; index++)
{
this.acceptOrderPanle.Controls.Add(btn[index]);
}
}
I'm not very good on delegates, but this is the way I would do your UpdatePanel method ...
public void UpdatePanel(Panel panel, Button button)
{
if(panel.InvokeRequired)
{
panel.Invoke(new Action<Panel,Button>(UpdatePanel), new object[] {panel, button});
}
else
{
panel.Controls.Add(button);
}
}
hope this help ...

how to populate selected items from one list box to another on a button click action?

I have two list boxes L1 and L2. Now on a button click method i have to move the selected items in L1 to L2 and Items in L1 should get Deleted.
protected void Btn2_Click(object sender, EventArgs e)
{
string sel = LB1.SelectedValue;
List<string> ab = new List<string>();
ab.Add(sel);
L2.Text = Convert.ToString(ab.Count);
for(int i =0; i < ab.Count ; i++)
{
string c = ab[i];
LB2.Items.Add(c);
}
if you want to remove the SelectedItem from the ListBox1
add the following statement at the end of your function:
LB1.Items.Remove(LB1.SelectedValue);
Complete Code:
protected void Btn2_Click(object sender, EventArgs e)
{
string sel = LB1.SelectedValue;
List<string> ab = new List<string>();
ab.Add(sel);
L2.Text = Convert.ToString(ab.Count);
for(int i =0; i < ab.Count ; i++)
{
string c = ab[i];
LB2.Items.Add(c);
}
LB1.Items.Remove(LB1.SelectedValue);//Add This to remove selected item from ListBox1
}
protected void Btn2_Click(object sender, EventArgs e)
{
List<ListItem> itemList = new List<ListItem>();
if (LB1.SelectedIndex >= 0)
{
for (int i = 0; i < LB1.Items.Count; i++)
{
if (LB1.Items[i].Selected)
{
if (!itemList.Contains(LB1.Items[i]))
{
itemList.Add(LB1.Items[i]);
}
}
}
for (int i = 0; i < itemList.Count; i++)
{
if (!LB2.Items.Contains(itemList[i]))
{
LB2.Items.Add(itemList[i]);
}
LB1.Items.Remove(itemList[i]);
}
LB2.SelectedIndex = -1;
}
}

Categories