Looping Through C# Textboxes - c#

I'm trying to have the user input doubles into 4 different textBoxes. Then, once the user clicks the calculate button, the following will happen:
foreach loop runs, parses textbox.Texts to doubles, and then adds
them to a list
for loop runs and indexes through the list, adding
them all up.
List item sum from previous step is divided by the number of values in the list result is entered into another textbox.
When I run it, no errors happen, but the result is not displayed in the texbox. Why is nothing getting displayed?
private void CalculateButton_Click(object sender, EventArgs e)
{
double gpa = 0;
List<double> grades = new List<double>();
foreach(Control textBox in Controls)
{
if ((textBox.GetType().ToString() == "System.Windows.Form.Textbox") && (textBox.Name.Contains("gradeBox")))
{
grades.Add(double.Parse(textBox.Text));
}
}
for(int i =0; i<grades.Count; i++)
{
gpa += grades[i];
}
gpa /= grades.Count;
gpaBox.Text = gpa.ToString();
}

Looks like the namespace of textbox is not quite correct. It should be System.Windows.Forms.TextBox. Notice "s" and capital "B". Following is the corrected version.
private void CalculateButton_Click(object sender, EventArgs e)
{
double gpa = 0;
List<double> grades = new List<double>();
foreach (Control textBox in Controls)
{
if ((textBox.GetType().ToString() == "System.Windows.Forms.TextBox") && (textBox.Name.Contains("gradeBox")))
{
grades.Add(double.Parse(textBox.Text));
}
}
for (int i = 0; i < grades.Count; i++)
{
gpa += grades[i];
}
gpa /= grades.Count;
gpaBox.Text = gpa.ToString();
}

Related

Storing string values in array then displaying the array values

I’m a student working on a class project to store string values into an array[10] using a “Store” button. Then the “Display” button will display the string values in the array[10] in a list box. Extra credit if we display the position too.
Currently when I click the “Store” button I do see the message the value was stored. But when I click the “Display” button the list box shows 10 “0”. Every time I make it only makes it worse so I’m not sure what I’m missing and overlooking.
My global variables
string[] results = new string[10];
string value;
I’m using the for loop to take the string value in the “ResultLabel” to store them in the array[10] until all spaces are take, total of 10 values. The “StoreLabel” displays the message that the value was stored.
protected void StoreButton_Click(object sender, EventArgs e)
{
for (int i = 0; i < results.Length; i++)
{
results[i] = ResultLabel.Text.ToString();
}
StoreLabel.Text = "Results have been stored";
}
Then I believe I’m taking the values from the results[10] array and displaying those values in the list box.
protected void DisplayButton_Click(object sender, EventArgs e)
{
DisplayListBox.Items.Clear();
for (int i = 0; i < results.Length; i++)
{
DisplayListBox.Items.Add(results[i].ToString());
}
}
You can append the index to string.
private void StoreButton_Click(object sender, EventArgs e)
{
for (int i = 0; i < results.Length; i++)
{
results[i] = ResultLabel.Text.ToString();
}
StoreLabel.Text = "Results have been stored";
}
private void DisplayButton_Click(object sender, EventArgs e)
{
DisplayListBox.Items.Clear();
for (int i = 0; i < results.Length; i++)
{
DisplayListBox.Items.Add($"{results[i].ToString()} - {i}");
}
}
I understand your project requires you to use an array and to limit it to 10 items. Those requirements might be simplified if we let the ListBox do all the hard work. I'd like to offer an easy way to get strings into the ListBox with the idea that you can then adapt this strategy to meet your project requirements.
The ListBox is simple to work with if we tell it to use our list as the source of the items it displays. Then all we have to do is add an item to this list and tell the ListBox to Refresh() its contents.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
listBoxDisplay.DataSource = Values;
}
// Here is our list of strings
BindingList<string> Values = new BindingList<string>();
private void buttonStore_Click(Object sender, EventArgs e)
{
// We look at the value in the textbox and add it to list...
Values.Add((Values.Count + 1).ToString() + " - " + textBoxValueToAdd.Text);
// …and tell the ListBox to update itself from the list
listBoxDisplay.Refresh();
}
}

Use loop to clear. textBox[i].Clear(). Is this possible?

