opening a form with a data inside it - c#

I have 3 Forms: frmLOGIN, frmREGISTER & frmACCOUNTS
frmLOGIN has two buttons BtnRegister and BtnLogin, when I press BtnRegister it opens up frmREGISTER.
frmREGISTER has 1 button BtnAddAcc, BtnAddAcc is used to add a rows to datagridview(datagridview inside frmACCOUNTS)
frmACCOUNTS has only 1 datagridview inside it, nothing else
BtnRegister code (inside frmLOGIN)
frmREGISTER frm = new frmREGISTER();
frm.Show();
this.Hide();
BtnAddAcc code (inside frmREGISTER)
frmACCOUNTS acc = new frmACCOUNTS
acc.datagridview.Rows.Add(userID,ln,fn,Dateofbirth,address,contactnumber,username,password);
PROBLEM
When I register a user, using the code above, works, when I try to add code like acc.Show(); to open the form and see if it adds the row to the datagridview, and yes it really adds a row. Now when I get back to the login form and press BtnLogin to open up the frmACCOUNTS the datagridview rows are GONE
Reference

I will answer my own question
Answer is that you need to create a CLASS
Class Controller
{
public static frmLOGIN log = new frmLOGIN();
public static frmREGISTER reg = new frmREGISTER();
public static frmACCOUNTS acc = new frmACCOUNTS();
public static void FormOpen(string form_name)
{
if(form_name == "accounts")
{
acc.Show();
}
else if (form_name == "register")
{
reg.Show();
}
else if (form_name == "login")
{
log.Show();
}
}
}
now to use this. you do not need to call the form again inside the other forms you just need to call the class and and the call the form there.
example
let's say, I want to show login form
so I will call
Controller.FormOpen("login");
let's say I want to use the datagridview inside the Accounts form
and put it inside a new variable
Datagridview DGV = Controller.acc.Datagridview1
now you can use the datagridview inside the accounts form as DGV
Conclusion
call the form inside a class so when other forms wants to call/use another form they will be calling the same forms and not making a new one

Related

Winforms TextBox keeps value in UserControl

I am making an app in which there are multiple UserControls stacked onto each other. So the elements go like this: MainForm -> User clicks on a UserControl1 on the MainForm which (UserControl1) has a panel on which there is displayed another UserControl2 with a button. When the user clicks on it, it displays another UserControl3 which is then displayed in the panel beneath the button, where finally the user enters some text in the textbox. I need the data from the textbox in the MainForm so I have MainForm and UserControls connected via EventHandlers and pass my ResponseModel in which there is some dat a that I need to pass to MainForm. The first time this works, an item is created and displayed, after the item there is this "button" (User controls) displayed, in case the user wants to create another one. But then comes the problem when the user types in a different text for a new item, it creates an item with the same text!! Like the textbox was never changed (I have a debugging point set on the constructor to see every time that the textbox is empty). Below is some code and an image, for you to see how this should work. Also when I first delete the item it then doesn't work to create a new item for some reason.
This is how I send the data from the last UserControl:
if (tbx_list_name.Text == "")
MessageBox.Show("You can't create new list without a name!", "Can't create new list!", MessageBoxButtons.OK, MessageBoxIcon.Warning);
else
CreateListTextBoxHandler?.Invoke(this, new ListCreationResponseModel() {
Code = id, ListName = tbx_list_name.Text
});
This is how I create the last UserControl which has the textbox:
control.CreateListTextBoxHandler += GetHandlerData;
panel.Controls.Add(control);
And this is how I get the data one stage down (this practice continues through couple more stages back to MainForm):
public void GetHandlerData(object sender, ListCreationResponseModel e)
{
try
{
panel.Controls.Clear();
CreateListButtonHandler?.Invoke(this, e);
}
catch (Exception ex)
{
_ = new ErrorHandler(ex);
}
}
You seem to have a recursion here. GetHandlerData is added to the CreateListTextBoxHandler event (or delegate) and invokes CreateListTextBoxHandler again, which will call GetHandlerData again...?? But tbx_list_name.Text is passed to the model only once at the top level down to all the other calls.
You can fix this by passing a reference to the textbox instead of the text itself. Then you will always be able to retrieve the current text of the textbox.
public class ListCreationResponseModel
{
private readonly TextBox _listNameTextBox;
public ListCreationResponseModel(TextBox listNameTextBox)
{
_listNameTextBox = listNameTextBox;
}
public int Code { get; set; }
public string ListName => _listNameTextBox .Text;
}
Now, when you retrieve the ListName you don't get a stored value but the actual text of the textbox.
You can create the handler like this:
CreateListTextBoxHandler?.Invoke(this, new ListCreationResponseModel(tbx_list_name) {
Code = id
});

Keep data on multiple form WindowsForms c#

