Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I'm pretty new to the C# and while making my first program i'm facing a problem.
So I got 3 windows form (MyForm1; MyForm2 and MyForm3)
MyForm1 has 2 buttons (Available Account & Add a new account)
When i click one of these buttons it opens a new windows form.
In the Add a new Account form I have 2 TextBox (1 for the ID and 1 for the PWD + Button (Save) and i'd like the user to input his ID and PWD and save it so i can re-use it in the Available Account form but i have no clue how to that. I tried different things i saw on YT but nothing seems to works like i would
Thanks for your help <3 (Tell me if you want me to copy/paste some part of the code).
Edit:
Here are the sourcecodes of the mentioned forms.
Form1
Form2
Form3
I deleted all my failed attemps, so they are basics.
From your post it's hard to determine what you're trying to do. So. If you only want to pass values between forms, you could do something like this:
Add new account form:
public static bool AddNewAccount(out int id, out string password)
{
id = 0;
password = "";
AddNewAccountForm f = new AddNewAccountForm();
bool result = (f.ShowModal() == ModalResult.OK);
if(result)
{
id = f.GetId();
password = f.GetPassword();
}
f.Dispose();
return result;
}
and in main form:
int id;
string pass;
if(AddNewAccountForm.AddNewAccount(out id, out pass))
{
//here user clicked OK, so you can save to the database your id and password
}
else
{
//here user clicked Cancel
}
I assumed that there are two buttons on your AddNewAccountForm. One - OK and the other - Cancel. You have to set the modal result for these buttons.
So, how it works?
AddNewAccount method is static method, so you can call it from your main like:
AddNewAccountForm.AddNewAccount()
AddNewAccount method is going to create your form, show it modally and then assign values enetred by user to out parameters.
My code assumes also that your AddAccountForm has methods like:
int GetId()
{
return Convert.ToInt32(idTextBox.Text);
}
string GetPassword()
{
return passwordTextBox.Text;
}
Note that GetId is badly written, I wanted it to be clear. Now that you understand this method, conversion to int should look like that (TryParse is better way to convert string to int):
int GetId()
{
int id;
if(!int.TryParse(idTextBox.Text, out id))
return -1;
else
return id;
}
You can also "group" id and password in some structure. Code would be cleaner. But I don't think you need it now. However, if you are curious you can read about structures here: https://msdn.microsoft.com/en-us/library/aa288471%28v=vs.71%29.aspx?f=255&MSPPError=-2147217396
If you want to store values in database or files:
** Part about good practices and system engeneering **
You should really not save them using AddAccountForm. This class is to create account in your application (just the model) - not to save it. If you want to store these values(id and password) you should pass them to your main form - as I already showed you and then main form should save them - using another class which is responsible for data management. I am not giving any example, because I don't know if you really need it now.
To make your code really reusable, you should keep a strict separation between display (view) and the data.
You didn't mention that you had a database. This lack of mention is a start of this separation. Your problem would be similar if you just have a List of account, or a Dictionary, or maybe a text file containing the items you want to edit in your application.
So let's assume you want to edit a collection of Accounts. You want to be able to add an Account to this collection, or change the data of an existing account in this collection.
This functionality is similar to the functionality of an ICollection<Account>.
So all that Form1 needs to know, is that it holds an ICollection<Account>. Somehow during initialization Form1 loads the Accounts collection. If the operator presses Add, a Form2 opens where he can fill in the required values for a new Account. The operator chooses either OK or Cancel to indicate he want this Account to be added to the collection or not (Using a Save button in the form is not windows standard and a bit unclear, so don't use it).
Add an Account
Code in Form1
private ICollection<Account> existingAccounts;
void OnButtonAdd(object sender, ...)
{
using (var form = new Form2())
{
form. ...// fill any needed values
// show form2 and check if OK or Cancel:
var dlgResult = form.ShowDialog(this);
// only add if OK pressed, otherwise ignore
if (dlgResult == DialogResult.OK)
{
this.existingAccounts.Add(form.Account);
}
}
}
Cond in Form2
In visual studio designer create a Form with a TextBox for the ID and a textbox for the password (give it password properties, so it displays *****)
Add an OK and a Cancel button. Give the DialogResult property of these buttons the proper OK and Cancel value.
Finally add one property to get the typed values:
public Account Account
{
get
{ // extract the values from the display
return new Account()
{
Id = this.TextBoxId.Text,
Pwd = this.TextBoxPwd.Text,
};
}
}
Edit existing Account
You also have a button to edit an existing account. Do you only want to edit the last Added account, or do you want to be able to edit any existing account?
In the latter case you'll have to make something that displays all existing account where operators can select one of them. Probably using a DataGridView, or a BindingSource. You'll probably end up with a function like:
Account GetSelectedAccount() {...}
The Form to edit an existing Account is similar to the form to create a new account. You should really consider using the same form for it.
public Account Account
{
get
{ // extract the values from the display
return new Account()
{
Id = this.TextBoxId.Text,
Pwd = this.TextBoxPwd.Text,
};
}
set
{
this.TextBoxId.Text = value.Id;
this.TextBoxPwd.Text = value.Pwd;
}
}
In form1, upon pressing Edit:
void OnButtonEdit_Click(object sender, ...)
{
using (var form = new FormEdit())
{
Account accountToEdit = this.GetSelectedAccount();
form.Account = accountToEdit;
// or: GetLastAddedAccount if you only want to edit the last added one
var dlgResult = form.ShowDialog(this);
if (dlgResult == DialogResult.OK)
{ // extract the edited Account from the form:
Account editedData = form.Account;
this.UpdateSelectedAccount(editedData);
}
}
}
Like in the examples above I usually decide to have an interface with a property that inserts and extracts Accounts instead of accessing every Account property separately. This allows you to change internals of an Account without having to change all (software) users of this Account
It's all about passing data between forms, So you can use one of following :
set the user input in public string so you can access the strings from other forms by the input form object.
you can pass the user input as constructor parameters and then use the data in your form.
there are also other multiple ways like delegate but i think the 2 previous ways are simple.
Related
I'm using c# and Visual Studio. I want to access a variable from another form. I've found some things like:
textBox1.Text = form22.textBoxt17.Text;
But I don't want to access a textBox value, I just want to access a variable. I've tried this:
string myVar1 = Form2.myVar2;
But that doesn't work.
Any help?
Update
This is what I've got now:
private string _firstName = string.Empty;
public string firstName
{
get
{
return _firstName ;
}
set
{
if (_firstName != value)
_firstName = value;
}
}
In formLogin (where the variable is located), just below public partial class formLogin : Form
Then, later in code, inside button on click event:
OleDbCommand command2 = new OleDbCommand();
command2.Connection = connection;
command2.CommandText = "select firstName from logindb where username = '" + txtUsername.Text + "' and password = '" + txtPassword.Text + "'";
firstName = command2.ExecuteScalar().ToString();
I write this in formAntonyms (from where I want to access the variable) in formLoad event:
formLogin fli = new formLogin();
lblName.Text = fli.firstName;
The problem with all this is that, when formAntonyms opens, lblName is still empty, instead of showing the users name. What am I doing wrong, I've done all the steps right...
You are on the right path, you should not expose controls or variables directly to client code.
Create a read only property in the form/class you want to read the value from:
//Form2.cs
public string MyVar{get{ return textBoxt17.Text;}}
Then, being form22 the instance variable of your already loaded Form2 form class. Then, from any client code that has a reference to it, you can read the value of the property:
string myVal = frm22.MyVar;
EDIT:
Ok based in your last comment, you have a variable in Florm1 and want to access it from Form2, the principle is the same as the previous example, but instead of exposing a control property you now expose a private variable, and instead of living in Form2 it now lives in Form1:
//Form1.cs
private string _myVar = string.Empty
public string MyVar
{
get
{
return _myVar ;
}
set
{
if(_myVar != value)
_myVar = value;
}
}
The property is now read/write so you can update its value from client code
//From From2, assuming you have an instance of Form1 named form1:
string val = form1.MyVar;
...
form1.MyVar = "any";
First of all it is bad object oriented design to access variables from classes directly. It reduces maintainability and reusability.
Your problems arise, because the functionality of your objects is not clear to you.
You should not think in terms of "I want the value of this variable", but in terms of: "Suppose you have a form22, what properties should such a form have?".
Well, apparently it has a size and a position and lots of others, and apparently your form has some information that it displays, and you think that users of this form want to know the text of the displayed information.
Let's suppose the displayed information is named MyInformation. Be aware, that you can only display a description of the information. This descriptive text is not the information itself.
A proper object oriented design of your form would be
class Form22 : Form
{
public string MyInformationText {get {return ...; }
...
}
Now you are communicating to the users of Form22 that a Form22 has some MyInformation. You also communicated that you are not willing to share this information, only to share a descriptive text of the information. Furthermore users of your form can't change this information.
This gives you a lot of advantages. For instance, suppose you don't want to display the text in a TextBox, but in a ComboBox. Or maybe you don't want to display it at all anymore. The users of the form who wanted a descriptive text of MyInformation don't have to change.
Of course your design could be different if you want users of your form to change the information. Probably that would also mean that you need to change the displayed description of your information. But again: users of your form won't need to know this. Again, this gives you the freedom to change it without users having to change:
public MyInformation SpecialInformation
{
get {return this.mySpecialInformation;}
set
{
this.mySpecialInformation = value;
this.UpdateDisplay(mySpecialInformation);
}
}
It depends on your model if you should still provide a property for the displayed text or not: Should all MyInformation object in the world have the same displayed text, or could it be that the displayed text in form22 might differ from the displayed text of MyInformation in form23? The answer to this influences whether MyInformation should have a function to get the descriptive text, or whether the forms should have a function to get the descriptive text.
These are just examples to show that you should think in: what should my object do? What should users of my object be capable to do with my objects. The more you allow them to do, the less you will be able to change. You will have the greatest flexibility if you supply them with no more information than required. Besides you'll need to test much less functionality.
I want to implement validation on text box for whether the name exists in the database. I am using wpf with c#. I have implemented a validation on the text box while saving new data. My problem is in Edit Mode: when I go to edit mode and try to save, an error appears that the name already exist.
The Below Code works fine on save mode But when it comes to Edit mode when datas get binding the error message shows.
pls suggest me a good way to implement the validation that work on edit mode too.
class MyParent
{
public MyCarClass CurrentCarEntity {get; set;}
private void txtName_TextChanged(object sender, RoutedEventArgs e)
{
CurrentCarEntity.Name = txtName.Text.Trim();
var getName = //Code for getting name from local db
if(CurrentCarEntity.Name != Null)
{
if(getName.Equals(CurrentCarEntity.Name))
{
MessageBox.Show("Name Already Exists");
}
}
}
}
Looks like you're making validation fail for the entire form if the name already exists - validation will trigger every time you try to submit (edit, insert, etc) so edits will always fail.
I would make two textboxes, one for inserts and one for edits. Hide the insert box while in edit mode, or if you want to stick with one, at least disable the validator when editing.
It seems that you are following the wrong approach
let us assume we have a class called users like following
public class User: IValidatableObject
{
public int Id{get; set;}
public string UserName{get; set;}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if(string.IsNullOrEmpty(UserName))
yield return new ValidationResult("Username field is required!", new string[]{"UserName"});
else
{
// check if another User has the same username already
var db= new YourDbContext();
var exists=db.Users.FirstOrDefault(t=>t.Id!=Id && t.UserName.ToLower()=UserName.ToLower());
if(exists!=null)
yield return new ValidationResult("Username is already used by another user!", new string[]{"UserName"});
}
}
}
you don't need to worry about the edit or create, since in both cases you are checking the database if the Users table contains another user,and not same user you are creating or editing, has the same username.
hope this will help you
hi i have question for remove data from 2 forms dialog
in first dialogform it's contain list of data, and in second dialogform it's contain detail of data and delete button... i already successfully delete data in database but i confused how to remove data from list...
if just select data and delete i know it's can be done with this code
quizzes.RemoveAt(listBoxQuizzes.SelectedIndex);
but problem here in dialogform1 not available button delete, just view details data. so if user want to delete data, he must open dialogform2 (detail data)
i already done delete data in database with this code
Global.deleteData("DELETE FROM Quiz_Occurrences WHERE ID = " + id);
and close detaildataform (dialogform2) by
this.Close();
and move to dialogform1 (listdatabox)
the problem in here, data which just i delete still in there because it's still not remove yet (already delete from database but not remove from list). and need to restart program to see effect of delete data
Update Progress
i changed data to global var, so it's technically i can remove data in dialogform2
this is code (modifier listbox in dialogform1)
int no = 1;
foreach (CQuizOccurrence myQuizOccurrence in Global.quizOccurrences) {
}
if i want to delete it from dialogform1, i can use
Global.quizOccurrences.removeAT(listBoxQuizzes.SelectedIndex);
but if i want to delete it from dialogform2
Global.quizOccurrences.removeAT(.........); //still not have idea how can i reference index
Update solution from #nitin
so first i write in formdialog2
public Frmdialog1 frm_dialog { get; set; }
then i write this in formdialog1
frmdialog2.frm_dialog=this;
then back again to formdialog1 to write
frm_dialog.quizzes.RemoveAt(frm_dialog.listBoxQuizzes.SelectedIndex);
is that right because i get many error
If you are opening second dialog from first one u can Have property in Frmdialog2 like
public Frmdialog1 frm_dialog { get; set; }
After creating object of Frmdialog2 in Frmdialog1 you can set this property as
frmdialog2.frm_dialog=this;
Now u can remove item from this listbox in Frmdialog2 iteself after deleting record from database as
frm_dialog.quizzes.RemoveAt(frm_dialog.listBoxQuizzes.SelectedIndex);
NOTE: Modifier for your listbox should be public
i'm finally be able to do as i want after ask many different question about this topic
first i try to change var to global, so i can remove data in listbox dialogform1 from dialogform2 (i think it's the easiest way)
//in dialog form1
foreach (CQuizOccurrence myQuizOccurrence in Global.quizOccurrences) {
//load data from Global.quizOccurences
}
//call function close to close dialogform1
then in dialogform2, match Global.quizOccurrences data with date&time detail data (using list & foreach)
List<CQuizOccurrence> matchData = new List<CQuizOccurrence>();
foreach (CQuizOccurrence myQuizOccurrence in Global.quizOccurrences)
{
DateTime dtDatabase = (DateTime)myQuizOccurrence.occurred;
string dt = dtDatabase.ToString();
if (dt == dateOccur) {
matchData.Add(myQuizOccurrence);
}
}
foreach (CQuizOccurrence myQuizOccurrence in matchData)
{
Global.quizOccurrences.Remove(myQuizOccurrence);
}
//call function show dialog for formdialog1
form1 could subscibe to the form2's close event.
inside form1
form2 f2dialog = new form2(/*I guess you are passing data here*/);
f2.dialog.Closing += eventhandler;
somewhere else
void eventhandler(object sender, eventargs e)
{
//refresh globaldata since by now you have ran delete query
//rebind or call listbox.items.refresh() or both <-------------this how do you get data from rver? the server is updated but does global know that?
}
then you need to call code to get data from database again. and rebind to data
listbox.datacontext = Global.GetData();//or however this is done
you have to manually reset this eveerytime you change your database
databinding is not as smart as you think it is.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
(c# + windows forms) Adding items to listBox in different class
I want to get the combobox value in form1 and use it at form2, because the value will return another data from the registered user
public void povoacboxcliente()
{
List<SM.BancoDados.BD.Model.Clientes> lstClientes = new List<SM.BancoDados.BD.Model.Clientes>();
ClienteFlow flow = new ClienteFlow();
lstClientes = flow.RetornaClientes();
cboxCliente.DataSource = lstClientes;
cboxCliente.DisplayMember = "Nome";
cboxCliente.ValueMember = "Id";
}
Now the value member (Id) will return the sex of the member, that is on database, this part is ok, but what I want is to do the operation in another form.. Here is the code that I'm trying on form2
public void enviasexo()
{
EnviarComando("0238373b3be503");
idClient = Convert.ToInt32(cboxCliente.SelectedValue);
UsuarioFlow usuarioFlow = new UsuarioFlow();
string combo = cboxCliente.SelectedValue.ToString();
string sexo = usuarioFlow.RetornaSexo(combo);
if (sexo == "M")
{
Thread.Sleep(2000);
EnviarComando("0232343b3bdc03");
Thread.Sleep(200); //envia comando
}
else if (sexo == "F")
{
Thread.Sleep(2000);
EnviarComando("0232353b3bdd03");
Thread.Sleep(200);
}
}
the "cboxCliente" was used in form1
Thanks People!
One way is to make the ComboBox public in Form1.Designer.cs
then access the ComboBox from Form2
Form Form1Object = new Form1();
Form1Object.cboxCliente.SelectedValue.ToString();
See similar answer at
Stack Overflow Answer for other similar question
Please use one of State management techniques which are available in Asp.Net when passing values in different forms.
see this
http://www.codeproject.com/Articles/331962/A-Beginner-s-Tutorial-on-ASP-NET-State-Management
Client side state management techniques
View State
Control State
Hidden fields
Cookies
Query Strings
Server side state management techniques
Application State
Session State
As a best practise form 2 should not be shown to user if one of the control value is strictly dependant on form 1...input from the user. apply page validation on form 2 and
redirect user to form1 if the values from the drop down is not selected..
hope this helps
[shaz]
I have a winforms application.
I have a textbox on one form (call F1) and when a button is clicked on this form (call F2), it launches another form.
On F2, I want to set a string via a textbox (and save it to a variable in the class), and then when I close this form, the string will appear in a label in F1.
So I am basically sharing variables between both forms. However, I can't get this to work correctly. How would this code look?
I would add a new property to form2. Say it's for a phone number. Then I'd add a friend property m_phone() as string to form 2. After showing an instance of form2 but before closing it, you can refer to the property m_phone in form1's code.
It's an additional level of indirection from Matthew Abbott's solution. It doesn't expose form2 UI controls to form1.
EDIT
e.g.:
public string StoredText
{
get;
private set;
}
inside the set you can refer to your UI control, like return textBox1.text. Use the get to set the textbox value from an earlier load.
And:
public string GetSomeValue()
{
var form = new F2();
form.ShowDialog();
return form.StoredText;
}
Just ensure that StoredText is populated (or not, if appropriate) before the form is closed.
Are you showing the second form as a dialog, this is probably the best way to do it. If you can avoid doing shared variables, you could do the following:
public string GetSomeValue()
{
var form = new F2();
form.ShowDialog();
return form.TextBox1.Text;
}
And called in code:
Label1.Text = GetSomeValue();
This might not be the most efficient way of approaching, but you could create a class called DB (database). Inside this class, create variables like
public static bool test or public static bool[] test = new bool[5];
In your other forms, you can just create an instance. DB db = new DB(); then grab the information using db.test = true/false. This is what I've been doing and it works great.
Sorry, I'm only like a year late.