In my application I have two forms (see image below). Clicking on "Add" button shows the second "Add wireless network" form.
After filling the form and clicking on "OK", second form adds the new profile and updates the wifi network profiles in the first form. There is a RefreshProfiles function in the first form and I call it in the second form with this:
((MainForm)this.Owner).RefreshWiFiProfiles();
and the "Add" button's code is this:
private void AddButton_Click(object sender, EventArgs e)
{
NewNetworkForm newNetworkForm = new NewNetworkForm();
newNetworkForm.Owner = this;
newNetworkForm.ShowDialog();
}
This setup is working fine, but since the number of lines increased as I added new things, I wanted to divide the code. So I created a class to contain some functions.
namespace WirelessNetworkManager
{
public class Tools
{
public static void RefreshWiFiProfiles(ListView ListViewControl)
{
// clear old list
ListViewControl.Items.Clear();
// update it
}
}
}
I call the method in the first form with this:
Tools.RefreshWiFiProfiles(ProfilesListView);
and it's working fine. The problem is, since I need to update the profiles list from the second form too, I need to call this in NewNetworkForm. I can access and pass the ProfilesListView in MainForm because it's in there. How can I pass a control that is in MainForm to a method in NewNetworkForm and modify it? Or is there a better approach to do this?
File structure
MainForm.cs (WirelessNetworkManager.MainForm)
NewNetworkForm.cs (WirelessNetworkManager.NewNetworkForm)
Tools.cs (WirelessNetworkManager.Tools)
You can set the Modifiers property of your ProfilesListView in Form2 to Public or Internal (It's Private by default) then you can access ProfilesListView of Form2 like this : Form2.ProfilesListView
For example:
ProfilesList.Refresh(Form2.ProfilesListView);
Your mistake is : You are creating a new Form when you are using RefreshWiFiProfiles() method.
You should access to existing Form2, for example if Form2 is Owner of Form1, this code works :
Form ownerForm = (Form)this.Owner;
Tools.RefreshWiFiProfiles(ownerForm.ProfilesListView);
Here is the complete example:
Form1 declaration:
Add a ListView to Form1, Set it's Modifiers to Public and add some items in it.
Add a Button to show Form2
Add a Button to clear Form2 ListView
Form1 Code:
public partial class Form1 : Form
{
Form2 form2;
public Form1()
{
InitializeComponent();
}
private void btnShowForm2_Click(object sender, EventArgs e)
{
form2 = new Form2();
form2.Owner = this;
form2.Show();
}
private void btnClearForm2List_Click(object sender, EventArgs e)
{
Tools.RefreshWiFiProfiles(form2.lstViewOfForm2);
}
}
Form2 declaration:
Add a ListView to Form2, Set it's Modifiers to Public and add some items in it.
Add a Button to clear Form1 ListView
Form2 Code:
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void btnClearForm1List_Click(object sender, EventArgs e)
{
Form1 form1 = (Form1)this.Owner;
Tools.RefreshWiFiProfiles(form1.lstViewOfForm1);
}
}
Declaration of Tools Class:
public static class Tools
{
public static void RefreshWiFiProfiles(ListView listView)
{
listView.Clear();
}
}
I tried implementing this. __curious_geek's answer and it worked fine.
MainForm.cs
namespace WirelessNetworkManager
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private void AddButton_Click(object sender, EventArgs e)
{
// passing "this" (MainForm) to the second form
NewNetworkForm newNetworkForm = new NewNetworkForm(this);
newNetworkForm.ShowDialog();
}
}
}
NewNetworkForm.cs
namespace WirelessNetworkManager
{
public partial class NewNetworkForm : Form
{
public NewNetworkForm()
{
InitializeComponent();
}
// a local variable to reference the first form (MainForm)
private MainForm mainForm = null;
// a second overloaded constructor accepting a form
public NewNetworkForm(Form callingForm)
{
// mainForm now refers to the first form (MainForm)
mainForm = callingForm as MainForm;
InitializeComponent();
}
private void OKButton_Click(object sender, EventArgs e)
{
// create wifi profile with user input
// accessing the ListView using this.mainForm
Tools.RefreshWiFiProfiles(this.mainForm.ProfilesListView);
this.Close();
}
}
}
Tools.cs
namespace WirelessNetworkManager
{
public class Tools
{
public static void RefreshWiFiProfiles(ListView ListViewControl)
{
ListViewControl.Items.Clear();
// iterate through wifi profiles and populate ListViewControl
}
}
}
Also the control element's (ListViewControl) Modifiers should be set to Public or Internal. Otherwise you'll get an error.
'WirelessNetworkManager.MainForm.ProfilesListView' is inaccessible due to its protection level
Related
This is a demo example, I can't use the original code. This context is very simplified.
I want to call a button/event from the child form (form2) when I'm clicking a button from the mother form (form1). I want to do this via subscribing (which I don't really understard since I'm new to coding).
Mother form:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 f = new Form2();
f.Show();
//Call the Button from Form2 here
}
}
Child Form:
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("MessageBox called from Form1 or Form2");
}
}
What you want to do, the way you want to do it, is in general not a good idea as you should not be relying on UI controls on another from, from your other form.
What you can do to achieve what you asked for without rewriting anything is more like this:
1) in the button click of Form2, you do not do anything else than calling a method on Form2, event handler contains no other logic
2) you make that method of form2 public
3) from your button click on form1, you call that same public method of form2
again, this would work but it is not necessarily the best design, it really depends on the whole architecture of your app if this fits or not with the rest or there are better and different ways to accomplish this.
Don't call other form "button clicks", if you want to call some logic from different places, extract logic into dedicated class and call it from both places
public class MyLogic
{
public void Execute(string someParameter)
{
// Do something with parameter
}
}
Then use it in both forms
public partial class Form1 : Form
{
private readonly MyLogic _importantLogic;
public Form1()
{
InitializeComponent();
_importantLogic = new MyLogic();
}
private void button1_Click(object sender, EventArgs e)
{
_importantLogic.Execute(this.textBox1.Text);
}
}
public partial class Form2 : Form
{
private readonly MyLogic _importantLogic;
public Form2()
{
InitializeComponent();
_importantLogic = new MyLogic();
}
private void button1_Click(object sender, EventArgs e)
{
_importantLogic.Execute("Always Form 2");
}
}
I am new to c# and using windows forms.
I have Form1 with a button (Button_Save) and textbox . and I have user control1 with one button (button1).
What I am trying to do in this program is: when I click on button1, its text appear in textbox (in Form1), then I enter new text and click save, the button1 text change accordingly.
I will explain when the freeze happens:
There are 2 parts:
first part: when I created instance of user control1 in Form1 then I participated in UserControl1Event and run program it works fine and button1 text appears in textbox when I click on it. Second part when I create instance of Form1 in user control1 and participated in Form1Event and run the program the program freezes for long time then gives error pointing at Form1 instance in user control1 (as shown in screen shot).
Anyone knows why this is happening ? what I am doing wrong?
Form1:
public partial class Form1 : Form
{
public event EventHandler Form1Event;
UserControl1 uc1 = new UserControl1();
public Form1()
{
InitializeComponent();
Controls.Add(uc1);
uc1.Visible = true;
uc1.UserControl1Event += new EventHandler(Handleuc1);
}
string Return_TextBox_Txt;
public string TextBox_Txt
{
get { return Return_TextBox_Txt; }
}
public void Handleuc1(object sender, EventArgs e) ////////////Handle uc1 event
{
textBox1.Text = uc1.ButtonText;
}
private void button_save__Click(object sender, EventArgs e)//change button text
{
Return_TextBox_Txt = textBox1.Text;
Form1Event(this, e);
}
}
User Control1:
public partial class UserControl1 : UserControl
{
string BtnTxt;
Form1 frm1 = new Form1();
public event EventHandler UserControl1Event;
public string ButtonText
{
get { return BtnTxt; }
}
private void UserControl1_Load(object sender, EventArgs e)
{
frm1.Form1Event += new EventHandler(HandleForm1Event);
}
public void HandleForm1Event(object sender, EventArgs e)
{
button1.Text = frm1.TextBox_Txt;
}
private void Button1_Click(object sender, EventArgs e)
{
BtnTxt = button1.Text;
UserControl1Event(this, e);
}
}
The problem is that both of your classes depend on each other.
Form1, when created, creates an instance of UserControl1, which in turn creates and instance of Form1, and so on. All this chained creation eventually makes your code throw a StackOverflowException.
It's expected behavior because of you are creating new Form1 instance and on object constructing it creates new UserControl1 instance that also creates new Form1 instance and so on.
If you need to have an owner of UserControl1 inside its instance you can pass it to the UserControl1 constructor:
public partial class Form1 : Form
{
...
UserControl1 uc1;
public Form1()
{
InitializeComponent();
// creates new control and pass owner via constructor parameter
uc1 = new UserControl1(this);
Controls.Add(uc1);
uc1.Visible = true;
uc1.UserControl1Event += new EventHandler(Handleuc1);
}
...
}
public partial class UserControl1 : UserControl
{
Form1 frm1;
public UserControl1(Form1 owner)
{
// save user control owner passed from constructor parameter to local variable
frm1 = owner;
}
...
}
I'm trying to pass a url from one Form to another Form (both are in the same project).
The first form contains a web browser control in it. It also has a button, on press of a button the second form launches. The second form just has a button with hard coded url. when the user clicks on the button the url should be passed to the first form and the webbrowser should navigate to the link. Below is the simple code I'm trying
Form1:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void loadwebpage(string link)
{
webBrowser1.Navigate(link);
}
private void button1_Click(object sender, EventArgs e)
{
secondForm form2 = new secondForm();
form2.Show();
}
}
Form2:
public partial class secondForm : Form
{
public secondForm()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
this.Close();
Form1 form1= new Form1();
form1.loadwebpage("http://www.google.com");
}
}
The above code is not working, the webbrowser control does not navigate to the google page. can anyone help
Send the first form as a parameter to your second form. On your second form, you could create a property on your class that matches the type of the first form.
In the constructor of the second form, set said property.
When the user clicks the button on the second form, reference the property of the class that has been set to the instance of the first form and call your loadwebpage function.
EDIT:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void loadwebpage(string link)
{
webBrowser1.Navigate(link);
}
private void button1_Click(object sender, EventArgs e)
{
secondForm form2 = new secondForm(this);
form2.Show();
}
}
Form 2:
public partial class secondForm : Form
{
public Form1 form1 { get; set;}
public secondForm(Form1 f)
{
form1 = f;
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
this.Close();
form1.loadwebpage("http://www.google.com");
}
}
I want to access a method in a child form from parent form.I have used the following code to access the controls.
Form form = (Form)Application.OpenForms["frmname"];
if (tableform != null)
{
GroupBox grp = (GroupBox)tableform.Controls["grpbxname"];
Panel table = (Panel)grp.Controls["panelname"];
}
Using the following code I am able to access controls in the child form from the parent form.
Same way I want to access the function/method in the child form.
For ex: from.newmethod();
Is there any possibility to achieve this,without creating new instance of form.It windows application using c#.net
Thanks.
declaring a method public is not a good practice. you can create delegate or event instead. you can create public delegate for that method and execute that delegate from the outside the class Or you can create Event that you can handle from the outside of the class.
public partial class Form1 : Form
{
public delegate void dMyFunction(string param);
public dMyFunction delMyFunction;
public Form1()
{
InitializeComponent();
delMyFunction = new dMyFunction(this.MyFunction);
}
private void button1_Click(object sender, EventArgs e)
{
Form2 frm = new Form2();
frm.Show();
}
private void MyFunction(string param)
{
this.Text = param;
}
}
Now, you can call this delegate from the outside the class
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
Form1 frm = (Form1)Application.OpenForms["Form1"];
frm.delMyFunction.Invoke("Hello");
//On Form load this method will be invoked and Form1 title will be changed.
}
}
I am working on a game that utilizes Windows Forms in C#. I want to be able to use the first form to call a second form. I have this working. Then I would like for the second form to send data back to the first form rather than creating a new instance of the first form. Can this be done? I know I need to have my properties set up so that I can set the variables from one form to the other. I am just not sure how to go about calling the first form without creating a new instance of it.
Is there a way that this can be done?
For example if I have Form A create an instance of Form B, can I have Form B do some work and send the data back to the original Form A without creating a new instance of Form A?
If you don't use the Data sent back Form A right away then you could use the Form_Closing event handler Form B and then a public property in Form B also.
In your Form A it could look like this:
public partial class FormA : Form
{
FormB frmB = new FormB(); // Instantiate FormB so that you could create an event handler in the constructor
public FormA()
{
InitializeComponent();
// Event Handler for Form Closing
frmB.FormClosing += new FormClosingEventHandler(frmB_FormClosing);
}
void frmB_FormClosing(object sender, FormClosingEventArgs e)
{
String fromFormB = frm2.FormBData; // Get Data from Form B when form is about to close
}
private void button1_Click(object sender, EventArgs e)
{
frmB.ShowDialog(); // Showing Form B
}
}
And in your Form B it could look like this:
private void button1_Click(object sender, EventArgs e)
{
// Let just say that the data is sent back once you click a button
FormBData = "Hello World!";
Close();
}
public String FormBData { get; set; }
It's hard to say without knowing your full requirements. But generally I go like this (Somewhat psuedo code).
Form2 dialogForm = new Form2();
if(dialogForm.ShowDialog() == DialogResult.OK)
{
this.PropertyOnForm1 = dialogForm.PropertyOnForm2
}
This ofcourse relies that your second form is a dialog. You will need to set the dialogresult buttons on Form2, and have a public property that will be accessed from Form1 once the dialog has been completed.
Let me know if this doesn't work and I'll write up a different answer.
Since you are creating Form2 in Form1, you can create a custom event in Form2 and subscribe to it in Form1 at the time that you create Form2, if you are returning information from Form2 when you are closing it then Edper's or MindingData's answers will work.
Here is a quick and dirty example using EventHandler<TEventArgs>
Form1
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 frm2 = new Form2();
frm2.myCustomEvent += frm2_myCustomEvent;
frm2.Show();
}
void frm2_myCustomEvent(object sender, string e)
{
this.Text = e;
}
}
Form2
public partial class Form2 : Form
{
public event EventHandler<string> myCustomEvent;
int count;
public Form2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
count +=1;
myCustomEvent(sender, count.ToString());
}
}