c# call method from another form to refresh my combobox - c#

I have a code here but it didn't work, i want to refresh my combobox from another form by calling the method cmb_lod();
Form1 were my combobox created
public void cmb_load()
{
try
{
con.Open();
cmd = new SqlCommand("SELECT subjectCode FROM Subjects", con);
reader = cmd.ExecuteReader();
while (reader.Read())
{
cmbSubjects.Items.Add(reader[0].ToString());
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
con.Close();
}
Form2 where i want to refresh my combobox after adding value
private void btnRefresh_Click(object sender, EventArgs e)
{
frmManipulateClass mc = new frmManipulateClass();
mc.cmb_load();
}

The problem is that in the second form, you're creating a NEW instance of the first form and then refresh the combobox on it. This second instance has nothing to do with the first instance. What you need to do is to obtain a reference to the original first form and call the method on it. One way is in the first form:
public static frmManipulateClass Current {get; private set;}
public frmManipulateClass()
{
Current = this;
}
and then in the second form:
frmManipulateClass.Current.cmb_load();
This is only useful if you open just a single instance of the first form.

Related

C# - Change label text from another class

I am a total noob on C# and I'm stuck on changing the status label text from an other class.
When this class connects to db I want to change the label text to "Connected":
public class DBConnect
{
public void Connect()
{
MySqlConnection conn;
string myConnectionString;
myConnectionString = "server = 127.0.0.1; uid=cardb;" +
"pwd=cardb; database=test;";
try
{
Form form = new Form();
conn = new MySqlConnection();
conn.ConnectionString = myConnectionString;
conn.Open();
form.setStatus();
}
catch (MySqlException ex)
{
MessageBox.Show(ex.Message);
}
}
}
This is the method setStatus I created in Form class:
public partial class Form : System.Windows.Forms.Form
{
public Form()
{
InitializeComponent();
}
public void setStatus()
{
StatusTextLabel.Text = "Connected";
}
The label text doesnt change though.. :/
I see no code to create a DBConnect object, or to call its Connect() method, and no code that makes the Form object visible, e.g. form.Show().
Other than that you probably should not create the Form from the Connect method; instead call Connect() from the Form, e.g. in Form_Load(), let it return a status, or better: the conn object (which you are now throwing away after connection), and make Form_Load set the Label.Text based on that.
Example code:
private void Form1_Load(object sender, EventArgs e)
{
var conn = new DBConnect().Connect();
if (conn != null && conn.State == ConnectionState.Open)
{
StatusTextLabel.Text = "Connected";
}
}
public class DBConnect
{
public SqlConnection Connect()
{
SqlConnection conn = ...
// ...
return conn;
}
}
Instead of creating an instance of a new Form, you probably need an instance of already opened form and call the method from there. You can try:
(System.Windows.Forms.Application.OpenForms["Form"] as Form).setStatus();
Pass the form instead of creating a new one.
private Form form {get;set;}
public DBConnect(Form form)
{
this.form = form;
}
Then try this
form.Invoke(new MethodInvoker(() => form.setStatus()));

Form Using User Control Won't Return Value

I am writing a user control. I want it to return a customer number when the user double clicks on the customer. I can't seem to get it to work. The user control is displayed and, on the double click, the data shows in the messagebox but I can't seem to get it to update the value on the main form.
Anytime I try to add a return value into FindCustomerControl_ItemHasBeenSelected, I get an error. It's like it hangs out in the user control and I can't leave it with a return value. So far, this is what I have:
In my main window:
public partial class TestForm : Form
{
public TestForm()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// one close button on the form
Close();
}
private void ShowSelectFromListWidget()
{
// show the user control
var uc = new FindCustomerControl();
uc.ItemHasBeenSelected += uc_ItemHasBeenSelected;
MakeUserControlPrimaryWindow(uc);
}
void uc_ItemHasBeenSelected(object sender,
FindCustomerControl.SelectedItemEventArgs e)
{
// once it has been selected, change a label on the screen to show the customer number
var value = e.SelectedChoice;
lblCustomer.Text = value;
}
}
In my user control:
public partial class FindCustomerControl : UserControl
{
public class SelectedItemEventArgs : EventArgs
{ public string SelectedChoice { get; set; } }
public event EventHandler<SelectedItemEventArgs> ItemHasBeenSelected;
public FindCustomerControl()
{ InitializeComponent();}
DataTable dt = new DataTable();
public void btnFind_Click(object sender, EventArgs e)
{ var dt = GetData();
dataGridView1.DataSource = dt; }
//Query database
public DataTable GetData()
{
UtilitiesClass ru = new UtilitiesClass();
string connectionString = ru.getConnectionString();
DataTable dt = new DataTable();
SqlConnection myConnection = new SqlConnection(connectionString);
myConnection.Open();
SqlCommand cmd = new SqlCommand("FindCustomer", myConnection);
cmd.Parameters.AddWithValue("#customer", txtCustomer.Text.Trim());
cmd.CommandType = CommandType.StoredProcedure;
SqlDataAdapter ta = new SqlDataAdapter(cmd);
ta.Fill(dt);
myConnection.Close();
return (dt);
}
private void dataGridView1_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
var handler = ItemHasBeenSelected;
string choice = dataGridView1[0, e.RowIndex].Value.ToString();
// this shows it
MessageBox.Show("Chosen: " + e.SelectedChoice);
if (handler != null) handler(this, new SelectedItemEventArgs { SelectedChoice = choice });
// I WOULD LIKE TO RETURN A VALUE HERE
}
}
It seems as though this should be common enough but, in spite of my hours of research and debugging, I have been unable to come up with a solution. I do know that uc.ItemHasBeenSelected += uc_ItemHasBeenSelected; in TestForm doesn't seem to ever get executed because I put a breakpoint there.
As I understood I guess you could use application current resources, where you can save any value you wish - in UWP it is something like this:
Application.Current.Resources["Name"] = customerNumber
Then you can cast this value to desired type:
(int)Application.Current.Resources["Name"]
Now you can use this value wherever you want.
Hope than helped in any way.
There is nothing wrong with the user class. It works fine. The problem is that the TestForm needs to start without the FindCustomerControl on it and instantiate the control within the program. It returns the value into the label or wherever else it needs to. Thanks very much to Brad Rem and this post: Return value from usercontrol after user action
public partial class TestForm : Form
{
public TestForm()
{
InitializeComponent();
ShowSelectFromListWidget();
}
private void button1_Click(object sender, EventArgs e)
{
Close();
}
private void ShowSelectFromListWidget()
{
var uc = new FindCustomerControl();
uc.ItemHasBeenSelected += uc_ItemHasBeenSelected;
this.MakeUserControlPrimaryWindow(uc);
}
void uc_ItemHasBeenSelected(object sender, FindCustomerControl.SelectedItemEventArgs e)
{
var value = e.SelectedChoice;
lblCustomer.Text = value;
lblMerchant.Focus();
//ClosePrimaryUserControl();
}
private void MakeUserControlPrimaryWindow(UserControl uc)
{
// my example just puts in in a panel, but for you
// put your special code here to handle your user control management
panel1.Controls.Add(uc);
}
private void ClosePrimaryUserControl()
{
// put your special code here to handle your user control management
panel1.Controls.Clear();
}
}

How do I call a method that only accepts a parameter that is in another form?

I have a form1 (that runs the program) and form2 (that is a form for user to input). Form2 has a function that clears the user input (textboxes, checkboxes, combo boxes, it clears them).
The function looks like this:
public void CleartheForm(Control groupofcontrols)
{
foreach (Control c in groupofcontrols.Controls)
{
if (c is TextBox)
{
((TextBox)c).Clear();
}
if (c.HasChildren)
{
CleartheForm(c);
}
if (c is CheckBox)
{
((CheckBox)c).Checked = false;
}
label3.Text = "";
comboBox1.SelectedIndex = -1;
comboBox2.SelectedIndex = -1;
}
}
This works on its own. On my main form, I need to call this function, it should look like this:
I make a instance of form2 call Inputform and then:
private void Addrecord_Click(object sender, EventArgs e)
{
Inputform.ShowDialog();
if(Inputform.Addedrecord == true)
{
Inputform.Addrecord();
Inputform.CleartheForm(WHAT DO I PUT IN HERE??);
}
}
So that once a record has been added, the input form clears itself and ready for another record to be added.
The question is as above, what do I put in there? How do I call the groupofcontrols that is in the Inputform.CleartheForm() that is located in form2 from form1?? I tried to make a public Control groupofcontrols on the top of form2 and then leave my form1 as Inputform.CleartheForm(Control groupofcontorls), but then it saids I don't have object reference. If I leave it blank it saids Inputform.CleartheForm(); does not take 0 arguement.
Well, if you wanted to clear all the controls in the InputForm you could write another version of CleartheForm() without a parameter, and call the version with a parameter from it, like so:
public void CleartheForm()
{
ClearTheForm(this); // Passes all the controls in the Form.
}
Or you can just call the original ClearTheForm(Control) passing a reference to the InputForm as an argument: InputForm.ClearTheForm(InputForm).
If you always want to clear all the controls, I'd write a separate parameterless method for clarity.
However, this is only useful if you want to clear all the controls in InputForm.
Because Form is inherited from Control, you can call your method with form as an argument - it will clear all the TextBoxes and CheckBoxes in it:
Inputform.CleartheForm(Inputform);
However, probably, you can simply create new (and empty!) Inputform each time.
And, for your method - you should put
label3.Text = "";
comboBox1.SelectedIndex = -1;
comboBox2.SelectedIndex = -1;
away from the loop.
From what you've said (i.e. you put the groupofcontrols as public on form2), this should work:
Inputform.CleartheForm(Inputform.groupofcontrols);
(This is considering that Inputform is a property or a field on your main form - which I observed it is as you're calling ShowDialog on it.)
I don't understand your program's workflow.
If it is:
Form1 opens Form2
User input data into Form2
User press OK button on Form2
Form2 closes
Form1 reflect changes which was made by the user in Form2
User can repeat from the step 1
You should use new instance of the Form2 for the each iteration
To do that you should remove any clear code from your Form2 and change your code to the next one:
private void Addrecord_Click(object sender, EventArgs e)
{
var inputForm = new Form2();
inputForm.ShowDialog();
if(inputForm.Addedrecord == true)
{
...Reflect changes here...
}
}
But if you need a Form2 should stay opened while a Form1 adds new record each time when user click "Ok" button on the Form2
You should call Form1 from the Form2, the next design will be nice
interface IDataTarget
{
void Update(int id, string name); // you should reflect here all of your data
}
class Form1
: Form, IDataTarget
{
public void Update(int id, string name)
{
// add new record here
}
private void AddButton_Click(...)
{
using(var form2 = new Form2(this))
{
form.ShowDialog(this);
}
}
}
class Form2
: Form
{
private readobly IDataTarget dataTarget;
public Form2(IDatatarget dataTarget)
{
this.dataTarget = dataTarget;
}
private OK_Click(...)
{
dataTarget.Update(textBox1.Text, textBox2.Text);
ClearTheControls();
}
}
Personally I would move this method into a class library. You can make it static class and then just call
FromControls.CleartheForm(Inputform.groupOfControls)
So, your new class in a class library is (and nothing has been tested here, so mistakes are likely!)
public static class FormControls
{
public static void CleartheForm(Control groupofcontrols)
{
foreach (Control c in groupofcontrols.Controls)
{
if (c is TextBox)
((TextBox)c).Clear();
if (c.HasChildren)
CleartheForm(c);
if (c is CheckBox)
((CheckBox)c).Checked = false;
}
}
}
I would remove the following code:
label3.Text = "";
comboBox1.SelectedIndex = -1;
comboBox2.SelectedIndex = -1;
...as the CleartheForm code above will clear it.
So, your code would be (remembering to add a reference to your class library)
private void Addrecord_Click(object sender, EventArgs e)
{
AddRecord();
}
private void AddRecord()
{
Inputform.ShowDialog();
if(Inputform.Addedrecord)
{
Inputform.Addrecord();
FromControls.CleartheForm(GetControlOnPage())
}
}
private control GetControlOnPage()
{
//logic to return control if needed although it may just be this:
return Inputform.groupofcontrols
}

NullReferenceException was unhandled - what is null?

I'm trying to access an event in my main form by clicking a button (btnsearch_Click) and everytime I clicked it, it says 'object reference not set to an instance of an object'.
Here is my code:
USER CONTROL
namespace Purchase_Order
{
public partial class Search : UserControl
{
public event EventHandler btnSearchClicked;
public Search()
{
InitializeComponent();
}
private void btnsearch_Click(object sender, EventArgs e)
{
btnSearchClicked(sender, e);
}
}
}
MAIN FORM
namespace Purchase_Order
{
public partial class formMain : Form
{
public formMain()
{
InitializeComponent();
}
private void formMain_Load(object sender, EventArgs e)
{
Search searchbox = new Search();
searchbox.btnSearchClicked += new EventHandler(SearchClicked);
}
void SearchClicked(object sender, EventArgs e)
{
MySqlConnection con = new MySqlConnection(serverstring);
try
{
string query = "SELECT * FROM tblclassification WHERE INSTR(class_name, #search)";
MySqlCommand cmd = new MySqlCommand(query, con);
MySqlDataAdapter da = new MySqlDataAdapter(cmd);
Search content = new Search();
cmd.Parameters.AddWithValue("#search", content.btnsearch.Text);
DataTable dt = new DataTable();
da.Fill(dt);
classification control = new classification();
control.dataGridView1.DataSource = dt;
control.dataGridView1.DataMember = dt.TableName;
panelMain.Controls.Clear();
panelMain.Controls.Add(control);
MessageBox.Show("OK");
}
catch (Exception)
{
throw;
}
finally
{
if (con.State == ConnectionState.Open)
{
con.Close();
}
}
}
You are creating a new instance of your user control in SearchClicked method and you are not registering the event against it.
Search content = new Search();
Also its better if you check whether any control has register your event before raising it like:
private void btnsearch_Click(object sender, EventArgs e)
{
if(btnSearchClicked != null)
btnSearchClicked(sender, e);
}
That means that you haven't got an instance of the type you want to use.
public event EventHandler btnSearchClicked; is just a reference for the "real" object you want to use.
It's like you trying to open a door of a house you only have a blueprint. This isn't really possible (at least not in our universe). You will first need to build the house and then try to enter it. Something like this is the case with your problem.
You will have to read a few tutorials about C#
Edit:
The thing about null is that there is nothing the reference you have is pointing too. If you haven't created anything then there isn't anything to reference...
Because you are trying to use something that doesn't exists (is null) you are getting an exception.
To try and expand a little on Habib's answer (I was going to post this as a comment but it's a little lengthy), you are first creating an instance of Search and registering the event in formMain_Load here:
private void formMain_Load(object sender, EventArgs e)
{
Search searchbox = new Search();
searchbox.btnSearchClicked += new EventHandler(SearchClicked);
}
This is all fine and dandy. However, in SearchClicked, you create a new instance of Search like so:
Search content = new Search();
This is a separate object to the one you created in formMain_Load and you never register the event to this object. It looks like what you want to do is share the Search instance from formMain_Load with the SearchClicked method. To do this, create a property in your codebehind:
public partial class formMain : Form
{
private Search _searchbox;
...
}
Then, in formMain_Load:
private void formMain_Load(object sender, EventArgs e)
{
_searchbox = new Search();
_searchbox.btnSearchClicked += new EventHandler(SearchClicked);
}
Now, you can reuse this object with the event registered in SearchClicked by changing this:
Search content = new Search();
To this:
Search content = _searchbox;
You should find that the exception goes away. Hopefully, this will have provided a little more insight and will help you to understand the cause of the error and how to circumvent it.
Share the Search instance from formMain_Load with the SearchClicked method
MAIN FORM
public partial class formMain : Form
{
private Search _searchbox;
...
private void formMain_Load(object sender, EventArgs e)
{
_searchbox = new Search();
_searchbox.btnSearchClicked += new EventHandler(SearchClicked);
}
void SearchClicked(object sender, EventArgs e)
{
Search content = _searchbox;
MySqlConnection con = new MySqlConnection(serverstring);
try
{
string query = "SELECT * FROM tblclassification WHERE INSTR(class_name, #search)";
MySqlCommand cmd = new MySqlCommand(query, con);
MySqlDataAdapter da = new MySqlDataAdapter(cmd);
cmd.Parameters.AddWithValue("#search", content.btnsearch.Text);
DataTable dt = new DataTable();
da.Fill(dt);
classification control = new classification();
control.dataGridView1.DataSource = dt;
control.dataGridView1.DataMember = dt.TableName;
panelMain.Controls.Clear();
panelMain.Controls.Add(control);
MessageBox.Show("OK");
}
catch (Exception)
{
throw;
}
finally
{
if (con.State == ConnectionState.Open)
{
con.Close();
}
}
}
}
USER CONTROL
public partial class Search : UserControl
{
public event EventHandler btnSearchClicked;
public Search()
{
InitializeComponent();
}
private void btnsearch_Click(object sender, EventArgs e)
{
btnSearchClicked(sender, e);
}
}

Can't load the textbox inside the constructor

I have a form called SelectCatagoryId which contains a DataGridView. I want to pass the selected cellvalue from here to another form called Add_product.
This is the code inside the button event in SelectcatagoryId.
private void dataGridView1_MouseClick(object sender, MouseEventArgs e)
{
String dgv;
dgv = dataGridView1.CurrentCell.Value.ToString();
Add_product ap = new Add_product(dgv);
this.Close();
}
This is the code inside Add_product form
namespace Supermarket
{
public partial class Add_product : Form
{
public Add_product()
{
InitializeComponent();
}
SqlConnection con;
string file;
public Add_product(String datagridvalue)
{
// MessageBox.Show(datagridvalue);
textBox10.Text = Convert.ToString(datagridvalue);
}
MessageBox is working correctly,value of dgv in form selectCatagoryId is passed correctly to form Add_product, but I can't assign the value of variable datagridvalue to textBox10.Text.
Before assign text to textBox you need to show form Add_product.
private void dataGridView1_MouseClick(object sender, MouseEventArgs e)
{
String dgv;
dgv = dataGridView1.CurrentCell.Value.ToString();
Add_product ap = new Add_product();
ap.Show();
ap.SetProduct(dgv);
this.Close();
}
...
Also add this method to Add_product class
public SetProduct(String datagridvalue)
{
// MessageBox.Show(datagridvalue);
textBox10.Text = datagridvalue;
}
Even with you are creating a overload of constructor, you need to InitializeComponent() so all the instance of the controls are created.
public Add_product(String datagridvalue)
{
InitializeComponent();
// MessageBox.Show(datagridvalue);
textBox10.Text = Convert.ToString(datagridvalue);
}
By default all the UI Component are initiated within the constructor of the form.
And Visual Studio generates all the Initialization in the InitializeComponent() method.

Categories

Resources