Comparing TextBox values without arrays. C# - c#

I have a basic program with 26 TextBoxes named textBox1 to textBox26 and a button. The button currently gives a value of 1,x or 2 to each TextBox. I also want it to compare the values of a TextBox and the one with a name contaning a number 13 greater than the last without using an array or multiple if/else statements. For example I want to compare textBox1 with textBox14. I currently have this code:
Random r = new Random();
int ran;
int x;
int y;
private void button1_Click(object sender, EventArgs e)
{
foreach (Control b in this.Controls.OfType<TextBox>())
{
ran = r.Next(1, 4);
if (ran == 1)
{
b.Text = "1";
}
else if (ran == 2)
{
b.Text = "x";
}
else if (ran == 3)
{
b.Text = "2";
}
x = b.TabIndex;
y = x + 13;
var box = (TextBox)this.Controls.Find("textBox" + x.ToString());
var box1 = (TextBox)this.Controls.Find("textBox" + y.ToString());
box.Text = box1.Text;
}
}
This gives the the error message:
There is no argument given that corresponds to the required formal parameter 'search Children' of 'Control.ControlCollection.Find(string, bool)'
on the lines with:
var box = (TextBox)this.Controls.Find("textBox" + x.ToString());
var box1 = (TextBox)this.Controls.Find("textBox" + y.ToString());

Your specific error is because you're not providing a value for the argument (as the error states...):
var box = (TextBox)this.Controls.Find("textBox" + x.ToString(), false);
Use false, as in my example, or true depending on your needs. Do you want the search to include controls (i.e. children) that are nested inside the controls you are searching?

Related

check if linq operation is null before execution C#

I have a Win-form with 60 Radio-buttons. I want to get the Text from the checked radio-buttons with this code:
private void button1_Click_1(object sender, EventArgs e)
{
string[] boxes = new string[30];
string[] names = new string[30];
for (int i = 1; i < boxes.Length; i++)
{
var label = this.Controls.Find("lb" + i, true)[0];
var panelcontr = this.Controls.Find("panel" + i, true)[0] as Panel;
var panels = panelcontr;
var p = panels.Controls.OfType<RadioButton>()
.FirstOrDefault(r => r.Checked).Text;
boxes[i] += p;
names[i] += label.Text;
tobeWritten += names[i] + boxes[i] + ",";
textBox1.Text = "Anamnese(" + tobeWritten + ")";
}
}
It works totally fine but the problem is, when just one radio-box is unchecked I get a warning during Debug. I know why the Warning appears but I want the Program not to stop.
What I'm asking is: Is it possible to create a MessageBox which appears, when I haven't checked a radioButton which e.g. says "You have to assign every button". I click the "OK"-Button and I am able to check the unchecked Button.
I tried with the suggestions from an other question at StackOverflow but no success because the function panels.Controls.OfType<RadioButton>() gets executed before the query.
You get a NullReferenceException here if there is no checked RadioButton:
var p = panels.Controls.OfType<RadioButton>()
.FirstOrDefault(r => r.Checked).Text;
Because FirstOrDefault returns null since RadioButton is a reference type. Then you can't access it's Text property. So how to avoid that?
Store the result and check if it's null before you use it:
RadioButton firstCheckedRadioButton = panels.Controls.OfType<RadioButton>()
.FirstOrDefault(r => r.Checked);
if(firstCheckedRadioButton != null)
{
string text = firstCheckedRadioButton.Text;
// ...
}
Your issue is here:
var p = panels.Controls.OfType<RadioButton>()
.FirstOrDefault(r => r.Checked).Text;
If the result of the FirstOrDefault call is null, the Text call will throw a null reference exception. You can avoid this by splitting up the calls, so that you call FirstOrDefault, check whether the result is null, and then call Text only once you know the result is not null.
Would it help to replace
var p = panels.Controls.OfType<RadioButton>()
.FirstOrDefault(r => r.Checked).Text;
with
var ch = panels.Controls.OfType<RadioButton>()
.FirstOrDefault(r => r.Checked);
if (ch == null)
{
// show message box and break;
}
var p = ch.Text;
It works now with this code:
private void button1_Click_1(object sender, EventArgs e)
{
string[] boxes = new string[30];
string[] names = new string[30];
for (int i = 1; i < boxes.Length; i++)
{
var label = this.Controls.Find("lb" + i, true)[0];
var panelcontr = this.Controls.Find("panel" + i, true)[0] as Panel;
var panels = panelcontr;
var radiobutton = panels.Controls.OfType<RadioButton>()
.FirstOrDefault(r => r.Checked);
if(radiobutton==null)
{
MessageBox.Show("Check all Buttons!");
break;
}
boxes[i] += radiobutton.Text;
names[i] += label.Text;
tobeWritten += names[i] + boxes[i] + ",";
textBox1.Text = "Anamnese(" + tobeWritten + ")";
}
}

