Saving state of multiple checkboxes using lists - c#

I am making application that stores data that users input through form. Since i have quite a few checkboxes and form stretches on multiple pages. I want to save state of these checkboxes so when i go to next page and come back, previously checked checkboxes should be checkedagain.
I am trying to accomplish this by using List<CheckBox> and bool[]. But it just doesnt work for some reason. I dont know what i am missing.
public void Ucitavanje34(bool[] Lista,List<CheckBox> check )
{
foreach (CheckBox ajtem in check)
{
int i = 0;
if (ajtem.Checked==true)
{
Lista[i] = true;
++i;
}
else
{
Lista[i]= false;
++i;
}
}
MessageBox.Show(string.Join(Environment.NewLine,Checkboxstrana3,boolarray ));
}
public void Ucitavanje43(bool[] Lista, List<CheckBox> check)
{
foreach (bool ajtem in Lista)
{
int i = 0;
if (ajtem == true)
{
check[i].Checked = true;
++i;
}
else
{
check[i].Checked = false;
++i;
}
}
MessageBox.Show(string.Join(Environment.NewLine,Stanje));
}
I know i can do this manually(1by1) but it is to cumbersome.
The output i get is just silly and i dont know what i am doing wrong .

You're resetting i to zero for each check box. It would probably be better to use a single for loop and use i for the index on both the List and the bool[].

The other answers already pointed out your problem, I just wanted to provied a different approach because your task is a good example where you can benefit from using LINQ.
bool[] Lista = check.Select(x => x.IsChecked).ToArray();
Refer to https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.select?view=netframework-4.8 if you're interested in that.

Your problem is in the for loop
you are doing int i=0; inside forloop. This will always fetch the first element from list.
public void Ucitavanje34(bool[] Lista,List<CheckBox> check )
{
int i = 0; //this line
foreach (CheckBox ajtem in check)
{
Lista[i] = ajtem.Checked;
++i;
}
MessageBox.Show(string.Join(Environment.NewLine,Checkboxstrana3,boolarray ));
}

public Dictionary<string, bool> Save(params CheckBox[] check)
{
Dictionary<string, bool> result = new Dictionary<string, bool>();
foreach (CheckBox item in check)
result.Add(item.Name, item.Checked);
return result;
}
public void Apply(Dictionary<string, bool> savedResults)
{
foreach (var item in savedResults)
{
var check = this.Controls[item.Key];
// var check = this.Controls.Find(item.Key, true).FirstOrDefault(); //easier way to find checkboxes
if(check != null && check.GetType().ToString() == "System.Windows.Forms.CheckBox")
{
((CheckBox)check).Checked = item.Value;
}
}
}
How to call it:
result = Save(checkBox1, checkBox2, checkBox3, checkBox4);
Now, save the result everywhere you want.
How to use it:
Dictionary<string, bool> result = ... // Load from somewhere
Apply(result);

Related

Taking a set of items from a list and to perform some operation based on need