I am just looking to know this to try and clean up my code, and also for future reference.
I have a number of textBoxes.
tbPart1.Clear();
tbPart2.Clear();
tbPart3.Clear();
tbPart4.Clear();
tbPart5.Clear();
tbPart6.Clear();
tbPart7.Clear();
Is there any way I could use a loop to replace the numbers?
I tried this, but have no idea how i could run the string.
for (int i = 1; i == 7; i++)
{
string p = "tbPart" + i.ToString() + ".Clear";
}
Inside of the form's code (i.e. in a button click event handler), you can enumerate through all of the TextBox controls on the form and perform a specific action on them:
this.Controls.OfType<TextBox>().ToList().ForEach(x => x.Clear());
If you need to only clear some of the TextBox controls, you can provide a sort of filter like so:
this.Controls.OfType<TextBox>()
// Add a condition to clear only some of the text boxes - i.e. those named "tbPart..."
.Where(x=>x.Name.StartsWith("tbPart"))
.ToList().ForEach(x => x.Clear());
No, you cannot do it that way. But you can define an array or list where you put the controls and then clear them. For example:
List<TextBox> textboxes = new List<TextBox>();
textboxes.Add(tbPart1);
textboxes.Add(tbPart2);
textboxes.Add(tbPart3);
...
Then when you want to clear them
foreach (var tb in textboxes)
tb.Clear();
TextBox[] boxes = new [] {
tbPart1,
tbPart2,
tbPart3,
tbPart4,
tbPart5,
tbPart6,
tbPart7
};
for (int i = 0; i < boxes.Length; i++)
{
boxes[i].Clear();
}
i think you should use an array of textbox then you can do a loop depends the count of numbers of textboxes.
foreach(Control ctrl in this.Controls)
{
if(ctrl.GetType() == typeof(TextBox))
{
ctrl.Text = String.Empty;
}
}
Answer number one by using Control name inside panel1
private void button2_Click(object sender, EventArgs e)
{
string currentCtrlName;
for (int i = 0; i < panel1.Controls.Count; i++)
{
currentCtrlName = "textBox" + (i+1).ToString();
panel1.Controls[currentCtrlName].Text = "";
}
}
==================
Answer number one by using Control index as a child inside panel1
private void button2_Click(object sender, EventArgs e)
{
for (int i = 0; i < panel1.Controls.Count; i++)
{
panel1.Controls[i].Text = "";
}
}
==================

Loop through array values?

So I have a listbox of salaries. And a button, which if clicked, shows the number of salaries above the average salary amount, and the number below the average salary amount. However, I cannot for the life of me figure out how to form this loop which return the number below and above the avg. salary amount. Here is what I have so far:
double[] employeeSalary = new double[7] { 8500.50, 7005.99, 9123.00, 100123.50, 6550.00, 8123.90, 7500.95 };
public Form2()
{
InitializeComponent();
listBox1.DataSource = employeeSalary;
}
private void button3_Click(object sender, EventArgs e)
{
double avgSalary;
avgSalary = employeeSalary.Average();
for (int i = 0; i < employeeSalary.Length; i++)
{
}
}
You already used LinQ, you can use it for the other tasks, too:
var avgSalary = employeeSalary.Average();
var aboveAverageCount = employeeSalary.Count(x => x > avgSalary);
var belowAverageCount = employeeSalary.Count(x => x < avgSalary);

How to get header values when click pivot table item in a gridview

This could be a little tricky so please bear with me.
I have this result from a gridview, the data came from a pivot table:
DateCreate 02/11/2013 02/19/2013 Total
OrdersPendInvoice 0 1 1
OrdersPendPickUp 1 15 16
Here the selectable items are the numbers, and just the numbers greater than zero.
So first I need for those items (the selectable ones) make them like linkButtons son when I click in one of them I can pass as reference (here the other tricky part) both headers.
Let's put an example:
If I clicked on number 15, which basically means that there are 15 OrdersPendPickUp for the date 02/19/2013. Then I will go to a different page with the references 02/19/2013 and OrdersPendPickUp and there show those 15 records. I have no problem with the last part as long as I have the references.
And for the Total case, I'd just need either the OrdersPendInvoice or OrdersPendPickUp (depending on the item selected) cause I will get all records for that reference no matter the date.
I did this but it's not much really, just changes the color of the items greater than zero :(
protected void gvOrdersProcessed_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType != DataControlRowType.Pager)
{
for (int i = 0; i <= e.Row.Cells.Count - 1; i++)
{
if (TryToParse(e.Row.Cells[i].Text) > 0)
{
e.Row.Cells[i].ForeColor = System.Drawing.Color.Red;
}
}
}
}
private int TryToParse(string value)
{
int number;
bool result = Int32.TryParse(value, out number);
if (result)
return number;
else
return 0;
}
Yes, it is tricky. However, give the following a try:
private List<string> _headers = new List<string>();
protected void gvOrdersProcessed_RowDataBound(object sender, GridViewRowEventArgs e)
{
//Collect the texts from the column headers
if (e.Row.RowType == DataControlRowType.Header)
{
for (int i = 0; i <= e.Row.Cells.Count - 1; i++)
{
this._headers.Add(e.Row.Cells[i].Text);
}
}
if (e.Row.RowType == DataControlRowType.DataRow)
{
for (int i = 0; i <= e.Row.Cells.Count - 1; i++)
{
if (TryToParse(e.Row.Cells[i].Text) > 0)
{
string rowKey = e.Row.Cells[0].Text;
string column = this._headers[i];
HyperLink link = new HyperLink();
link.Text = e.Row.Cells[i].Text;
link.NavigateUrl="page.aspx?key=" + rowKey + "&column=" +column;
e.Row.Cells[i].Controls.Clear();
e.Row.Cells[i].Controls.Add(link);
}
}
}
}
Links would be like:
Normal values: ~/page.aspx?key=OrdersPendPickUp&column=02/19/2013
Total: ~/page.aspx?key=OrdersPendPickUp&column=Total