c# windows form application dynamic objects value

i have made a mistake of re-inventing the wheel. There are options
but somehow i like the feel of this.
Sorry but don't have enough rep to post an image.
This is how the form looks like:
SNO.-------ITEMS--------FROM--------TO---------QUANTITY // labels
[ 1 ]-------[-----------▼]---[--------]----[--------]------[-------------] {NEW} {DELETE} //textboxes and buttons
I've got the 'new' button click event to generate a row, and serial number to be automatic
and inserted the items into the collections from Properties panel.
Delete button deletes an entire row and shifts both the button up on Y position.
I need to assign the value of quantity [(TO - FROM ) + 1] in the QUANTITY text boxes,
for which i have the code as :
public void print_quant(object Sender, EventArgs e)
{
TextBox quanty;
quanty = (TextBox)this.Controls.Find("QUANTITY" + (count), true)[0];
calculate_quant(this, e);
quanty = result;
}
public static string result;
public string calculate_quant(object sender, EventArgs e)
{
TextBox sfrom;
sfrom = (TextBox)this.Controls.Find("SFRM" + count, true)[0];
TextBox sto;
sto = (TextBox)this.Controls.Find("STO" + count, true)[0];
TextBox quan;
quan = (TextBox)this.Controls.Find("QUANTITY" + count, true)[0];
//if (!string.IsNullOrEmpty(sfrom.Text) && !string.IsNullOrEmpty(sto.Text))
{
int to = Convert.ToInt32(sto.Text);
int from = Convert.ToInt32(sfrom.Text);
int quantity = (to - from) + 1;
result = quantity.ToString();
quan.Text = result;
}
return result;
}
count is initialized at 1 on form load, keeps increasing with number of rows
the same code works in the delete row method
public void delete_row(object sender, EventArgs e) //function to delete a row
{
TextBox snum;
snum = (TextBox)this.Controls.Find("SNO"+count, true)[0];
snum.Dispose();
...//delete other row elements
}
please help me figure out why it doesnt work for the print_quant / calculate_quant methods
I made some changes to your code. I changed the return on your calculate method to a string, and added a quanty.Text=calculatemethod line to your print method
public void print_quant(object Sender, EventArgs e)
{
TextBox quanty;
quanty = (TextBox)this.Controls.Find("QUANTITY" + (count), true)[0];
//add this line
quanty.Text = calculate_quant(this, e).ToString();
}
public static string result;
//change this
//public void calculate_quant(object sender, EventArgs e)
//to
public string calculate_quant(object sender, EventArgs e)
{
TextBox sfrom;
sfrom = (TextBox)this.Controls.Find("SFRM" + count, true)[0];
TextBox sto;
sto = (TextBox)this.Controls.Find("STO" + count, true)[0];
//this isn't being used here
//TextBox quan;
//quan = (TextBox)this.Controls.Find("QUANTITY" + count, true)[0];
//if (!string.IsNullOrEmpty(sfrom.Text) && !string.IsNullOrEmpty(sto.Text))
{
int to = Convert.ToInt32(sto.Text);
int from = Convert.ToInt32(sfrom.Text);
int quantity = (to - from) + 1;
return quantity.ToString();
}
}
Edit
try this.
Create a usercontrol and make it look exactly like one of your rows.
add a property variable for each of the boxes
//whenever you Sno="something" the textbox will automatically be updated.
private string _Sno="00000";
public string Sno{get{return _Sno;}set{_sno=value; SnoTextBox.Text=value;}}
do this for each of your textboxes.
on your main form now you can add a flowpanel, they a bit tricky at first. when you add your new Usercontrol to it, they will automatically be added from the top down, or up, or however you set it up.
When you want to add a new row, just add your new Usercontrol to the flowpanel
FlowPanel flowPanel =new FlowPanel();
FlowPanel.Controls.Add(new myUserControl());
to delete
FlowPanel.Controls.RemoveAt(2);
This is really poorly written, but I am out of time. Either ignore me altogether, or try to figure it out. Sorry I couldn't be more help.
this worked for me
private void textBox_TextChanged(object sender, EventArgs e)
{
TextBox quant;
int x = count - 1;
string num = Convert.ToString(x);
quant = (TextBox)this.Controls.Find("QUANTITY" + x , true)[0];
TextBox to = (TextBox)this.Controls.Find("STO" + x, true)[0];
TextBox from = (TextBox)this.Controls.Find("SFRM" + x, true)[0];
string tovalue = to.Text;
int to1 = Convert.ToInt32(tovalue);
string fromvalue = from.Text;
int from1 = Convert.ToInt32(fromvalue);
int result = (to1 - from1) + 1 ;
if (result > 0)
{
string result1 = Convert.ToString(result);
quant.Text = result1;
}
}
after adding
STO.TextChanged += new System.EventHandler(textBox_TextChanged);
at the function that was generating the boxes where i needed to calculate :)