I 'am making a WindowsForms application. I have 2 Forms :
On the first form (Form1), There are many fields (Textboxs) that should be filled by the user, then click to a button (Transfer).
This button should show all the input datas of Form1 in a new Form (Form2).
I'm not sure how to begin to move data from one form to another. Can somebody guide me how to do it?
If Form1 creates Form2 specifically to show the data, then you can use a non-default constructor to pass the information as you create the form.
First, let's consider an example of the information you want to transfer, and name it Form2Info:
// This class is an example of the information you want to transfer
public class Form2Info
{
public string text1;
public int number1;
}
Then, you modify Form2's constructor to take the information:
public partial class Form2 : Form
{
private Form2Info info;
public Form2(Form2Info information)
{
InitializeComponent();
info = information;
// Do something with this information, such as populate a TextBox or Label on the form.
}
}
Finally, you want to create a Form2 instance from your Form1:
// Create the information you want to pass; we fill it with some placeholder data here.
Form2Info info = new Form2Info();
info.text1 = "Hello"
info.number1 = 5;
// Now create the form and pass the data
Form2 form2 = new Form2(info);
form2.ShowDialog(); // Show modal dialog.
Each Textbox has a value (Textbox.Text property). You will have to transfer the content of these different properties to the new controls in your second form.
The easiest way will be through a custom Form constructor for the second form.
public Form2(string textBox1Value, string textBox2Value)
// etc... add as many as you like or use an object that holds all values in properties
{
InitializeComponent(); // Required by WinForms
this.TextBox1.Text = textBox1Value;
this.TextBox2.Text = textBox2Value;
}
Make sure you match the text boxes you want using the names. Finally when creating the form on the Transfer button code, call this constructor instead.

How to Inherit windows forms controls

I have one main form with controls like datagridview, combobox , textboxes and so on.I have created another which i want to use it as a wizard for selection as am trying to make it look user friendly. Now i want to be able to inherit controls inside the main form. i don't have a class nor create it as i don't wanna use it. i know how to create class and call my class within the form i want to access the method, properties and function.
How can i access the controls from one form to another.
e.g datagridview and textbox are from form1. on form two,i want to be able to access those two controls(datagridview and textbox). Please note here am giving as an example but from my main form i have more that two kinds of control.
My code from the wizard form
private void btnBrosweInput_Click(object sender, EventArgs e)
{
BrowseFile();
ReadFile(ref Gridview_Input,
ref txtInputfile,
ref cboLanguage,
bref btnNewfile);
//Errors that m getting from this method
1.Gridview_Input' does not exist in the current context
2.The best overloaded method match for .FrmExisitngFile.ReadFile(ref System.Windows.Forms.DataGridView, ref System.Windows.Forms.TextBox, ref System.Windows.Forms.ComboBox, ref System.Windows.Forms.Button)' has some invalid arguments
3.Error 5 Argument 1: cannot convert from 'ref Gridview_Input' to 'ref System.Windows.Forms.DataGridView'
}
I have place this method for readfile on the form
private void ReadFile(ref DataGridView _Grid, ref TextBox _InputTexBox, ref ComboBox _cboLanguage, ref Button _btnNew)
{
_Grid.Rows.Clear();
string PathSelection = "";
if (_InputTexBox.Text.Length > 0)
{
PathSelection = _InputTexBox.Text;
}
oDataSet = new DataSet();
XmlReadMode omode = oDataSet.ReadXml(PathSelection);
for (int i = 0; i < oDataSet.Tables[2].Rows.Count; i++)
{
string comment = oDataSet.Tables["data"].Rows[i][2].ToString();
string font = Between(comment, "[Font]", "[/Font]");
string datestamp = Between(comment, "[DateStamp]", "[/DateStamp]");
string commentVal = Between(comment, "[Comment]", "[/Comment]");
string[] row = new string[] { oDataSet.Tables["data"].Rows[i][0].ToString(), oDataSet.Tables["data"].Rows[i][1].ToString(), font, datestamp, commentVal };
_Grid.Rows.Add(row);
_btnNew.Enabled = true;
}
}
from the wizard form am trying to access the controls from the main form which contains the grid where everything will get loaded on
There is a lot of things going on in your code, but the main problem is that you try to manipulate data from your UI controls. This is a tremendously bad idea and it dramatically complicates your design (as you can already see from this fairly small feature).
As I stated in the OP's comments, you don't want to manipulate the controls to work with data. You want to manipulate data from POCO (Plain Old CLR Objects). And then update (or better: databind) all the controls that expose those data.
So you should start by doing something like this:
public class Form2 : Form
{
private List<Things> _listOfThings;
private string _inputText;
private LanguageEnum _lang;
...
// Receives data, NOT controls!
public Form2(List<Things> listOfThings, string inputText, LanguageEnum lang, ...)
{
_listOfThings = listOfThings;
...
}
...
}
Your Form1 reflects the state of listOfThings via a DataGridView, inputText via a TextBox and so on. You get the idea. Form1 pass those data (NOT the controls) to Form2 via constructor injection:
Form2 form2 = new Form2(listOfThings, inputTextBox.Text, ...);
form2.ShowDialog();
You read and update the data using the private fields in the Form2 class. When Form2 is closed, you update Form1's controls, either explicitly or using Databinding.

Get an Label reference without using name

I am trying to write a program that opens an arbitrary number of forms ( each one containing a label) when the user clicks on a button, and i put them on a list:
List<Form> formlist = new List<Form>();
...
public void showFrame()
{
Form f = new Form();
// I add the components i need ...
formlist.Add(f)
}
What i need now is, given the i index of the form in formlist, to change the label.Text of that form.
Is possible to do it, withous using a different name for each lavel?
Give the control(s) you add to the form a Name. Then it is
formlist[i].Controls["somename"].Text = "mumble";

Sharing a variable between two winforms

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.

Categories