on-the-fly search algorithm in listbox

So, I have a listbox with x number of items. On top of the listbox I have a TextBox (this is the search field). I try do develop an algorithm that removes items from the listbox, if it doesn't contain the searchword (variable keyword in the code). This is supposed to happen for each key the user types (on-the-fly). So, the code:
private void _keywordTextBox_TextChanged(object sender, EventArgs e)
{
string keyword = _keywordTextBox.Text;
if (keyword == searchtext || isSpace) // do nothing if space is typed - searchtext is a templatetext in the textbox ("type here to search...")
return; // ignore
else if (keyword == "")
{
listBox.Items.Clear();
foreach (string s in originalList)
listBox.Items.Add(s);
}
else
{
List<string> selection = new List<string>();
foreach (string s in originalList) // originalList is the listbox at startup
selection.Add(s);
listBox.BeginUpdate();
string[] keywordSplit = keyword.Split(' ');
try
{
for (int i = originalList.Count - 1; i >= 0; i--)
{
string[] selectionSplit = selection[i].Split(' ');
int l = 0; // number of hits
for (int j = 0; j < selectionSplit.Length; j++)
{
for (int k = 0; k < keywordSplit.Length; k++)
{
if (selectionSplit[j].ToLower().Contains(keywordSplit[k].ToLower()))
{
l++;
break;
}
}
}
if (l < keywordSplit.Length) // Not hit on all keywords
selection.RemoveAt(i);
}
}
finally
{
listBox.Items.Clear();
foreach (string s in selection) // Add selection in listbox
listBox.Items.Add(s);
if (listBox.Items.Count > 0)
listBox.SetSelected(0, true); // Select first item in listbox
listBox.EndUpdate();
}
}
}
The problem is hard to describe, other than it doesn't work as intended. The behavour is, as far as I can see, sporadic.
If I search for "ck flow", I should get a hit for stackoverflow. More importantly, it should also work if I deletes chars (delete key of backspace). Anybody?
Edit: more details:
The listbox should shrink and grow on each keystroke, based on what the user searches for. The listbox should keep every item that matches the keyword typed in by the user, and filter away that doesn't match.
Or you could try to work out a Regular Expression:
private void textBox1_TextChanged(object sender, EventArgs e)
{
string keyword = textBox1.Text;
if (string.IsNullOrEmpty(keyword.Trim()))
{
listBox1.Items.Clear();
listBox1.Items.AddRange(_originalList.ToArray());
}
else
{
Regex regex = new Regex(GetRegexPatternFromKeyword(keyword));
List<string> selection =
_originalList.Where(s => regex.IsMatch(s)).ToList();
listBox1.Items.Clear();
listBox1.Items.AddRange(selection.ToArray());
}
}
private static string GetRegexPatternFromKeyword(string keyword)
{
string[] words =
keyword.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Select(word => "(?=.*" + word.Replace(")", #"\)") + ")").ToArray();
return string.Join("", words);
}
disclaimer: there could be some cases where an input would 'destroy' the regex pattern
Your code increases l too often. For instance;
the text 'aaa aaa aaa' with searchword 'aaa bbb' will give an l of 3 because every time you find 'aaa' you increase l. So this will be a match even though 'bbb' is never found.
You can fix this (among others) by deleting found parts of keywordsplit and recreating keywordsplit anew before every search of a new selectionline.
l++;
break;
becomes
l++
keywordSplit.RemoveAt[k];
break;
and move
string[] keywordSplit = keyword.Split(' ');
to just before you start the k loop
Altough I feel there might be better ways to achieve what you want with a bit cleaner and faster code it should work.
I got it to work. #IvoTops helped me in the right direction. Just loop trough all the keyword first, and then the selections.
for (int j = 0; j < keywordSplit.Length; j++)
{
for (int k = 0; k < selectionSplit.Length; k++)
{
if (selectionSplit[k].ToLower().Contains(keywordSplit[j].ToLower()))
{
l++;
break;
}
}
}
Seems to work ok now.

Categories