Im trying to Create a method that can look at all text boxes in my program and tell me when the next blank one is so far. this is what i have come up with and cannot get it to work
public void CheckBox()
{
string[] itemBoxArray = new string[] { "itemBox1", "itemBox2", "itemBox3", "itemBox4", "itemBox5", "itemBox6",
"itemBox7", "itemBox8", "itemBox9", "itemBox10","itemBox11","itemBox12","itemBox13","itemBox14","itemBox15","itemBox16",};
for (int i = 0; i < itemBoxArray.Length; i++)
{
if (itemBoxArray[i] == string.Empty)
{
MessageBox.Show(" " + itemBoxArray[i] + " Is empty");
}
else
{
MessageBox.Show("Item Box is full");
}
}
}
create array of TextBox like below
public void CheckBox()
{
TextBox[] itemBoxArray = new TextBox[] { itemBox1, itemBox2, ........};
for (int i = 0; i < itemBoxArray.Length; i++)
{
if (String.IsNullOrEmpty(itemBoxArray[i].Text))
{
MessageBox.Show(" " + itemBoxArray[i].Name + " Is empty");
}
else
{
MessageBox.Show("Item Box is full");
}
}
}
You could use something like this to find the first TextBox that has an empty Text value:
var emptyTextBox = Controls.OfType<TextBox>().First(x => x.Text == string.Empty);
MessageBox.Show(string.Format(" {0} Is empty", emptyTextBox.Name));
You'll probably have to beef this up a bit.
It'll fail if no TextBox is empty. Use FirstOrDefault and test for null if that's a concern.
Also, it'll fail to find TextBox controls inside of a GroupBox or Panel. That may not matter depending on how your form is designed.
If you only have a set number of TextBox controls to check for, your code will work with a little adjustment, but if you're going to keep adding more TextBoxes, it's going to be a pain to maintain.
Related
I have the following code
private List<CheckBox> list = new List<CheckBox>();
//Displays toppings in receipt
foreach (CheckBox cbToppings in gbToppings.Controls)
{
if (cbToppings.Checked == true)
{
list.Add(cbToppings);
iToppings++;
}
}
for (Int32 i = 0; i < list.Count; i++)
{
txtToppingsReceipt.Text += Convert.ToString(list[i].Text + Environment.NewLine);
}
I have a groupbox with checkboxes in them, and the goal is to display the checked items in a multiline textbox when a button (btnOrder) is clicked. That part works perfectly for the first time, however, right now, when I click the btnOrder again, it does not clear the original output, despite me putting txtToppingsReceipt.Clear();.
I have another button which basically resets all fields, and that the clear textbox code is under that button. However no matter where I put that code, it simply does not want to clear the box after everytime btnOrder is clicked.
Am I doing something wrong? Will you guys be able to help me, I guess, reset the loop after every time it runs? If I put "break;" in the for loop, the code only runs once, and refuses to cooperate the second time I click btnOrder.
I'm new to programming so I may be getting ahead of myself. Either way, hopefully you guys can help me figure this thing out...
Your code should look something like this:
void MethodName()
{
List<CheckBox> list = new List<CheckBox>();
foreach (CheckBox cbToppings in gbToppings.Controls)
{
if (cbToppings.Checked == true)
{
list.Add(cbToppings);
iToppings++;
}
}
txtToppingsReceipt.Text = "";
for (Int32 i = 0; i < list.Count; i++)
{
txtToppingsReceipt.Text += list[i].Text + Environment.NewLine;
}
}
That way you're creating a new list each time and you're clearing the txtToppingsReceipt text before rebuilding it.
Please note that you didn't show us your full method so I don't know what name you've called it.
Or even better, like this:
void MethodName()
{
txtToppingsReceipt.Text = "";
foreach (CheckBox cbToppings in gbToppings.Controls)
{
if (cbToppings.Checked == true)
{
txtToppingsReceipt.Text += list[i].Text + Environment.NewLine;
iToppings++;
}
}
}
You could have written your code like this though:
var list = gbToppings.Controls.OfType<CheckBox>().Where(x => x.Checked == true).Select(x => x.Text).ToList();
iToppings = list.Count;
txtToppingsReceipt.Text = String.Join(Environment.NewLine, list);
Why not simply start with txtToppingsReceipt.Text = ""; to clear the textbox.
txtToppingsReceipt.Text = "";
list.Clear();
//Displays toppings in receipt
foreach (CheckBox cbToppings in gbToppings.Controls)
{
if (cbToppings.Checked == true)
{
list.Add(cbToppings);
iToppings++;
}
}
for (Int32 i = 0; i < list.Count; i++)
{
txtToppingsReceipt.Text += Convert.ToString(list[i].Text + Environment.NewLine);
}
If would not suggest to use a multiline text box for keep adding the line. Use a rich text box and use rtb.AppendText
Don't use += operator to append string, make use of = operator to assign changed value of txtToppingsReceipt.Text. I have refactor code and will work as expected.
string totalToppings = string.Empty;
foreach (CheckBox cbToppings in gbToppings.Controls)
{
if (cbToppings.Checked == true)
{
totalToppings += cbToppings.Text + Environment.NewLine;
iToppings++;
}
}
txtToppingsReceipt.Text = totalToppings;
I usually figure things out but this has me beat.
I have an array of listboxes on a form and a submit button. The user can pick items from any listbox then click the submit button to choose the confirm the item, but what needs to happen is that if they select something from listbox 1 then change their mind and select something from listbox 2, the item selected in listbox 1 should become unselected.
I can code that in to the eventhandlers but the problem is as soon as I change a value in another listbox programatically it fires another event. I can't seem to logic my way out of it.
Any ideas would be great otherwise I guess I will just have to put multiple submit buttons.
EDIT:
I figured out what I think is quite an obvious and simple solution in the end. I made use of the focused property to distinguish whether the user or the program was making changes. Works for both mouse and keyboard selections.
Thanks for the suggestions...
for (int i = 0; i < treatments.Length; i = i + 1)
{
this.Controls.Add(ListBoxes[i]);
this.Controls.Add(Labels[i]);
this.Controls.Add(Spinners[i]);
Labels[i].Top = vPosition - 20;
Labels[i].Left = hPosition;
Labels[i].Width = 600;
ListBoxes[i].Left = hPosition;
ListBoxes[i].Top = vPosition;
ListBoxes[i].Width = 600;
Spinners[i].Top = vPosition + ListBoxes[i].Height;
Spinners[i].Left = hPosition + ListBoxes[i].Width - 60;
Spinners[i].Width = 40;
for (int d = 25; d > 0; d = d - 1) { Spinners[i].Items.Add((d).ToString()); }
Spinners[i].SelectedIndex = 24;
//EVENT HANDLER CODE that is executed if any selectetindexchange in any LIstbox in array
ListBoxes[i].SelectedIndexChanged += (sender, e) =>
{
for (int s = 0; s < i; s = s + 1)
{
//FIND WHICH LBs[s] IS THE SENDING LISTBOX
if (ListBoxes[s] == sender && ListBoxes[s].Focused == true)
{
string msg = "sender is ListBox " + s.ToString() + "\nFocus is" + ListBoxes[s].Focused.ToString();
// MessageBox.Show(msg);
}
else if(ListBoxes[s].Focused==false)
{
ListBoxes[s].SelectedIndex = -1;
}
}
}; //end of event handler
}
I generally solve this kind of problem with a flag that lets me know that I am changing things, so my event handlers can check the flag and not take action in that case.
private int codeChangingCount = 0;
private void combobox1_SelectedIndexChanged(object sender, EventArgs e) {
codeChangingCount++;
try {
combobox2.SelectedIndex = someNewValue;
} finally {
codeChangingCount--;
}
}
private void combobox2_SelectedIndexChanged(object sender, EventArgs e) {
if (codeChangingCount == 0) {
//I know this is changing because of the user did something, not my code above
}
}
You can do this with a simple bool instead of an int, but I like the counter approach so that I can keep incrementing codeChangingCount in nested calls and not accidentally reset it. In my production code, I have a class dedicated to this kind of flagging, and it (mis)uses IDisposable to decrement, so I can just wrap my calls in a using block, but the above snippet is simpler for illustration.
Check if Focused ListBox == ListBox2 and SelectedIndex > -1 then deselect Index[0]
if (ListBoxes[s] == sender && ListBoxes[s].Focused == true)
{
if(s == 1 && ListBoxes[s].SelectedIndex > -1) //assuming 1 is listbox2
{
ListBoxes[0].SelectedIndex = -1; // Deselect ListBox1
}
string msg = "sender is ListBox " + s.ToString() + "\nFocus is" + ListBoxes[s].Focused.ToString();
}
I have created two string arrays from a text file and populated a combobox with array1. What I would like to understand is, how do I get a textbox to show the index of array2 that matches the selected index of the combobox (array1)?
I thought something like this may work:
if(phoneComboBox.Text == cPhone[index])
{
nameTextBox.Text = cName[index]; //show equal index item to cPhone/phoneComboBox
}
But that doesn't seem to work. I've also tried a foreach loop, maybe I'm just doing it wrong. I have the reading of the text file and arrays in the window_loaded event and don't know if that's the issue. I've seen SelectedIndexChanged event mentioned a lot in similar questions, but I do not have that event to use, just SelectionChanged.
Can someone please point me on the right track with this? I know arrays may not be the best use here, but they are what I have used, so please help me to understand it properly.
This is how I've read the arrays:
private void Window_Loaded_1(object sender, RoutedEventArgs e)
{
//read file on start
int counter = 0;
string line;
StreamReader custSR = new StreamReader(cFileName);
line = custSR.ReadLine();
while (line != null)
{
Array.Resize(ref cPhone, cPhone.Length + 1);
cPhone[cPhone.Length - 1] = line;
counter++;
line = custSR.ReadLine();
Array.Resize(ref cName, cName.Length + 1);
cName[cName.Length - 1] = line;
counter++;
line = custSR.ReadLine();
phoneComboBox.Items.Add(cPhone[cPhone.Length - 1]);
}
custSR.Close();
/*string changeAll = string.Join(Environment.NewLine, cPhone);
string allOthers = string.Join(Environment.NewLine, cName);
MessageBox.Show(changeAll + allOthers);*/
//focus when program starts
phoneComboBox.Focus();
}
In the if you are comparing text strings, so you should use the function ".Equals" in stead of
"=="
if(phoneComboBox.Text.Equals(cPhone[index]))
{
nameTextBox.Text = cName[phoneComboBox.SelectedIndex];
}
You don't need to check the condition, just get the selected index:
nameTextBox.Text = cName[phoneComboBox.SelectedIndex];
and in WPF you have SelectionChanged.
SelectedIndexChanged is for winform.
Best Practice:
But I would suggest you a better way to achieve this using Tag property. You wont have to change a lot of code for it.
//Create "ComboBoxItem" instead of "array"
while (line != null)
{
//initialize
ComboBoxItem cmItem = new ComboBoxItem();
//set Phone as Display Text
cmItem.Content = line; //it is the Display Text
//get Name
line = custSR.ReadLine();
//set Tag property
cmItem.Tag = line; //it is the attached data to the object
//add to "Items"
phoneComboBox.Items.Add(ComboBoxItem);
}
and now its very simple to get the selected item in SelectionChanged event:
void phoneComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
nameTextBox.Content = (e.AddedItems[0] as ComboBoxItem).Tag;
}
You don't need to handle those arrays anymore.
Thanks for the other answers, this is the answer I came up with that works. Fixes the indexOutOfRange exception I was getting.
private void phoneComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (phoneComboBox.SelectedIndex != -1)
{
nameTextBox.Text = cName[phoneComboBox.SelectedIndex];
}
else
{
nameTextBox.Text = string.Empty;
}
}
I have a CheckBoxList which I'm populating with data. When I attempt to retrieve the checked items from the list I can only grab the item ordinal, I cannot get the value.
I've read that you can use Items[i].Value however when I try to do this I get an error stating that there is no extension method 'value'.
Here's the code I'm using to try and grab the information (note the GetItemText(i) actually only gives me the item position, not the text for the item)
private void btnGO_Click(object sender, EventArgs e)
{
for (int i = 0; i < chBoxListTables.Items.Count; i++)
{
if (chBoxListTables.GetItemChecked(i))
{
string str = chBoxListTables.GetItemText(i);
MessageBox.Show(str);
//next line invalid extension method
chBoxListTables.Items[i].value;
}
}
}
This is using .Net 4.0
Any thoughts would be appreciated...thanks
This ended up being quite simple. chBoxListTables.Item[i] is a string value, and an explicit convert allowed it to be loaded into a variable.
The following code works:
private void btnGO_Click(object sender, EventArgs e)
{
for (int i = 0; i < chBoxListTables.Items.Count; i++)
{
if (chBoxListTables.GetItemChecked(i))
{
string str = (string)chBoxListTables.Items[i];
MessageBox.Show(str);
}
}
}
Try to use this.
for (int i = 0; i < chBoxListTables.Items.Count; i++)
{
if (chBoxListTables.Items[i].Selected)
{
string str = chBoxListTables.Items[i].Text;
MessageBox.Show(str);
var itemValue = chBoxListTables.Items[i].Value;
}
}
The "V" should be in CAPS in Value.
Here is another code example used in WinForm app and runs properly.
var chBoxList= new CheckedListBox();
chBoxList.Items.Add(new ListItem("One", "1"));
chBoxList.Items.Add(new ListItem("Two", "2"));
chBoxList.SetItemChecked(1, true);
var checkedItems = chBoxList.CheckedItems;
var chkText = ((ListItem)checkedItems[0]).Text;
var chkValue = ((ListItem)checkedItems[0]).Value;
MessageBox.Show(chkText);
MessageBox.Show(chkValue);
to get the items checked you can use CheckedItems or GetItemsChecked. I tried below code in .NET 4.5
Iterate through the CheckedItems collection. This will give you the item number in the list of checked items, not the overall list. So if the first item in the list is not checked and the second item is checked, the code below will display text like Checked Item 1 = MyListItem2.
//Determine if there are any items checked.
if(chBoxListTables.CheckedItems.Count != 0)
{
//looped through all checked items and show results.
string s = "";
for (int x = 0; x < chBoxListTables.CheckedItems.Count; x++)
{
s = s + (x + 1).ToString() + " = " + chBoxListTables.CheckedItems[x].ToString()+ ", ";
}
MessageBox.Show(s);//show result
}
-OR-
Step through the Items collection and call the GetItemChecked method for each item. This will give you the item number in the overall list, so if the first item in the list is not checked and the second item is checked, it will display something like Item 2 = MyListItem2.
int i;
string s;
s = "Checked items:\n" ;
for (i = 0; i < checkedListBox1.Items.Count; i++)
{
if (checkedListBox1.GetItemChecked(i))
{
s = s + "Item " + (i+1).ToString() + " = " + checkedListBox1.Items[i].ToString() + "\n";
}
}
MessageBox.Show (s);
Hope this helps...
//Simple example code:
foreach (var item in YourCheckedListBox.CheckedItems)
{List<string>.Add(item);}
You can try this:-
string values = "";
foreach(ListItem item in myCBL.Items){
if(item.Selected)
{
values += item.Value.ToString() + ",";
}
}
values = values.TrimEnd(','); //To eliminate comma in last.
Instead of this:
CheckboxList1.Items[i].value;
Try This:
CheckboxList1.Items[i].ToString();
It worked for me :)
Try to use this :
private void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < chBoxListTables.Items.Count; i++)
if (chBoxListTables.GetItemCheckState(i) == CheckState.Checked)
{
txtBx.text += chBoxListTables.Items[i].ToString() + " \n";
}
}
You can initialize a list of string and add those items that are selected.
Please check code, works fine for me.
List<string> modules = new List<string>();
foreach(ListItem s in chk_modules.Items)
{
if (s.Selected)
{
modules.Add(s.Value);
}
}
This will do the trick for you:
foreach (int indexChecked in checkedListBox1.CheckedIndices)
{
string itemtxt = checkedListBox11.Items[indexChecked];
}
It will return whatever string value is in the checkedlistbox items.
I have an application which has to monitor 211 rods, and every 5 seconds it will update 2 ListBox controls, each one containing either the inserted rods or the removed ones. When I manually use the button for inserting/removing rods the code executes perfectly and the ListBoxes update properly. When I use the global button which inserts all 211 one of the ListBox controls stops working properly.
The code for ListBox update
bool IClear = true, RClear = true;
for (int foo = 0; foo < Rods.Count; foo++)
{
if (Rods[foo].State == RodState.Inserted)
{
UpdateRodList update = new UpdateRodList(UpdateIRodUI);
if (IClear)
{
InsertedRods.Dispatcher.BeginInvoke(update, System.Windows.Threading.DispatcherPriority.Normal, foo, true);
IClear = false;
}
else
{
InsertedRods.Dispatcher.BeginInvoke(update, System.Windows.Threading.DispatcherPriority.Normal, foo, false);
}
}
if (Rods[foo].State == RodState.Removed)
{
UpdateRodList update = new UpdateRodList(UpdateRRodUI);
if (RClear)
{
RemovedRods.Dispatcher.BeginInvoke(update, System.Windows.Threading.DispatcherPriority.Normal, foo, true);
RClear = false;
}
else
{
RemovedRods.Dispatcher.BeginInvoke(update, System.Windows.Threading.DispatcherPriority.Normal, foo, false);
}
}
}
The code for the insert button (the remove one is similar)
Int32[] RodsID = null;
bool bParsed = false;
if (RemovingRods_.Text.Contains("*"))
{
RodsID = new Int32[211];
for (int i = 0; i < 211; i++)
{
RodsID[i] = i;
}
RemovingRods_.Text = "";
bParsed = true;
}
if (RemovingRods_.Text.Contains("-"))
{
string stext = RemovingRods_.Text;
Int32 a = Int32.Parse(RemovingRods_.Text.Substring(0, RemovingRods_.Text.IndexOf("-")));
Int32 b = Int32.Parse(RemovingRods_.Text.Substring(RemovingRods_.Text.IndexOf("-") + 1));
RodsID = new Int32[b - a];
for (int i = 0; i < b - a; i++)
{
RodsID[i] = i + a;
}
RemovingRods_.Text = "";
bParsed = true;
}
if (!bParsed)
{
string[] RodsID_;
char[] split = { ' ' };
RodsID_ = RemovingRods_.Text.Split(split);
RemovingRods_.Text = "";
RodsID = new Int32[RodsID_.Length];
for (int i = 0; i < RodsID_.Length; i++)
{
RodsID[i] = Int32.Parse(RodsID_[i]);
}
}
foreach (int numb in RodsID)
{
if (Rods[numb].Type == "Control Rod")
{
ControlRod Rod = new ControlRod();
Rod.Number = numb;
Rod.RodState = RodState.Changing;
RemovingCRods.Add(Rod);
}
if (Rods[numb].Type == "Shortened Control Rod")
{
ShortenedControlRod Rod = new ShortenedControlRod();
Rod.Number = numb;
Rod.RodState = RodState.Changing;
RemovingSRods.Add(Rod);
}
if (Rods[numb].Type == "Automated Control Rod")
{
// Automated Rods -- NO MANUAL CONTROL
}
}
And the global button code
try
{
Int32[] RodsID = null;
string text = "0-211";
RodsID = new Int32[211];
for (int i = 0; i < 211; i++)
{
RodsID[i] = i;
}
foreach (int numb in RodsID)
{
if (Rods[numb].Type == "Control Rod")
{
ControlRod Rod = new ControlRod();
Rod.Number = numb;
Rod.RodState = RodState.Changing;
InsertingCRods.Add(Rod);
}
if (Rods[numb].Type == "Shortened Control Rod")
{
ShortenedControlRod Rod = new ShortenedControlRod();
Rod.Number = numb;
Rod.RodState = RodState.Changing;
InsertingSRods.Add(Rod);
}
if (Rods[numb].Type == "Automated Control Rod")
{
AutomatedControlRod Rod = new AutomatedControlRod();
Rod.Number = numb;
Rod.RodState = RodState.Changing;
InsertingARods.Add(Rod);
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
What happens is when I press the global one, the Removed Rods ListBox will have all the rods as it should, and the Inserted Rods ListBox will contain the rods that were inserted before I pressed the button. It's as if when I pressed this button, this control doesn't update. P.S. If I remove rods manually using the button or insert it works perfectly.
As for the code requested by Marko:
private void UpdateIRodUI(Int32 foo, Boolean clear)
{
if (clear)
{
InsertedRods.Items.Clear();
}
InsertedRods.Items.Add(Rods[foo].Number + " : " + Rods[foo].Type + " (" + foo.ToString() + ")");
}
private void UpdateRRodUI(Int32 foo, Boolean clear)
{
if (clear)
{
RemovedRods.Items.Clear();
}
RemovedRods.Items.Add(Rods[foo].Number + " : " + Rods[foo].Type + " (" + foo.ToString() + ")");
}
Update: I have put the update ListBox code in a seperate function and took Marko's advice and also put in a function the InsertRods. Everything works fine now, but it seems that after I press the "emergency" button the InsertedRods ListBox updates and works just fine but RemovedRods just stops updating, unless I do it manually (it's supposed to update every 5 seconds through a Tick event). I even tried inserting all the rods, updating the ListBoxes and the clearing the "faulty" ListBox and still nothing, same result.
I just took a quick glance of your posted code without focusing very deeply on it and a couple of questions popped into mind:
1) You posted your code for ListBox update, but it's unclear from the other two code pieces that where do you call the ListBox update method?
2) The code that you posted for "insert button" looks more like the code from the "remove button", because of Removing_Rods.Add()... But why do you duplicate your insert/remove button code in your global button code? Why not have an insert method, that both the insert button and global (insert) button call? And the same for remove. If you need to slightly alter the code based on whether the caller is the insert button or the global button, you can pass in a variable and check it inside the insert method.
3) Have you tried debugging your code? As in whether the listbox update method is called when the global button code is executed...