Code:-
public partial class Players : Form
{
public TextBox[] spelers = new TextBox[7];
List<string> spelersSpel = new List<string>();
public Form1 game = new Form1();
public Players()
{
InitializeComponent();
spelers[0] = inputSpeler1;
spelers[1] = inputSpeler2;
spelers[2] = inputSpeler3;
spelers[3] = inputSpeler4;
spelers[4] = inputSpeler5;
spelers[5] = inputSpeler6;
}
private void btnSpelers_Click(object sender, EventArgs e)
{
for (int i = 0; i < spelers.Length; i++)
{
if (spelers[i] != null)
spelersSpel.Add(spelers[i].Text);
}
foreach (TextBox item in spelers)
{
if (item != null)
spelersSpel.Add(item.Text);
}
MessageBox.Show(spelersSpel.Count.ToString());
game.ShowDialog();
}
}
I've got 6 textboxes that I've put into an array. Then I want to put this array into a form. Because I don't know how much input I get from the textboxes I don't use an array. But when I want to see how big my list is. It's saying 6. If I only type text in the first textbox the list should be 1.
What am I doing wrong?
You can get the input count by this way:
spelersSpel.Clear();
foreach (TextBox item in spelers)
{
if (item != null && item.Text.Trim() != "") //check if null or empty
spelersSpel.Add(item.Text);
}
Because (spelers[i] != null) and (item != null) does not check whether the textboxes are blank; It means the array element is null or not.
If you want to check whether your textbox is blank, you should find property Text;
if (item.Text != "")
I'm not able to use my IDE and it is not sure, but try this.
public partial class Players : Form
{
public TextBox[] spelers = new TextBox[6]; // [7];
List<string> spelersSpel = new List<string>();
public Form1 game = new Form1();
public Players()
{
InitializeComponent();
spelers[0] = inputSpeler1;
spelers[1] = inputSpeler2;
spelers[2] = inputSpeler3;
spelers[3] = inputSpeler4;
spelers[4] = inputSpeler5;
spelers[5] = inputSpeler6;
}
private void btnSpelers_Click(object sender, EventArgs e)
{
/*
// 1.
for (int i = 0; i < spelers.Length; i++)
{
if (spelers[i] != null) {
throw new Exception("NullTextBoxException");
}
else if (spelers[i].Text == "") {
// skip when the textbox is empty
continue;
}
spelersSpel.Add(spelers[i].Text);
}
*/
foreach (TextBox item in spelers)
{
if (item != null) {
// throw exception when referring textbox is null
throw new Exception("NullTextBoxException");
}
else if (item.Text == "") {
// skip when the textbox is empty
continue;
}
spelersSpel.Add(item.Text);
}
MessageBox.Show(spelersSpel.Count.ToString());
game.ShowDialog();
}
}
You are confusing the TextBox object with its Text property.
If I understand correctly you want the List<string> to contain only the text for the textboxes that are not empty, so your code should be something like this
spelersSpel.Clear();
foreach (TextBox item in spelers)
{
if (item != null && !string.IsNullOrWhiteSpace(item.Text))
spelersSpel.Add(item.Text);
}
Notice that you declare the array to contain 7 TextBoxes (index from 0 to 6) but you add only 6 textboxes to it, so you need always this check for NULL because, when you loop over your elements, you have a NULL entry in your array at index 6. So, perhaps, if you have only 6 textboxes it is better to declare the array with
public TextBox[] spelers = new TextBox[6];
Next, in the click event, you execute two loops to fill the list, this of course will duplicate the list content.
However, I think that a better approach is to use directly a List<TextBox>, work with it and get rid of the array and the List<string>
public partial class Players : Form
{
public List<TextBox> spelers;
public Form1 game = new Form1();
public Players()
{
InitializeComponent();
spelers = new List<TextBox>()
{
inputSpeler1, inputSpeler2, inputSpeler3,
inputSpeler4, inputSpeler5, inputSpeler6
}
}
private void btnSpelers_Click(object sender, EventArgs e)
{
MessageBox.Show(spelers
.Count(x => !string.IsNullOrWhiteSpace(x.Text))
.ToString());
game.ShowDialog();
}
}
Related
I'm working with Windows Forms in C# and I have a Character object that's being generated from user input from one form and then passed back into the Main Form via a custom event handler.
The new object is then to be added to a List on the main form. However, when a new item is added to the list on the main form, it also replaces all of the other items in the list, so I end up with a list of all identical objects.
Here's the code where I'm trying to add the new object to the list.
private void HandleCharacterCreated(object sender, EventArgs e)
{
CharCreatorForm extractForm = sender as CharCreatorForm;
characterList.Add(extractForm.NewCharacter);
Debug.WriteLine("NEW LINE");
foreach (Character character in characterList)
{
Debug.WriteLine(character);
}
SetCharacterCountValue();
if (CharacterAdded != null)
{
CharacterAdded(this, new EventArgs());
}
}
If it helps, here is the block of code from the input form that is then passed back over to the main form to be added to the list.
public void CreateCharacter()
{
newCharacter.Name = nameTextBox.Text;
newCharacter.Level = levelPicker.Value;
newCharacter.Race = racePicker.Text;
newCharacter.Class = classPicker.Text;
if (goodRadioBtn.Checked == true && evilRadioBtn.Checked == false)
{
newCharacter.Alignment = 1;
}
else if(evilRadioBtn.Checked == true && goodRadioBtn.Checked == false)
{
newCharacter.Alignment = 2;
}
newCharacter.ImageIndex = classPicker.SelectedIndex;
if (CharacterCreated != null)
{
CharacterCreated(this, new EventArgs());
}
ClearFields();
}
CreateCharacter() is not newing up a new Character, but rather it is just setting new property values on an existing object.
Since class objects are reference objects, you are adding the same "reference" to your list over and over and each time mutating (changing properties) the single object in memory that the pointers point at.
Simple fix is to just create a new Character in your CreateCharacter() method:
public void CreateCharacter()
{
newCharacter = new Character(); // <-- here.
newCharacter.Name = nameTextBox.Text;
newCharacter.Level = levelPicker.Value;
newCharacter.Race = racePicker.Text;
newCharacter.Class = classPicker.Text;
// ... etc
}
I'm having problems in passing the values of the array.
I created an array in a class, then I instantiate it in frmMain(form1) then i put some values in the array(I signed up I put username and password in the array). frmMain should pass the values in the the array right?
My problem is when I instantiate the class(which holds the array) in frmProfile(form2) its like i never put some values in it.
In short, I want the array to be accessible in all forms. Do I need a constructor method?(something like get; set;?).
public class Tagasalo //this is the class i created
{
public String[,] array = new String[5, 2];
}
heres my code in frmMain(form1)
Tagasalo arr = new Tagasalo();
frmProfile profile = new frmProfile();
int row;
bool validInput = true;
int tries = 3;
public frmMain()
{
InitializeComponent();
}
public void btnSignUp_Click(object sender, EventArgs e)
{
if (txtUsernameS.Text.Trim() == String.Empty)
{
errorProvider1.SetError(txtUsernameS, "Please put a Username.");
}
else if (txtUsernameS.TextLength > 1 && txtUsernameS.TextLength < 4)
{
errorProvider1.SetError(txtUsernameS, "Your Username must have 4 or more characters.");
}
else
{
errorProvider1.Clear();
}
if (txtPasswordS.Text == String.Empty)
{
errorProvider2.SetError(txtPasswordS, "Please put a Password.");
}
else if (txtPasswordS.TextLength > 1 && txtPasswordS.TextLength < 6)
{
errorProvider2.SetError(txtPasswordS, "Your Password must have 6 or more characters.");
}
else
{
errorProvider2.Clear();
}
for (row = 0; row < 5; row++)
{
if (txtUsernameS.TextLength >= 4 && txtPasswordS.TextLength >= 6)
{
if (txtConfirmPassword.Text != txtPasswordS.Text)
{
errorProvider3.SetError(txtConfirmPassword, "Your Password does not match.");
}
else if (txtConfirmPassword.Text == txtPasswordS.Text)
{
if (arr.array[row, 0] == null && arr.array[row, 1] == null)
{
arr.array[row, 0] = txtUsernameS.Text;
arr.array[row, 1] = txtPasswordS.Text;
MessageBox.Show("Signed-Up Successfully!");
break;
}
else if(txtUsernameS.Text == arr.array[row,0])
{
MessageBox.Show("Username already Used.");
break;
}
}
}
}
if (row > 5)
{
MessageBox.Show("Sorry, maximum number of accounts has been reached.");
}
}
here's my code in frmProfile(form2)- In this form I just want the label to show the username of the user.
Tagasalo arr = new Tagasalo();
int row;
public frmProfile()
{
InitializeComponent();
}
private void changePasswordToolStripMenuItem_Click(object sender, EventArgs e)
{
frmChangePassword changepass = new frmChangePassword();
changepass.Show();
this.Hide();
}
private void logOutToolStripMenuItem_Click(object sender, EventArgs e)
{
frmMain logout = new frmMain();
logout.Show();
this.Hide();
}
public void frmProfile_Load(object sender, EventArgs e)
{
for (row = 0; row < 5; row++ )
{
if(arr.array[row,0] == arr.array[row,1])
{
lblUsername.Text = arr.array[row, 0];
break;
}
}
}
then, i want to change the password. replace the value of the array and when i log-out the array is empty again. I cant log-in again with the same account.
Tagasalo arr = new Tagasalo();
public frmChangePassword()
{
InitializeComponent();
}
private void btnSaveChanges_Click(object sender, EventArgs e)
{
if (txtCurrentPassword.Text == String.Empty)
{
errorProvider1.SetError(txtCurrentPassword, "Please type your Current Password.");
}
else
{
errorProvider1.Clear();
}
if (txtNewPassword.Text == String.Empty)
{
errorProvider2.SetError(txtNewPassword, "Please type your New Password.");
}
else
{
errorProvider2.Clear();
}
if (txtConfirmNewPassword.Text != txtNewPassword.Text)
{
errorProvider3.SetError(txtConfirmNewPassword, "Re-type your New Password.");
}
else
{
errorProvider3.Clear();
}
if(txtCurrentPassword.Text != String.Empty && txtNewPassword.Text != String.Empty && txtConfirmNewPassword.Text == txtNewPassword.Text)
{
MessageBox.Show("Changed Password Successfully!");
frmProfile profile = new frmProfile();
profile.Show();
this.Hide();
}
}
private void btnCancel_Click(object sender, EventArgs e)
{
frmProfile profile = new frmProfile();
profile.Show();
this.Hide();
}
Sorry if it's too long. I've been searching the net for days after school and I cant find the answer.
What do you mean with "you want the variable accessible in all forms" ?
To acess variables from another class you have to write classname.variablename to access them, for your example this would be:
Tagasalo.array ... do stuff ...
If you want to create a class which describes variables and/or methods of objects you create via the constructor of this class and then access those I would recommend reading about "Classes", "Objects", "Instances" first and if this does not help you ask with this knowledge again.
Another thing that might be helpfull: If you want a class which describes variables and/or methods and the rest of your application shall be able to just create one single and only instance of this class reading about "Singleton-classes".
Hope this helps, specify what you want to do and I might be able to help you more specific.
In all honesty, I wouldn't recommend using a global variable, as it uses unnecessary resources.
However,
What you are explaining/describing is a global variable. If you are using windows forms (which I think you are), you can create a class (right click on your project name>add>class). Call it 'MyArrayClass'.
Then (as you have already said) use the constructor MyArray(){get;set}
You can then access it via : MyArrayClass.MyArray[i] where [i] is the index you want.
I'll edit this post once I find some good documentation as well.
EDIT: This works great (since you are new) : http://www.dotnetperls.com/global-variable.
Just pass it in the constructor of Form2:
Form2 form2 = new Form2(arr);
form2.ShowDialog();
Then in the Form2 constructor:
public Form2(List<double> arr)
{
//do stuff with it here
}
EDIT 2: For what you are doing, this would be better for you: http://codemyne.net/articles/asp/creating-a-simple-registration-or-signup-and-login-or-signin-form-using-asp.net-and-sqlserver.aspx?visitid=171&type=2
Edit 3
static class Global
{
private static string _globalVar = "";
public static string GlobalVar
{
get { return _globalVar; }
set { _globalVar = value; }
}
}
and for using any where you can write:
GlobalClass.GlobalVar = "any string value"
This was used for a string value.
I want to get all the control from multiple form (Main, Two and Three) and
compare if the control tag equals the variable str_name and if true write the
value of str_value in c.Text.
the code:
private static Form[] getformular()
{
Main main = new Main();
Two f2 = new Two();
Three f3 = new Three();
Form[] form = { main, f2, f3};
return form;
}
private void initcontrol()
{
String str_name = "name";
String str_value = "value";
foreach(Form f in getformular())
{
foreach (Control c in f.Controls)
{
if (f != null && c = null)
{
if (c.Tag.Equals(str_name))
{
c.Text = str_value;
}
}
}
}
}
Could please someone help me?
First, as stated by #JonB some of conditional checking (ifs logic) in your current code seems off.
Second, looping through Form.Controls will only bring you all controls placed directly in the Form. For example if you have tab control (or any other container control) placed in form, and you have a textbox inside that tab control, you'll get only the tab control and couldn't find the textbox by looping through Form.Controls. You can solve that with recursive method as demonstrated below.
private void initcontrol()
{
String str_name = "name";
String str_value = "value";
var result = false;
foreach(Form f in getformular())
{
//if you want to check if f null, it should be here.
if(f != null) result = setControlText(f, str_name, str_value);
}
if(!result) MessageBox.Show("Control not found");
}
private bool setControlText(Control control, string str_name, string str_value)
{
var isSuccess = false;
foreach (Control c in control.Controls)
{
//if c is not null
if (c != null)
{
//check c's Tag, if not null and matched str_name set the text
if (c.Tag != null && c.Tag.Equals(str_name))
{
c.Text = str_value;
isSuccess = true;
}
//else, search in c.Controls
else isSuccess = setControlText(c, str_name, str_value);
//if control already found and set, exit the method now
if (isSuccess) return true;
}
}
return isSuccess;
}
C# - 2.0
I am trying to figure out on how to do a loop on a list of controls with certain names: "txtTesting[i]"
txtTesting1
txtTesting2
txtTesting3 ...
txtTesting13
With the code I have a total of 13. But this can change as time goes by. So I am looking to get the data from the textboxes that have data in them. I just can not seem to figure out a way to do a count of the controls. I have tried this...
for (int i = 1; i < 13; i++)
{
if (txtTesting[i].text != "")
{
//
}
}
I am also getting this error...
Error 51 The name 'txtTesting' does not exist in the current context
Unless I am missing something here.
System.Web.UI.WebControls.TextBox
Assuming this is a System.Windows.Forms application, you should be able to go through all your controls on the form and then select the ones that are TextBox as follows:
foreach (System.Windows.Forms.Control control in this.Controls)
{
if (control is System.Windows.Forms.TextBox)
{
if (((System.Windows.Forms.TextBox)control).Text != "")
{
// Do something
}
}
}
For an asp.net application this would be very similar:
foreach (System.Web.UI.Control control in this.Controls)
{
if (control is System.Web.UI.WebControls.TextBox)
{
if ((System.Web.UI.WebControls.TextBox)control).Text != "")
{
// Do something
}
}
}
txtTesting looks like an array. does it have a Length property?
for (int i = 1; i < txtTesting.Length; i++)
if it's a type List<T> than maybe it has a Count property
for (int i = 1; i < txtTesting.Count; i++)
If you don't already have an array, you can initialize one in your presumed Form's constructor
List<WhateverTypeTxtTestingIs> txtTesting = new List<WhateverTypeTxtTestingIs>();
txtTesting.Add(txtTesting1);
txtTesting.Add(txtTesting2);
...
The most efficient way would be to add the controls to an array and loop over that, but you could also loop through the controls and inspect the control's Name:
foreach(Control c in this.Controls) // <-- "this" may not be appropriate - you just need to reference the containing control
{
if(c.Name.StartsWith("txtTesting")
{
///
}
}
In your constructor, after the call to InitializeComponent, stuff the text boxes in a collection.
// class-scoped variable
private List<Textbox> _boxen = new List<TextBox>();
public MyFormDerp()
{
InitializeComponent();
_boxen.Add(txtTesting1);
// etc
_boxen.Add(txtTesting13);
}
and, later on...
foreach(TextBox box in _boxen)
if (box.text != "")
{
//
}
Also, your design should make you itch.
You can use a foreach over your array:
foreach (TextBox txt in txtTesting)
{
if (txt.text != "")
{
//
}
}
Or, the array has a length property that you can use.
for (int i = 1; i < txtTesting.length; i++)
{
if (txtTesting[i].text != "")
{
//
}
}
If you don't have an array of controls, you may want to look at this answer to loop through all the controls on your form. Except the generic Dictionary isn't in C# 2, so it will look more like this:
private void button1_Click(object sender, EventArgs e)
{
ArrayList txtTesting = ArrayList();
LoopControls(controls, this.Controls);
foreach (TextBox txt in txtTesting)
{
if (txt.text != "")
{
//
}
}
}
private void LoopControls(ArrayList list, Control.ControlCollection controls)
{
foreach (Control control in controls)
{
if (control is TextBox && control.Name.StartsWith("txtTesting"))
list.Add(control);
if (control.Controls.Count > 0)
LoopControls(list, control.Controls);
}
}
I have a textbox in my form for user to key in an item code.
When the focus of the textbox is lost, it will look into the database to check if the item code exists or not.
However, I am getting infinite loop when I try to lose focus by clicking on other textboxes.
private void txtICode_LostFocus(object sender, RoutedEventArgs e)
{
if (txtICode.IsFocused != true)
{
if (NewData)
{
if (txtICode.Text != null)
{
if (txtICode.Text != "")
{
Item temp = new Item();
Item[] list = temp.Query(new object[] { Item.DataEnum.Item_Code }, new string[] { txtICode.Text });
if (list.Length > 0)
{
System.Windows.Forms.MessageBox.Show("This item code is already being used.", "Invalid information");
txtICode.Focus();
return;
}
}
}
}
}
}
The txtICode.IsFocused is set to true every time after the end of the method and the loop just continues forever.
I tried removing txtICode.Focus(); but it makes no difference.
Is there anything wrong with my code?
I am using .Net 3.5 and WPF for my form.
You do not have to restore focus to TextBox in the LostFocus event.
remove these 2 lines :
txtICode.Focus();
return;
You could implement code more clean & readable way :
private void txtICode_LostFocus(object sender, RoutedEventArgs e)
{
if (!NewData)
return;
if (String.IsNullOrEmpty(txtICode.Text))
return;
Item temp = new Item();
Item[] list = temp.Query(new object[] { Item.DataEnum.Item_Code }, new string[] { txtICode.Text });
if (list.Length > 0)
{
System.Windows.Forms.MessageBox.Show("This item code is already being used.", "Invalid information");
}
}
private void txtICode_LostFocus(object sender, RoutedEventArgs e)
{
string inputText = txtICode.Text;
if (string.IsNullOrEmpty(inputText) || !NewData)
{
return;
}
Item temp = new Item();
Item[] list = temp.Query(new object[] { Item.DataEnum.Item_Code },
new string[] { inputText });
if (list != null && list.Length > 0)
{
MessageBox.Show("This item code is already being used.", "Invalidinformation");
txtICode.Focus();
return;
}
}
You can use BeginInvoke Method to execute asynchronously:
private void txtICode_LostFocus(object sender, RoutedEventArgs e)
{
txtICode.Dispatcher.BeginInvoke(() => {
if (txtICode.IsFocused != true)
{
if (NewData)
{
if (txtICode.Text != null)
{
if (txtICode.Text != "")
{
Item temp = new Item();
Item[] list = temp.Query(new object[] { Item.DataEnum.Item_Code }, new string[] { txtICode.Text });
if (list.Length > 0)
{
System.Windows.Forms.MessageBox.Show("This item code is already being used.", "Invalid information");
txtICode.Focus();
return;
}
}
}
}
});
}