How to insert Text into Textboxes created during runtime (WFA)

I want to insert text into textboxes creating during run time
user can decide how many textboxes will create (range 1-99) I am using this code to create textboxes
for (int i = 0; i < Calculation.Num; i++)
{
TextBox txtRun = new TextBox();
txtRun.Name = "txtBox" + i;
txtRun.Location = new System.Drawing.Point(35, 50 + (20 * i) * 2);
txtRun.Size = new System.Drawing.Size(75, 25);
this.Controls.Add(txtRun);
}
Suppose user create 5 textboxes it will look like this
after that user insert numbers in each textbox then click calculate then all numbers stored in array using this code
Button btn = sender as Button;
if (btn.Name.Equals("btn1"))
{
var sum = this.Controls.OfType<TextBox>()
.Where(t => char.IsDigit(t.Name.Reverse().Take(1).FirstOrDefault())
&& t.Enabled)
.Select(t =>
{
double i;
if (!double.TryParse(t.Text, out i)) { return 0d; }
NumbersHolder[abc] = i;
abc++;
return i;
})
.Sum();
}
after that i want to calculate those numbers if number is between 70-76 replace that number with 2.75 if it is between 77-79 replace it with 3.0 if it is between 80-86 replace with 3.3 and if it is 87-100 replace with 4.0
A little confused by what you are asking.
You want the TextBox controls you are generating in the for loop to have values?
Just set
txtRun.Text = "your value";
before adding it.

Create control in runtime