I have a list of items in a list. From that list I need to take the first 1000 items and need to submit the package and then again I need to take another 1000 and need to submit a package. If the list is not having 1000 I need to submit the package with all the items. for that I wrote the following code which is returning an error as collection modified.
List<SyncQueue> tempMassiveSyncQueue=massiveSyncQueue;
while (tempMassiveSyncQueue.Count != 0)
{
int MassivePackageFileCount =Convert.ToInt32(ConfigurationManager.AppSettings["MassivePackageFileLimit"]);
massiveSyncQueues = tempMassiveSyncQueue;
List<SyncQueue> tempMassivePackageSyncQueue=new List<SyncQueue>();
if (massiveSyncQueues.Count > 1000
{
var massivePackageSyncQueue = (massiveSyncQueues.Take(1000)).ToList<SyncQueue>();
tempMassivePackageSyncQueue = massivePackageSyncQueue;
SubmitPackage(massivePackageSyncQueue);
}
if (tempMassivePackageSyncQueue.Count != 0)
{
foreach (var massivesynq in tempMassiveSyncQueue)
{
foreach (var deleteId in tempMassivePackageSyncQueue.Where(id => id.SyncQueueId == massivesynq.SyncQueueId))
{
tempMassiveSyncQueue.Remove(massivesynq);
}
}
}
else
{
SubmitPackage(massiveSyncQueues);
}
massiveSyncQueues = null;
}
Can any one help on this?
Incorporate Skip into your logic
int loopCount = 0;
While(true)
{
var ListToProcess = massiveSyncQueue.Skip(loopCount*1000).Take(1000);
SubmitPackage(ListToProcess);
if(ListToProcess.Count < 1000) // We know there are no more in the list massive list.
{
break;
}
loopCnt++;
}
Your problem is that you are adjusting the collection on which the bounds of the foreach construct are set.
Try using ToList() on the collection you are looping through, as this creates a new List in memory:
foreach (var massivesynq in tempMassiveSyncQueue.ToList())
{
foreach (var deleteId in tempMassivePackageSyncQueue.Where(id => id.SyncQueueId == massivesynq.SyncQueueId).ToList())
{
tempMassiveSyncQueue.Remove(massivesynq);
}
}
In line 1 you set tempMassiveSyncQueue = massiveSyncQueue, yet within the while loop you set massiveSyncQueue = tempMassiveSync.
The collection modified error usually occurs when you modify the collection you are looping through. Which is why you need to first create a copy of the collection which is INDEPENDANT to the original collection and loop through that.
Before the while loop you need to add all items in massiveSyncQueue to tempMassiveSyncQueue. You then need to loop through the temp list with your code. In the second loop, you are removing items from the list you are looping through. I assume you meant to remove the items from massiveSyncQueue and not the temp list.
Try the following:
List<SyncQueue> tempMassiveSyncQueue = new List<SyncQueue>();
foreach(var item in massiveSyncQueue)
{
tempMassiveSyncQueue.Add(item);
}
while (tempMassiveSyncQueue.Count != 0)
{
int MassivePackageFileCount = Convert.ToInt32(ConfigurationManager.AppSettings["MassivePackageFileLimit"]);
List<SyncQueue> tempMassivePackageSyncQueue=new List<SyncQueue>();
if (massiveSyncQueues.Count > 1000
{
var massivePackageSyncQueue = (massiveSyncQueues.Take(1000)).ToList<SyncQueue>();
tempMassivePackageSyncQueue = massivePackageSyncQueue;
SubmitPackage(massivePackageSyncQueue);
}
if (tempMassivePackageSyncQueue.Count != 0)
{
foreach (var massivesynq in massiveSyncQueue)
{
foreach (var deleteId in tempMassivePackageSyncQueue.Where(id => id.SyncQueueId == massivesynq.SyncQueueId))
{
massiveSyncQueue.Remove(massivesynq);
}
}
}
else
{
SubmitPackage(massiveSyncQueues);
}
massiveSyncQueues = null;
}
Try this
int count=1;
while(tempMassivePackageSyncQueue.Count>1000)
{
var massivePackageSyncQueue = (massiveSyncQueues.skip(count*1000).Take(1000)).ToList<SyncQueue>();
tempMassivePackageSyncQueue = massivePackageSyncQueue;
SubmitPackage(massivePackageSyncQueue);
count++;
}
var massivePackageSyncQueue = (massiveSyncQueues.skip(count*1000).Take()).ToList<SyncQueue>();
tempMassivePackageSyncQueue = massivePackageSyncQueue;
SubmitPackage(massivePackageSyncQueue);

Foreach going out of bounds while searching through array c#

The purpose of my program is to take a data txt file and edit it, and/or make additions and subtractions to it.
The text file format is like this:
Name|Address|Phone|# of people coming|isRSVP
The code I have seems to be doing it's job all the way up until I try to click one of the names within a listbox and it needs to search through the multidimensional array to pull information out and place within a set of textboxes where they can be edited. The problem is that the foreach loop I use gives me an out of bounds exception. I tried to do a step into debug to make sure the data is correct in the array and see the process. Everything seems to do correctly but for some reason in the conditional statement person[0]==listbox1.selectedIndex isn't returning true even though both are the same as I seen through the step into process. Any help would be greatly appreciated.
This is my code:
StringBuilder newFile = new StringBuilder();
static string txtList= "guest_list.txt";
static string[] file = File.ReadAllLines(txtList);
static int x = file.Count();
string[,] list = new string[x ,5];
public void loadGuestList()
{
int count2 = 0;
foreach (string line in file)
{
string[] sliced = line.Split('|');
int count = 0;
list[count2, count] = sliced[0];
count++;
list[count2, count] = sliced[1];
count++;
list[count2,count] = sliced[2];
count++;
list[count2,count]= sliced[3];
count++;
list[count2, count] = sliced[4];
count++;
listBox1.Items.Add(list[count2,0]);
count2++;
}
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
foreach (string person in list)
{
if ( person[0].ToString()==listBox1.SelectedItem.ToString())
{
addTxt.Text = char.ToString(person[1]);
textPhone.Text = char.ToString(person[2]);
textPeople.Text = char.ToString(person[3]);
if (person[4] == 'n' )
{
}
else
{
chkRSVP.Checked = true;
}
break;
}
}
}
The problem lies in this line:
foreach (string person in list)
The list is defined as being string[,] which when you for each over will do every element, not just the column of data. You really should do something such as:
for(int index = 0; index <= list.GetUpperBound(0); index++)
{
string slice1 = list[index, 0];
string slice2 = list[index, 1];
....
}
or switch to using a Dictionary<string, string[]>().
Try to use a "Person" object and override equals(). Right now you're trying to put your multidimensional array (list[0]) into a string, it'll give you a unwanted result. You should use list[0,0] instead.
In agreement with Adam Gritt, I tested the following code and it seemed to work:
using System;
namespace so_foreach_bounds
{
class MainClass
{
public static void Main (string[] args)
{
//System.Text.StringBuilder newFile = new System.Text.StringBuilder();
string txtList= "guest_list.txt";
string[] file = System.IO.File.ReadAllLines(txtList);
int x = file.Length;
System.Collections.Generic.List<string[]> list = new System.Collections.Generic.List<string[]> ();
foreach (string line in file)
{
string[] sliced = line.Split('|');
list.Add(sliced);
}
foreach (string[] person in list)
{
Console.WriteLine (String.Join(", ", person));
if (person[0] =="Gary")
{
string txtAdd = person[1];
string txtPhone = person[2];
string txtpeople = person[3];
if (person[4] == "n" )
{
}
else
{
bool has_resvped = true;
}
break;
}
}
}
}
}
The issue is how you are iterating over the 2d array. It is usually a better idea to create a "Person" class, than try to manage it via arrays though. Oh yes, and it's usually a good idea to check that a list box item is selected before attempting to use one of its members.

Compare Model to List<string>

I have 2 lists I am trying to compare.
List SelectedPersonCodes; is a just a list of strings (obviously)
List CurrentUserLocations; is a list of LocationId, LocationName pairs.
I need to see if any of the CurrentUserLocation locationIds have a match in the SelectedPersonCOdes list, which is made up of locationIds.
I have put together this:
public JsonResult VerifyDetailAccess(int id)
{
List<UserLocation> CurrentUserLocation = repo.GetUserLocations();
List<string> SelectedPersonLocations = repo.GetTrespassedSiteCodes(id);
bool IsAuth = false;
foreach (var current in CurrentUserLocation)
{
for(var s = 0; s < SelectedPersonLocations.Count(); s++)
{
if(current.LocationCode == SelectedPersonLocations[s])
{
IsAuth = true;
}
}
}
return Json(IsAuth, JsonRequestBehavior.AllowGet);
}
It always comes out false. The problem is the if statement, I am not getting the values in the SelectedPersonLocations. How do I expose those values so I can iterate against them?
I have also tried dual foreach:
foreach (var current in CurrentUserLocation)
{
foreach (var select in SelectedPersonLocations)
{
if(current.LocationCode == select)
{
IsAuth = true;
}
}
This exposes the value in select, but even if current.LocationCode and select are the same, it still skips setting the flag, so IsAuth stays false.

compare List<string> and List<T>

I'm using C# and framework 4.0.
I have a list of type string and another list of type class T;
How can I compare List with a List and save the difference?
private void simpleButton_Compare_Click(object sender, EventArgs e)
{
try
{
bool Is_Egal = true;
int i = 0;
foreach (string Od_Scan in Ordre_Scan)
{
if (!Outils.Get_Ordre_Donne()[i].NoOrdre.Contains(Od_Scan) && !String.IsNullOrWhiteSpace(Od_Scan))
{
Is_Egal = false;
Temp_Od_Scan.Add(Od_Scan);
}
i++;
}
foreach (Pers_Compare Od_Done in Outils.Get_Ordre_Donne())
{
if (!Ordre_Scan.Contains(Od_Done.NoOrdre) && !String.IsNullOrWhiteSpace(Od_Done.NoOrdre))
{
Is_Egal = false;
Temp_Od_Donne.Add(Od_Done);
}
else
{
Temp_Od_Donne_Egal.Add(Od_Done);
}
}
if (Is_Egal)
{
MessageBox.Show("égalité");
}
else
{
MessageBox.Show("PAS égalité");
}
}
catch (Exception excThrown)
{
MessageBox.Show(excThrown.Message);
}
}
and the data :
List<string> Ordre_Scan= new List<string> { "azer","qsdf"};
Pers_Compare obj = new Pers_Compare();
obj.Nolv = 1;
obj.Noordre = "qsdf"
Pers_Compare obj2 = new Pers_Compare();
obj2.Nolv = 1;
obj2.Noordre = "wxcv"
List<Pers_Compare> Ordre_Donne = new List<Pers_Compare>();
Ordre_Donne.add(obj);
Ordre_Donne.add(obj2);
And I want to save the data in Ordre_Donne but not in Od_Scan and vice versa.
foreach (string Od_Scan in Temp_Od_Scan)
{
all item that not found in List A
--> wxcv
}
foreach (var Od_Done in Temp_Od_Donne)
{
all item that not found in List B
--> azer
}
The answer given for a slightly different question (comparing a List with another List) seems to me to be a good solution for your issue, they address multiple issues to do with comparisons of lists.
EDIT: However you should be more specific with your requirements i.e. what exactly is a 'difference', e.g. is {1,1,2} and {1,2} the same?
Here is the answer given the most votes... (included here just encase it gets removed for some reason (as per Bob' suggestion))
"
DESCRIPTION:
I need to check that they both have the same elements, regardless of their position within the list. Each MyType object may appear multiple times on a list. Is there a built-in function that checks this? What if I guarantee that each element appears only once in a list?
EDIT: Guys thanks for the answers but I forgot to add something, the number of occurrences of each element should be the same on both lists.
ANSWER:
If you want them to be really equal (i.e. the same items and the same number of each item), I think that the simplest solution is to sort before comparing:
Enumerable.SequenceEqual(list1.OrderBy(t => t), list2.OrderBy(t => t))
Edit:
Here is a solution that performs a bit better (about ten times faster), and only requires IEquatable, not IComparable:
public static bool ScrambledEquals<T>(IEnumerable<T> list1, IEnumerable<T> list2) {
var cnt = new Dictionary<T, int>();
foreach (T s in list1) {
if (cnt.ContainsKey(s)) {
cnt[s]++;
} else {
cnt.Add(s, 1);
}
}
foreach (T s in list2) {
if (cnt.ContainsKey(s)) {
cnt[s]--;
} else {
return false;
}
}
return cnt.Values.All(c => c == 0);
}
Edit 2:
To handle any data type as key (for example nullable types as Frank Tzanabetis pointed out), you can make a version that takes a comparer for the dictionary:
public static bool ScrambledEquals<T>(IEnumerable<T> list1, IEnumerable<T> list2, IEqualityComparer<T> comparer) {
var cnt = new Dictionary<T, int>(comparer);
...
"
var list1 = Ordre_Donne.Where(o => !Ordre_Scan.Any(s => s == o.Noordre));
var list2 = Ordre_Scan.Where(s => !Ordre_Donne.Any(o => o.Noordre == s));
You can either implement IComparable on your Pers_Compare class, which will look something like:
public int CompareTo(string other)
{
return this.Noordre.CompareTo(other);
}
Or, if you don't have control of the data structure, you could do something like
var Temp_Od_Donne = from od in Ordre_Donne
where !Ordre_Scan.Contains(od.Noordre)
select od;
var Temp_Od_Scan = from os in Ordre_Scan
where !Ordre_Donne.Select(od => od.Noordre).Contains(os)
select os;

convert foreach loop to linq code

the below code is working as expected but I'm looking to convert the below code to use Linq?
any suggestions?
string[] selections = "Men,Women,Boys".Split(',');
int _chkboxId = 0;
int _chkboxTextId = 1;
try
{
string id = "lstchk_" + _chkboxId;
while (!driver.FindElement(By.Id(id)).Equals(null))
{
string checkboxId = String.Format("lstchk{0}", _chkboxTextId);
string checkboxName = driver.FindElement(By.Id(checkboxId)).Text;
foreach (string match in selections)
{
if (checkboxName == match.Trim())
{
//matched... do more work here...
}
}
}
foreach (string match in selections.Where(match => checkboxName == match.Trim()))
{
//matched... do more work here...
}
If your selections list contains only distinct values, than you could use
if(selections.Any(match=>match.Trim().Equals(checkboxName)))
{
//Do work
}
instead of your loop. Same if your list may contain non-distinct values, but the work should be done only once for each checkboxName
switch(checkboxName) {
case "Men":
case "Women":
case "Boys":
// do more work here
default:
// no match, bail
}
Sometimes, there's just a different way to write the code.
How would you convert this simple foreach to a linq statement?
public List<string> GetItems()
{
var items = new List<string>();
foreach (Ranorex.ListItem item in ranorexComboBox.Items)
{
items.Add(item.Text);
}
return items;
}

Categories