Form1 frm = new Form1();
frm.mdiParent=this;
frm.show();
I want to create a global method showFrm(Form formToShow) which i can access from anywhere in my project.
I've tried.
public void showFrm(Form formToShow)
{
formToShow f=new formToShow();//getting error here
f.mdiParent= mdiForm;
f.show();
}
Put this method in your "only parent form" class:
public void ShowMdiChild<T>() where T: Form, new()
{
var form = new T();
form.MdiParent = this;
form.Show();
}
Usage:
yourOnlyParentForm.ShowMdiChild<SomeForm>();
I would also remind you that C# is case-sensitive.
Related
I am trying to open ChildForms on MdiParent Form using a Form Manager Class.
I've tried several alternatives in order to tell "FormManager" Class which Form is the MdiParent; however it would always throw errors (1 different error for each different occasion).
Most of the times it would say that MainForm was not a MdiContainer; and this is not true as I had set MainForm previously as such.
Note:1 Main Form is set as a MdiContainer.
Note:2 If I attempt to open only 1 Form it will open perfectly inside MdiParent Form. However if I attempt to Load 2 or more Forms it will throw error.
Note:3 If I create the Child Forms Instances on Main Form; Everything works just fine. No issues at all. But this is not how I want to do it.
// [Class] : Main Form
// Member Variables
private FormManager FrmMgr;
// Load Forms using FormManager Class
private void Load_Forms()
{
// Create a new Instance of FormManager.
if (FrmMgr == null) { FrmMgr = new FormManager(); }
// Set MainForm as MdiParent in FormManager Class
FrmMgr.MdiParent = this;
// Alternatively Manually Set the MdiParent in MainForm (Uncomment Line Bellow)
// this.IsMdiContainer = true;
}
// [Class] : Form Manager
// <Member Variables>
private Form1 frm1;
private Form2 frm2;
// FormManager <Constructor>.
// Constructor Receives MdiParent Information from MainForm
// and Sets the MdiParent.ActiveControl Information to Every Form
// when calling each (Form initiation) Method.
public FormManager(Form _MainParent)
{
// Create new Instance of Form1
Init_Frm1(_MainParent);
// Create new Instance of Form2
Init_Frm2(_MainParent);
}
private void Init_frm1(_MainParent)
{
if (frm1 == null) { frm1 = new Form1(); }
frm1.MdiParent = _MainParent;
frm1.Show();
}
private void Init_frm2(_MainParent)
{
if (frm2 == null) { frm2 = new Form2(); }
frm2.MdiParent = _MainParent;
frm2.Show();
}
}
Can anyone point me in the right direction and help me understand why this happens?
Thanks in advance.
I was finally able to sort it out.
The issue seemed to be consisted in the way I've used to pass "MainForm" as the "MdiParent" to "FormManager" class.
// [Class] MainForm
// Create new Instance (Always Active); of FormManager Class
// Note: When FormManager Class is Loaded; it's Constructor will
// run the Methods that will open all the initial Forms.
private void Load_Modules()
{
// "this" refers to "MainForm"
if (FrmMgr == null) { FrmMgr = new FormManager(this); }
}
// [Class] FormManager
// Member Variables
private Form1 frm1;
private Form2 frm2;
// <Constructor>
public FormManager(Form _MainParent)
{
// Create new Instance of Form1 under "Init_Frm1" Method
Init_Frm1(_MainParent);
// Create new Instance of Form2 under "Init_Frm2" Method
Init_Frm2(_MainParent);
}
// Method that Will Create new Instance of Form1
private void Init_Frm1(Form _MainParent)
{
if (frm1 == null) { frm1 = new Form1(); }
frm1.MdiParent = _MainParent;
frm1.Show();
}
// Method that Will Create new Instance of Form2
private void Init_Frm2(Form _MainParent)
{
if (frm2 == null) { frm2 = new Form2(); }
frm2.MdiParent = _MainParent;
frm2.Show();
}
I have Form1 where I want to use the list of objects listaPacienti I created in Form2 but it doesn't work.
Pacient is the class used to generate objects.
Here is Form1's beginning:
public partial class Form1 : Form
{
Form2 formPacienti = new Form2();
List<Pacient> listaPacienti = new List<Pacient>();
public Form1()
{
InitializeComponent();
}
And here is the beginning of Form2 where I created the list listaPacienti I want to pass to Form1:
public partial class Form2 : Form
{
List<Pacient>listaPacienti=new List<Pacient>();
Pacient p1 = new Pacient(0, "Pacient1", 0, 200);
Pacient p2 = new Pacient(1, "Pacienct2", 0, 100);
Form1 formMedici = new Form1(listaPacienti);
public Form2()
{
InitializeComponent();
listaPacienti.Add(p1);
listaPacienti.Add(p2);
}
What's wrong because I searched here before and that's how it is recommended to be done and if I wrote something wrong I don't know what it is because in Form2, the parameter "listaPacienti" from the following line
Form1 formMedici = new Form1(listaPacienti);
shows me this message: "A field initializer cannot reference the non-static field, method or property "Form2.listaPacienti".
Thank you
There are several things wrong here actually. The error itself is telling you that you can't use a class member when initializing a class member. You're trying to use listaPacienti to initialize formMedici. But you could initialize it in the constructor. Something like this:
List<Pacient> listaPacienti = new List<Pacient>();
Pacient p1 = new Pacient(0, "Pacient1", 0, 200);
Pacient p2 = new Pacient(1, "Pacienct2", 0, 100);
Form1 formMedici;
public Form2()
{
InitializeComponent();
listaPacienti.Add(p1);
listaPacienti.Add(p2);
formMedici = new Form1(listaPacienti);
}
However, your Form1 constructor also needs to accept that parameter. So you either need to modify the existing Form1 constructor or add a new one:
public Form1(List<Pacient> listaPacienti)
{
InitializeComponent();
// do something with listaPacienti?
}
However, it's not really clear why you're even doing this. You create an instance of Form2 in Form1:
Form2 formPacienti = new Form2();
Then you create an instance of Form1 in Form2:
Form1 formMedici = new Form1(listaPacienti);
This is an infinite recursion waiting to happen. Do you really want Form2 to create a new instance of Form1? Or do you want to use the existing instance of Form1? If the latter, then remove the references to Form1 entirely from Form2.
There are a variety of ways to accomplish the overall goal of what you're trying to do, and which one is ideal depends on more than what's presented here. But the simplest approach given the information present is probably to just make listaPacienti accessible from outside of Form2:
public List<Pacient> ListaPacienti { get; set; }
Pacient p1 = new Pacient(0, "Pacient1", 0, 200);
Pacient p2 = new Pacient(1, "Pacienct2", 0, 100);
public Form2()
{
InitializeComponent();
ListaPacienti = new List<Pacient>()
ListaPacienti.Add(p1);
ListaPacienti.Add(p2);
}
Now that listaPacienti is a public property, any code which has a reference to an instance of Form2 can access that property:
Form2 formPacienti = new Form2();
// Do other things with formPacienti?
// Either way, here you can access formPacienti.ListaPacienti
You need to add one more constructor to form one like this.
public Form1(List<Pacient> list)
{
this.listaPacienti=list;
InitializeComponent();
}
After that you can go with this code as you are going.
Form1 formMedici = new Form1(listaPacienti);
Move the instantiation of Form1 and listaPacienti into the constructor. This existing answer provides a good description of why you are getting this error - A field initializer cannot reference the nonstatic field, method, or property.
public partial class Form2 : Form
{
List<Pacient>listaPacienti;
Pacient p1 = new Pacient(0, "Pacient1", 0, 200);
Pacient p2 = new Pacient(1, "Pacienct2", 0, 100);
Form1 formMedici;
public Form2()
{
listaPacienti=new List<Pacient>();
formMedici = new Form1(listaPacienti);
InitializeComponent();
listaPacienti.Add(p1);
listaPacienti.Add(p2);
}
}
You can do the following
Sender Form:
private void btnIniciar_Click(object sender, EventArgs e)
{
this.Hide();
Main newMain = new Main(this.lsProcesos);
newMain.ShowDialog();
this.Show();
}
Receiver Form:
public partial class Main : Form
{
List<Proceso> lsProcesos;
public Main(object sender)
{
InitializeComponent();
lsProcesos = (List<Proceso>)sender;
}
}
i am working on a project, i am creating a instance and opening a specific form in my program, like i use following code to open a form:
frm2 cs = new frm2();
cs.Show();
but the problem here is each time i click on the button it just open a new windows and the previous one is also opened, all i want to do here is when i click on button and that window is already open then it simply go to already opened windows except opening the new one.
hope you guys understand my question and will help me doing it.
EDIT:
i tried this code : the code i wrote in frm2.cs file is:
public partial class frm2 : Form
{
private static frm2 _form2 = null;
public frm2()
{
InitializeComponent();
}
public static frm2 Instance
{
get
{
if (_form2 == null)
{
_form2 = new frm2();
}
return _form2;
}
}
and in frmMain.cs file where i code to access the instance and open the project is :
private void addProductToolStripMenuItem_Click(object sender, EventArgs e)
{
frm2.Instance.Show();
//frm2 cs = new frm2();
//cs.Show();
}
it work fine the first time, but when i open the frm2 , close it and then again try to open it the compiler give error at frm2.Instance.Show(); and the error comes is
: Cannot access a disposed object.
Object name: 'frm2'.
Save the instance of the form opened in a global class variable and then, if this variable is not null just call Show instead of opening againg. Some tips should be followed though
public class Form1: Form
{
private frm2 _currentInstance = null;
....
if(_currentInstance == null)
{
_currentInstance = new frm2();
_currentInstance.FormClosed += instanceHasBeenClosed;
_currentInstance.Show();
}
_currentInstance.BringToFront();
....
private void instanceHasBeenClosed(object sender, FormClosedEventArgs e)
{
_currentInstance = null;
}
}
It is important to subscribe to the FormClosed event for the _currentInstance. In this way your Form1 will be notified when your user closes the instance. And you could reset the internal variable to null, so at the subsequent click you could reopen again the instance
There is also the possibility to use the Application.OpenForms collection to check if your form is shown
frm2 f = Application.OpenForms["NameOfForm2"];
if(f != null)
f.BringToFront();
else
{
frm2 f = new frm2();
f.Show();
}
I know you don't want to write that much code but it seems this is the only way to go.
At least, you can separate that code from your forms by writing a generic code.
var f = FormManager.Show<Form2>(); //create a new form.
f = FormManager.Show<Form2>(); //show the existing form.
f.Close();
f = FormManager.Show<Form2>(); //create a new form
public static class FormManager
{
static Dictionary<Type, Form> _Forms = new Dictionary<Type, Form>();
public static T Show<T>() where T: Form, new()
{
var type = typeof(T);
Form f = null;
if(_Forms.TryGetValue(type,out f))
{
f.BringToFront();
}
else
{
f = new T();
f.FormClosing += (s, e) => _Forms.Remove(s.GetType());
_Forms.Add(type, f);
f.Show();
}
return (T)f;
}
}
you can use singleton design pattern to return always the same instance
public partial class Form2 : Form
{
private static Form2 _form2 = null;
private Form2()
{
InitializeComponent();
}
public static Form2 Instance
{
get
{
if (_form2 == null)
{
_form2 = new Form2();
}
return _form2;
}
}
}
// use this to call the instance
Form2.Instance.Show();
Singleton pattern may be a way to go - just apply it to windows forms (you can check this link for the description of the singleton pattern in C#: http://msdn.microsoft.com/en-us/library/ff650316.aspx).
Check on multiple buttons in that Form is open or not:
private bool isOpen(string name)
{
IsOpen = false;
foreach (Form f in Application.OpenForms)
{
if (f.Text == name)
{
IsOpen = true;
f.Focus();
break;
}
}
if (IsOpen == false)
{
return IsOpen;
}
return IsOpen;
}
Call this in the button click to Check the current Form:
if (isOpen("Item Import Master")) ;
else
{
Item_Import_Master obj1 = new Item_Import_Master();
obj1.Show();
}
You need to check if a form is Disposed before you show it again, otherwise you get Cannot access a disposed object exeption
something like this should work
private static AdvancedRDSWindow form2;
private AdvancedRDSWindow()
{
InitializeComponent();
}
public static AdvancedRDSWindow Instance
{
get
{
if (form2 == null || form2.IsDisposed)
{
form2 = new AdvancedRDSWindow();
}
return form2;
and then you can show it with a button for instance
private void AdvancedRDS_Click(object sender, EventArgs e)
{
AdvancedRDSWindow.Instance.Show();
}
Use this code in the button click event
If the form is already opened, it will bring the form to front
# Here is my code.. #
foreach (Form form in Application.OpenForms)
{
if (form.GetType() == typeof(frm2))
{
form.Activate();
return;
}
}
frm2 frm = new frm2();
frm.Show();
public void IsOpen(Form f)
{
bool open = false;
FormCollection fc = Application.OpenForms;
foreach (Form form in fc)
{
if (form == f)
{
if (form.WindowState == FormWindowState.Minimized)
{
form.WindowState = FormWindowState.Normal;
}
form.BringToFront();
open = true;
}
}
if (open == false)
{
f = new Form();
f.Show();
}
}
So i've got this bit of code here. It's meant to check the open forms in the application and determine if a form is already open. Now i'm using this because there's a couple of forms I don't want opened twice at the same time. My issue being is that I can't open the type of form that i want. I want to get the formtype of F and open the form of that specific type. Ex:
private void mnuSettings_Click(object sender, EventArgs e)
{
Settings set = new Settings();
IsOpen(set);
}
So i pass the form here, so f should equal the settings form. But I need the method to dynamically open different forms. So say I use Form1 instead of settings, I need to open an instance of Form1 if it's not open. Any help is greatly appreciated.
public Dictionary<Type, Form> forms = new Dictionary<Type, Form>();
public void OpenSingletonForm<T>() where T : Form, new() {
if (!forms.ContainsKey(typeof(T)) {
forms.Add(typeof(T), new T());
}
forms[typeof(T)].Show();
}
And use it like so:
OpenSingletonForm<SettingsDialog>();
This is my form 2, this is where the checkboxes are.
My operator in here which is on the middle, has a random character generator, which my code is this :
char[] select = new char[] { '+', '-', '/', '%', '*' };
var rand = new Random();
char num = select[rand.Next(5)];
lbloperator.Text = Convert.ToString(num);
If the only check is addition, my form 1 will only perform addition, or if add,subtract, my form 1 will only perform add and subtract. Please help me with this! :(
FORM1
There is tow ways to do that:
1- first way is define public property in form2 that can tell form1 the status of checkBox1:
Form2:
public bool MyCheckBoxStatus
{
get {return checkBox1.Checked;}
}
Form 1 (For Example):
Form2 frm = new Form2;
frm.ShowDialog();
if (frm.MyCheckBoxStatus)
{
//Do something...
}
2- The other way: if you are using Windows Forms Application then all your controls have a property named Modifiers change its value to public and write this code in Form1:
Form2 frm = new Form2;
frm.ShowDialog();
if (frm.checkBox1.Checked)
{
//Do something...
}
Try this:
public partial class Form2: Form
{
public string checkBoxSelected = "";
}
public partial class Form1 : Form
{
private void MakeResult()
{
Form2 result = new Form2();
result.checkBoxSelected = "+";
result.Show();
}
}
I'm not too sure exactly what you are asking, but it sounds like you are trying to pass some data between forms.
In Form2, you can add a public property that reads your label
public string TheOperator {
get { return lblOperator.Text; }
}
Then from Form1, you can create a new instance of form2 and then reference the Property when needed.
Form2 fm = new Form2();
fm.Show();
string theOp = fm.TheOperator;
//////////
In response to your edit:
You can add this to Form1, exposing the operator variable there:
public string MyOperator {
get { return lblOperator.Text; }
set {
lblOperator.text = value;
//You can perform any updates to
//your calculations here, or call
//another method to do so
}
}
private void OpenForm2()
{
Form2 frm2 = new Form2(this);
frm2.Show();
}
Then inside of Form2, you pass a reference to Form1 so that you can access the public property:
private Form1 frm;
public New(Form1 _frm)
{
frm = _frm;
}
private void UpdateOperator()
{
//call this method, calculating your operator and then
//set the operator on the first form (variable frm) to
//What you need it to do
frm.MyOperator = lblOperator.Text;
}