I can't manage to get the values from textboxes that are created at run-time.
I want an user to choose something from a checkedlistbox, and to enter any values he wants in textboxes that are created at every button click.
How can I get the name of those texboxes? They really exist? I am a beginner and I really don't understand how they are created.
This is my code where I create textboxes.
private void checkedListBox1_SelectedIndexChanged(object sender, EventArgs e)
{
int x = 466;
int y = 84;
foreach (var itemChecked in checkedListBox1.CheckedItems)
{
int i = 0;
TextBox tb = new TextBox();
tb.Location = new Point(x, y);
tb.Name = "txtBox" + i++.ToString();
Controls.Add(tb);
y += 30;
}
just place the i outside the foreach and done.
int i = 0;
foreach (var itemChecked in checkedListBox1.CheckedItems)
{
i++;
string textBoxName = "textBox" + i.ToString();
TextBox tb = new TextBox();
tb.Location = new Point(x, y);
//tb.Name = "txtBox" + i++.ToString(); <--Your Version
tb.Name = textBoxName;
//...
//Other stuff or your codes
}
Rather than searching for exact name what you can do is have a string(fixed) which is searched for the control.
so if you find that string ( in your case which is 'textbox' ), what you can do is search for that fixed string in the name of control. if it exists then it's dynamically generated control.
foreach(Control c in parentControlIdOrName.Controls)
{
if(c.GetType()==typeof(TextBox))
{
if(((TextBox)c).Name.indexOf("textbox")!=-1)
{
// do your coding here...what ever you want....
}
}
}
Haven't tested but,Hope for the best. It might work.

Checking if both keys match isn't working right

This application works as if you were playing the lottery, you pick 5 numbers from a comboBox, click a button to generate the 5 key numbers and then you press another button to check the results (after you introduce the prize monei on the textbox below, AKA "prémio").
The button that does the checking is the highlighted one Verificar Prémio.
Here's it's code:
private void button5_Click(object sender, EventArgs e)
{
if (textBox1.Text != "" && textBox1.Text!="Prémio em €")
{
int contador = 0;
for (int i = 1; i <= 5; i++)
{
string posicao = i.ToString();
for (int c = 1; c <= 5; c++)
{
string poschave = c.ToString();
if (listBox1.Items.IndexOf(posicao) ==
listBox2.Items.IndexOf(poschave))
{
contador = contador + 1;
}
}
i = int.Parse(posicao);
double valor;
double premio = double.Parse(textBox1.Text);
if (contador == 5)
{
MessageBox.Show(" Parabens ganhou o 1º premio acertou 5 números
o seu prémio é de " + premio + "€");
}
else
{
if (contador == 4)
{
valor = premio * 0.75;
MessageBox.Show(" Acertou 4 numeros o seu premio é: " +
valor + "€");
}
else
{
if (contador == 3)
{
valor = premio * 0.5;
MessageBox.Show("Acertou 3 numeros o seu premio é: " +
valor + "€");
}
else
if (contador <= 2)
{
MessageBox.Show(" Infelizmente nao ganhou,
nada tente outra vez");
}
}
}
}
}
}
Whatever I do, it always shows the messageBox saying I got all 5 correct...
EDIT:
listBox1 is the one on the left, (3, 9, 17, 20, 10), you choose them from the combobox and when you Click "Apostar" it is added to it.
listBox2 is the box on the right.
EDIT2:
By replacing
for (int c = 1; c <= 5; c++)
{
string poschave = c.ToString();
if (listBox1.Items.IndexOf(posicao) == listBox2.Items.IndexOf(poschave))
{
contador = contador + 1;
}
}
with
foreach (var item in listBox1.Items)
{
// Convert it to string to avoid object reference comparison. Not 100%
// sure if this is needed
string value = item.ToString();
if (listBox2.Items.Contains(value))
contador++;
}
The error doesnt show anymore however it still isnt working properly, my guess is that the program is checking if they match, then get the result, therefore it always show "you won nothing" 5 times in a row...
How can I fix this?
I don't understand Spanish(?) so it's very hard to understand your code (please use english variable names, even if you have a localized UI)
However, one cause of the problem could be this line:
listBox1.Items.IndexOf(posicao) == listBox2.Items.IndexOf(poschave)
In case neither posicao or poschave is found in their respective listboxes, -1 will be returned and the expression will be true (i.e. contador will be incremented). I'm guessing this is not the desired behavior.
If you instead want to check if an item in the left listbox is also available in the right, then you could do:
void Button_Click(object sender, EventArgs e)
{
if (textBox1.Text == "" || textBox1.Text == "Prémio em €")
return;
int numMatches = 0;
foreach (var item in listBox1.Items)
{
if (listBox2.Items.Contains(item))
numMatches++;
}
// numMatches will now contain the number of elements in the left
// listbox that also exist in the right listbox
if (numMatches > 2)
{
double premio = Double.Parse(textBox1.Text);
double prize = 0;
if (numMatches == 5)
prize = premio * 1.0;
if (numMatches == 4)
prize = premio * 0.75;
else
prize = premio * 0.5;
// Use string.Format() instead to get fancier formatting of numbers
Messagebox.Show ("Sweet, you got " + numMatches + " out of 5 correct numbers. Your prize is " + prize + "€");
}
else
{
MessageBox.Show("Sorry, not enough matches - you win nothing!");
}
}
EDIT:
The reason you get 5 message boxes is because you have the call to Messagebox.Show() inside a for loop that loops five times. I've updated the code sample above to do what I think you want your button callback to do
Your source is way too complicated, you have two loops, one integer > string followed by string > integer... try this:
int count = 0;
for (int i = 0; i < 5; i++)
{
if (listBox2.Items.IndexOf(listBox1.Items[i]) > 0)
{
count++;
}
}
// count is 0 - 5
You only check for 5 numbers of the left ListBox if it is in the right ListBox.

Categories

Resources