Close form currently in focus - c#

I was wondering how you would close the Form that is currently in focus or the one which a control is contained in. For example, I have an imported header with a menu that I import into all forms in my application.
This is the (simplified) code in my Header class:
public static Panel GetHeader()
{
...
menuItem.Text = "Menu Item";
menuItem.Name = "Next form to open";
menuItem.Click += toolStrip_Click;
...
}
public static void toolStrip_Click(object sender, EventArgs e)
{
ToolStripMenuItem menuItem = sender as ToolStripMenuItem;
NavigationClass.SaveNextForm(menuItem.Name);
}
The navigation class is just something I made which will select the next form to open but I couldn't find anything to then close the current one (since Close() isn't an option due to it being imported with Controls.Add(HeaderClass.GetHeader))
Edit
Just to make clear, this form is in another file which is just a normal class file. That's where the difficulty lies because I'm trying to avoid a severe violation of the DRY principle

Don't use static handlers as #Hans Passant suggests. That is important.
Try sending your main form to your class as a parameter, and store it in that class. This can be done either when you are instantiating your class, or after that. Then, when you need to close the form, call it's Close method. Since you don't include your codes in more details, here is my example with some assumptions.
public class MainForm : Form
{
private HeaderClass HeaderClass;
public MainForm()
{
HeaderClass = new HeaderClass(this);
}
}
public class HeaderClass
{
private MainForm MainForm;
public HeaderClass(MainForm mainForm)
{
MainForm = mainForm;
}
public void MethodThatYouNeedToCloseTheFormFrom()
{
...
MainForm.Close();
...
}
}
Let us know if you require any more elaboration.

Related

C# Forms: Help in referencing existing class instead of creating new instance every time [duplicate]

I have two forms, one is the main form and the other is an options form. So say for example that the user clicks on my menu on the main form: Tools -> Options, this would cause my options form to be shown.
My question is how can I send data from my options form back to my main form? I know I could use properties, but I have a lot of options and this seems like an tedious odd thing to do.
So what is the best way?
Form1 triggers Form2 to open. Form2 has overloaded constructor which takes calling form as argument and provides its reference to Form2 members. This solves the communication problem. For example I've exposed Label Property as public in Form1 which is modified in Form2.
With this approach you can do communication in different ways.
Download Link for Sample Project
//Your Form1
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 frm = new Form2(this);
frm.Show();
}
public string LabelText
{
get { return Lbl.Text; }
set { Lbl.Text = value; }
}
}
//Your Form2
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private Form1 mainForm = null;
public Form2(Form callingForm)
{
mainForm = callingForm as Form1;
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
this.mainForm.LabelText = txtMessage.Text;
}
}
(source: ruchitsurati.net)
(source: ruchitsurati.net)
In the comments to the accepted answer, Neeraj Gulia writes:
This leads to tight coupling of the forms Form1 and Form2, I guess instead one should use custom events for such kind of scenarios.
The comment is exactly right. The accepted answer is not bad; for simple programs, and especially for people just learning programming and trying to get basic scenarios to work, it's a very useful example of how a pair of forms can interact.
However, it's true that the coupling that example causes can and should be avoided, and that in the particular example, an event would accomplish the same thing in a general-purpose, decoupled way.
Here's an example, using the accepted answer's code as the baseline:
Form1.cs:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 frm = new Form2();
frm.Button1Click += (s1, e1) => Lbl.Text = ((Form2)s1).Message;
frm.Show();
}
}
The above code creates a new instance of Form2, and then before showing it, adds an event handler to that form's Button1Click event.
Note that the expression (s1, e1) => Lbl.Text = ((Form2)s1).Message is converted automatically by the compiler to a method that looks something similar to (but definitely not exactly like) this:
private void frm_Message(object s1, EventArgs e1)
{
Lbl.Text = ((Form2)s1).Message;
}
There are actually lots of ways/syntaxes to implement and subscribe the event handler. For example, using an anonymous method as the above, you don't really need to cast the sender parameter; instead you can just use the frm local variable directly: (s1, e1) => Lbl.Text = frm.Message.
Going the other way, you don't need to use an anonymous method. You could in fact just declare a regular method just like the compiler-generated one I show above, and then subscribe that method to the event: frm.Button1Click += frm_Message; (where you have of course used the name frm_Message for the method, just as in my example above).
Regardless of how you do it, of course you will need for Form2 to actually implement that Button1Click event. That's very simple…
Form2.cs:
public partial class Form2 : Form
{
public event EventHandler Button1Click;
public string Message { get { return txtMessage.Text; } }
public Form2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
EventHandler handler = Button1Click;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
}
In addition to the event, I've also declared a property Message that exposes the Text property (and only the Text property, and only as read-only in fact) of the txtMessage control. This allows the subscriber to the event to get the value and do whatever it needs to with it.
Note that all that the event does is to alert the subscriber that the button has in fact been clicked. It's up to the subscriber to decide how to interpret or react to that event (e.g. by retrieving the value of the Message property and assigning it to something).
Alternatively, you could in fact deliver the text along with the event itself, by declaring a new EventArgs sub-class and using that for the event instead:
public class MessageEventArgs : EventArgs
{
public string Message { get; private set; }
public MessageEventArgs(string message)
{
Message = message;
}
}
public partial class Form2 : Form
{
public event EventHandler<MessageEventArgs> Button1Click;
public Form2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
EventHandler handler = Button1Click;
if (handler != null)
{
handler(this, new MessageEventArgs(txtMessage.Text));
}
}
}
Then the subscriber can just retrieve the message value directly from the event object:
frm.Button1Click += (sender, e) => Lbl.Text = e.Message;
The important thing note in all of the above variations is that at no point does the class Form2 need to know anything about Form1. Having Form1 know about Form2 is unavoidable; after all, that's the object that will create a new Form2 instance and use it. But the relationship can be asymmetrical, with Form2 being usable by any object that needs the features it offers. By exposing the functionality as an event (and optionally with a property), it makes itself useful without limiting its usefulness to only the Form1 class.
The best in this case would be to have some OptionsService class/interface that is accessible via IServiceProvider.
Just add an event when something changes, and the rest of the app can respond to it.
There are lots of ways to perform communication between two Forms.
Some of them have already been explained to you. I am showing you the other way around.
Assuming you have to update some settings from the child form to the parent form. You can make use of these two ways as well :
Using System.Action (Here you simply pass the main forms function as the parameter to the child form like a callback function)
OpenForms Method ( You directly call one of your open forms)
Using System.Action
You can think of it as a callback function passed to the child form.
// -------- IN THE MAIN FORM --------
// CALLING THE CHILD FORM IN YOUR CODE LOOKS LIKE THIS
Options frmOptions = new Options(UpdateSettings);
frmOptions.Show();
// YOUR FUNCTION IN THE MAIN FORM TO BE EXECUTED
public void UpdateSettings(string data)
{
// DO YOUR STUFF HERE
}
// -------- IN THE CHILD FORM --------
Action<string> UpdateSettings = null;
// IN THE CHILD FORMS CONSTRUCTOR
public Options(Action<string> UpdateSettings)
{
InitializeComponent();
this.UpdateSettings = UpdateSettings;
}
private void btnUpdate_Click(object sender, EventArgs e)
{
// CALLING THE CALLBACK FUNCTION
if (UpdateSettings != null)
UpdateSettings("some data");
}
OpenForms Method
This method is easy (2 lines). But only works with forms that are open.
All you need to do is add these two lines where ever you want to pass some data.
Main frmMain = (Main)Application.OpenForms["Main"];
frmMain.UpdateSettings("Some data");
Properties is one option, shared static class - another option, events - another option...
You might try AutoMapper. Keep your options in a separate class and then use AutoMapper to shuttle the data between the class and the form.
Create a Class and put all your properties inside the class .. Create a Property in the parent class and set it from your child (options) form
You can have a function in Form B like so:
public SettingsResults GetNewSettings()
{
if(this.ShowDialog() == DialogResult.Ok)
{
return new SettingsResult { ... };
}
else
{
return null;
}
}
And you can call it like this:
...
using(var fb = new FormB())
{
var s = fb.GetNewSettings();
...
// Notify other parts of the application that settings have changed.
}
MVC, MVP, MVVM -- slight overkill for someone admittedly saying they want tutorials. Those are theories that have entire courses dedicated to them.
As already posted, passing an object around is probably easiest. If treating a class as an object (interchangeable in this sense) is new, then you may want to spend another 2-4 weeks figuring out properties and constructors and such.
I'm not a C# master by any means, but these concepts need to be pretty concrete if you want to go much further beyond passing values between two forms (also classes/objects in their own right). Not trying to be mean here at all, it just sounds like you're moving from something like VB6 (or any language with globals) to something far more structured.
Eventually, it will click.
This is probably sidestepping your problem a little bit, but my settings dialog uses the Application Settings construct. http://msdn.microsoft.com/en-us/library/k4s6c3a0.aspx
I can't find a good example that's similar to how I do it (which is actually having an actual class+object), but this covers another way of doing it:
Reading default application settings in C#
A form is a class, just like any other class. Add some public variables to your form class and set them when they click the button to close the form (technically they are just hiding it).
A VB.NET example, but you'll get the idea -
In your OptionsForm class:
Public Option1 as String = ""
etc. Set them when they hit the "Ok" button.
So in your main form, when they hit the "options" button - you create your options form:
OptionsForm.ShowDialog()
when it exits, you harvest your option settings from the public variables on the form:
option1 = OptionsForm.Option1
etc.
The best way to deal with communication between containers is to implement an observer class
The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.
(Wikipedia)
the way i do this is creating an Observer class, and inside it write something like this:
1 public delegate void dlFuncToBeImplemented(string signal);
2 public static event dlFuncToBeImplemented OnFuncToBeImplemented;
3 public static void FuncToBeImplemented(string signal)
4 {
5 OnFuncToBeImplemented(signal);
6 }
so basically: the first line says that there would be a function that somebody else will implement
the second line is creating an event that occurs when the delegated function will call
and the third line is the creation of the function that calls the event
so in your UserControl, you should add a function like this:
private void ObserverRegister()//will contain all observer function registration
{
Observer.OnFuncToBeImplemented += Observer_OnFuncToBeImplemented;
/*and more observer function registration............*/
}
void Observer_OnFuncToBeImplemented(string signal)//the function that will occur when FuncToBeImplemented(signal) will call
{
MessageBox.Show("Signal "+signal+" received!", "Atention!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
and in your Form you should do something like:
public static int signal = 0;
public void button1_Click(object sender, EventArgs e)
{
Observer.FuncToBeImplemented(signal);//will call the event in the user control
}
and now, you can register this function to a whole bunch of other controls and containers and they will all get the signal
I hope this would help :)

Using Extensions with the Static Class System.Windows.Forms

I'm new to C# so bear with me, I'm trying to add methods to the Forms class so that I can show and hide other forms from within a different form if that makes sense. In my extension I have:
namespace ExtensionMethods
{
public static partial class FormExtentsion : Form
{
public static void HideForm(this Form frm)
{
frm.Hide();
}
public static void UnhideForm(this Form frm)
{
frm.Show();
}
}
}
And in my project I have:
private void bnTrBack_Click(objects sender, EventArgs e)
{
Main.UnhideForm();
this.Close();
}
Where Main is my main form. Is there a way to have a form open/close another form? Any help is much appreciated!!
As #CEvenhuis pointed out in a question comment, you need an instance of the main form.
(And, you don't need extension methods at all. Never do—They just allow calling code to look and feel different. But, in this case, in the code you've shown, you are just giving pet names to well-known, existing methods.)
Anyway, in the "child" form, you could have a field to refer to the instance of the main form.
Form _parent;
And use it like
private void bnTrBack_Click(objects sender, EventArgs e)
{
_parent.Show();
Close();
}
Or, assuming the child is only ever a child of the main form,
Main _main;
private void bnTrBack_Click(objects sender, EventArgs e)
{
_main.Show();
Close();
}
The question would be how to set the field.
It can be set in a constructor:
ReadOnly Main _main;
And change the designer-generated code from:
public Child()
{
InitializeComponent();
}
to
public Child(Main main)
{
InitializeComponent();
_main = main;
}
Stepping back a bit, instead of hiding the main form, you could instead—if appropriate— show the child form as a modal dialog and receive back a simple result after it closes:
var result = new Child().ShowDialog();
In general, there are two things to evaluate concerning the options:
User experience: Are the controls presented to the users in a way they can understand and in a way that allows them to follow desired workflows?
Coupling between classes: Which classes depend on which classes and in what way? Is there a good plan for passing data and control?

How can I make my Form Control variables acessible to classes other than my Form class?

For example after creating a new Windows Form project I have my class called Form1.cs and from that form I can simply start typing the name of a form control and it will auto populate the form control variable names and I am able to use them in the class. However I have other classes that need to be able to access these form control variables as well, but they are not accessible.
Make them public if they are going to be used in another assembly, or internal if they are going to be used in the same project. Making them static means you don't have to pass your Form1 into the other classes.
Example... Say your Form1 has a string that contains the text you display in the title bar. Making it internal static, like this:
internal static readonly string MsgBox_Title = " Best Application Evar!";
lets you access it from other classes like this:
Form1.MsgBox_Title
It doesn't have to be readonly; that's just an example I pulled from an old app...
If you don't want static variables, you'll have to pass in an instance of Form1.
public class SomeClass
{
private Form1 m_Form1;
public SomeClass(Form1 form1)
{
m_Form1 = form1;
}
private void someMethod()
{
string localValue = m_Form1.SomeMemberStringVariable;
}
}
It's a very contrived example, but hopefully you get the idea.
If you want to call the Refresh method from a class instantiated from Form1, you could use an event in the child class to notify Form1.
Example:
This Form1 has a button that I use to show a secondary form.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnShowPopup_Click(object sender, EventArgs e)
{
PopupForm f = new PopupForm();
f.CallRefreshHandler += PopupForm_CallRefreshHandler;
f.ShowDialog();
}
private void PopupForm_CallRefreshHandler(object sender, EventArgs e)
{
Refresh();
}
}
The secondary form, "PopupForm", has a button that I use to raise an event that the Form1 is subscribed to, and lets Form1 know to call Refresh.
public partial class PopupForm : Form
{
public event EventHandler CallRefreshHandler;
public PopupForm()
{
InitializeComponent();
}
private void btnRaiseEvent_Click(object sender, EventArgs e)
{
EventHandler handler = CallRefreshHandler;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
}
Hope this helps.
Create an object of that class & start using those variables like this
Form1 fm = new Form1();
string abc = fm.VAR;
Define a public property in your form.
public string MyProp { get; set; }
Form1 frm = new Form1();
frm.MyProp = "Value";
Or define the property as static to avoid having to instantiate Form1:
public static string MyProp { get; set; }
Form1.MyProp = "Value";
I ran into this issue recently. I was keeping some methods in a separate class. Maybe not a good design decision in my case, I'm not sure yet. And these methods sometimes needed to communicate with controls in the main Form1. For example, to write to textBox1.
Turns out easy enough. Just write your method signature to include a TextBox instance. For example you pass textBox1 in and inside the method you refer to it as tb. Then when you call that method (even though it is in another class) you set the tb.Text property to whatever you like and it will show on textBox1.
This makes sense when you consider that control is just a special kind of object, graphically represented in the Form. When you pass it as an argument to a method in another class or the same class, you are actually passing the reference. So writing text to it in the method call will write text to the original control.

Passing directory structure to another form [duplicate]

I have two forms, one is the main form and the other is an options form. So say for example that the user clicks on my menu on the main form: Tools -> Options, this would cause my options form to be shown.
My question is how can I send data from my options form back to my main form? I know I could use properties, but I have a lot of options and this seems like an tedious odd thing to do.
So what is the best way?
Form1 triggers Form2 to open. Form2 has overloaded constructor which takes calling form as argument and provides its reference to Form2 members. This solves the communication problem. For example I've exposed Label Property as public in Form1 which is modified in Form2.
With this approach you can do communication in different ways.
Download Link for Sample Project
//Your Form1
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 frm = new Form2(this);
frm.Show();
}
public string LabelText
{
get { return Lbl.Text; }
set { Lbl.Text = value; }
}
}
//Your Form2
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private Form1 mainForm = null;
public Form2(Form callingForm)
{
mainForm = callingForm as Form1;
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
this.mainForm.LabelText = txtMessage.Text;
}
}
(source: ruchitsurati.net)
(source: ruchitsurati.net)
In the comments to the accepted answer, Neeraj Gulia writes:
This leads to tight coupling of the forms Form1 and Form2, I guess instead one should use custom events for such kind of scenarios.
The comment is exactly right. The accepted answer is not bad; for simple programs, and especially for people just learning programming and trying to get basic scenarios to work, it's a very useful example of how a pair of forms can interact.
However, it's true that the coupling that example causes can and should be avoided, and that in the particular example, an event would accomplish the same thing in a general-purpose, decoupled way.
Here's an example, using the accepted answer's code as the baseline:
Form1.cs:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 frm = new Form2();
frm.Button1Click += (s1, e1) => Lbl.Text = ((Form2)s1).Message;
frm.Show();
}
}
The above code creates a new instance of Form2, and then before showing it, adds an event handler to that form's Button1Click event.
Note that the expression (s1, e1) => Lbl.Text = ((Form2)s1).Message is converted automatically by the compiler to a method that looks something similar to (but definitely not exactly like) this:
private void frm_Message(object s1, EventArgs e1)
{
Lbl.Text = ((Form2)s1).Message;
}
There are actually lots of ways/syntaxes to implement and subscribe the event handler. For example, using an anonymous method as the above, you don't really need to cast the sender parameter; instead you can just use the frm local variable directly: (s1, e1) => Lbl.Text = frm.Message.
Going the other way, you don't need to use an anonymous method. You could in fact just declare a regular method just like the compiler-generated one I show above, and then subscribe that method to the event: frm.Button1Click += frm_Message; (where you have of course used the name frm_Message for the method, just as in my example above).
Regardless of how you do it, of course you will need for Form2 to actually implement that Button1Click event. That's very simple…
Form2.cs:
public partial class Form2 : Form
{
public event EventHandler Button1Click;
public string Message { get { return txtMessage.Text; } }
public Form2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
EventHandler handler = Button1Click;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
}
In addition to the event, I've also declared a property Message that exposes the Text property (and only the Text property, and only as read-only in fact) of the txtMessage control. This allows the subscriber to the event to get the value and do whatever it needs to with it.
Note that all that the event does is to alert the subscriber that the button has in fact been clicked. It's up to the subscriber to decide how to interpret or react to that event (e.g. by retrieving the value of the Message property and assigning it to something).
Alternatively, you could in fact deliver the text along with the event itself, by declaring a new EventArgs sub-class and using that for the event instead:
public class MessageEventArgs : EventArgs
{
public string Message { get; private set; }
public MessageEventArgs(string message)
{
Message = message;
}
}
public partial class Form2 : Form
{
public event EventHandler<MessageEventArgs> Button1Click;
public Form2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
EventHandler handler = Button1Click;
if (handler != null)
{
handler(this, new MessageEventArgs(txtMessage.Text));
}
}
}
Then the subscriber can just retrieve the message value directly from the event object:
frm.Button1Click += (sender, e) => Lbl.Text = e.Message;
The important thing note in all of the above variations is that at no point does the class Form2 need to know anything about Form1. Having Form1 know about Form2 is unavoidable; after all, that's the object that will create a new Form2 instance and use it. But the relationship can be asymmetrical, with Form2 being usable by any object that needs the features it offers. By exposing the functionality as an event (and optionally with a property), it makes itself useful without limiting its usefulness to only the Form1 class.
The best in this case would be to have some OptionsService class/interface that is accessible via IServiceProvider.
Just add an event when something changes, and the rest of the app can respond to it.
There are lots of ways to perform communication between two Forms.
Some of them have already been explained to you. I am showing you the other way around.
Assuming you have to update some settings from the child form to the parent form. You can make use of these two ways as well :
Using System.Action (Here you simply pass the main forms function as the parameter to the child form like a callback function)
OpenForms Method ( You directly call one of your open forms)
Using System.Action
You can think of it as a callback function passed to the child form.
// -------- IN THE MAIN FORM --------
// CALLING THE CHILD FORM IN YOUR CODE LOOKS LIKE THIS
Options frmOptions = new Options(UpdateSettings);
frmOptions.Show();
// YOUR FUNCTION IN THE MAIN FORM TO BE EXECUTED
public void UpdateSettings(string data)
{
// DO YOUR STUFF HERE
}
// -------- IN THE CHILD FORM --------
Action<string> UpdateSettings = null;
// IN THE CHILD FORMS CONSTRUCTOR
public Options(Action<string> UpdateSettings)
{
InitializeComponent();
this.UpdateSettings = UpdateSettings;
}
private void btnUpdate_Click(object sender, EventArgs e)
{
// CALLING THE CALLBACK FUNCTION
if (UpdateSettings != null)
UpdateSettings("some data");
}
OpenForms Method
This method is easy (2 lines). But only works with forms that are open.
All you need to do is add these two lines where ever you want to pass some data.
Main frmMain = (Main)Application.OpenForms["Main"];
frmMain.UpdateSettings("Some data");
Properties is one option, shared static class - another option, events - another option...
You might try AutoMapper. Keep your options in a separate class and then use AutoMapper to shuttle the data between the class and the form.
Create a Class and put all your properties inside the class .. Create a Property in the parent class and set it from your child (options) form
You can have a function in Form B like so:
public SettingsResults GetNewSettings()
{
if(this.ShowDialog() == DialogResult.Ok)
{
return new SettingsResult { ... };
}
else
{
return null;
}
}
And you can call it like this:
...
using(var fb = new FormB())
{
var s = fb.GetNewSettings();
...
// Notify other parts of the application that settings have changed.
}
MVC, MVP, MVVM -- slight overkill for someone admittedly saying they want tutorials. Those are theories that have entire courses dedicated to them.
As already posted, passing an object around is probably easiest. If treating a class as an object (interchangeable in this sense) is new, then you may want to spend another 2-4 weeks figuring out properties and constructors and such.
I'm not a C# master by any means, but these concepts need to be pretty concrete if you want to go much further beyond passing values between two forms (also classes/objects in their own right). Not trying to be mean here at all, it just sounds like you're moving from something like VB6 (or any language with globals) to something far more structured.
Eventually, it will click.
This is probably sidestepping your problem a little bit, but my settings dialog uses the Application Settings construct. http://msdn.microsoft.com/en-us/library/k4s6c3a0.aspx
I can't find a good example that's similar to how I do it (which is actually having an actual class+object), but this covers another way of doing it:
Reading default application settings in C#
A form is a class, just like any other class. Add some public variables to your form class and set them when they click the button to close the form (technically they are just hiding it).
A VB.NET example, but you'll get the idea -
In your OptionsForm class:
Public Option1 as String = ""
etc. Set them when they hit the "Ok" button.
So in your main form, when they hit the "options" button - you create your options form:
OptionsForm.ShowDialog()
when it exits, you harvest your option settings from the public variables on the form:
option1 = OptionsForm.Option1
etc.
The best way to deal with communication between containers is to implement an observer class
The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.
(Wikipedia)
the way i do this is creating an Observer class, and inside it write something like this:
1 public delegate void dlFuncToBeImplemented(string signal);
2 public static event dlFuncToBeImplemented OnFuncToBeImplemented;
3 public static void FuncToBeImplemented(string signal)
4 {
5 OnFuncToBeImplemented(signal);
6 }
so basically: the first line says that there would be a function that somebody else will implement
the second line is creating an event that occurs when the delegated function will call
and the third line is the creation of the function that calls the event
so in your UserControl, you should add a function like this:
private void ObserverRegister()//will contain all observer function registration
{
Observer.OnFuncToBeImplemented += Observer_OnFuncToBeImplemented;
/*and more observer function registration............*/
}
void Observer_OnFuncToBeImplemented(string signal)//the function that will occur when FuncToBeImplemented(signal) will call
{
MessageBox.Show("Signal "+signal+" received!", "Atention!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
and in your Form you should do something like:
public static int signal = 0;
public void button1_Click(object sender, EventArgs e)
{
Observer.FuncToBeImplemented(signal);//will call the event in the user control
}
and now, you can register this function to a whole bunch of other controls and containers and they will all get the signal
I hope this would help :)

Showing a hidden form

How do i show a from that have been hidden using
this.Hide();
I have tried
MainMenuForm.Show();
and this just says i need an object ref. I then tried:
MainMenuForm frmMainMenu = new MainMenuForm();
frmMainMenu.Show();
Which seems to show the appropriate form. But when you exit the app, it is still held in memory because it hasn't shown the form that was hidden, instead it has shown a new version of the form. In effect having 2 instances of the form (one hidden, one visible).
Just to clarify, the MainMenuForm is the startup form. When (for example) Option 1 is clicked, the MainMenuForm then hides itself while opening up the Option 1 form. What i would like to know is how to i make the Option 1 form that the MainMenuForm opens "unhide" the MainMenuForm and then close itself.
What's the correct procedure here?
Thanks in advance.
When you do the following:
MainMenuForm frmMainMenu = new MainMenuForm();
frmMainMenu.Show();
You are creating and showing a new instance of the MainMenuForm.
In order to show and hide an instance of the MainMenuForm you'll need to hold a reference to it. I.e. when I do compact framework apps, I have a static classes using the singleton pattern to ensure I only ever have one instance of a form at run time:
public class FormProvider
{
public static MainMenuForm MainMenu
{
get
{
if (_mainMenu == null)
{
_mainMenu = new MainMenuForm();
}
return _mainMenu;
}
}
private static MainMenuForm _mainMenu;
}
Now you can just use FormProvider.MainMenu.Show() to show the form and FormProvider.MainMenu.Hide() to hide the form.
The Singleton Pattern (thanks to Lazarus for the link) is a good way of managing forms in WinForms applications because it means you only create the form instance once. The first time the form is accessed through its respective property, the form is instantiated and stored in a private variable.
For example, the first time you use FormProvider.MainMenu, the private variable _mainMenu is instantiated. Any subsequent times you call FormProvider.MainMenu, _mainMenu is returned straight away without being instantiated again.
However, you don't have to store all your form classes in a static instance. You can just have the form as a property on the form that's controlling the MainMenu.
public partial class YourMainForm : Form
{
private MainMenuForm _mainMenu = new MainMenuForm();
protected void ShowForm()
{
_mainMenu.Show();
}
protected void HideForm()
{
_mainMenu.Hide();
}
}
UPDATE:
Just read that MainMenuForm is your startup form. Implement a class similar to my singleton example above, and then change your code to the following in the Program.cs file of your application:
Application.Run(FormProvider.MainMenu);
You can then access the MainMenuForm from anywhere in your application through the FormProvider class.
The simplest and easiest way is to use LINQ and look into the Application.OpenForms property. I'm assuming you have only 1 instance of the form (hopefully!), otherwise make sure to have to have some public property on the hidden form to be able to differentiate it.
The following code will un-hide the form for you:
var formToShow = Application.OpenForms.Cast<Form>()
.FirstOrDefault(c => c is MainMenuForm);
if (formToShow != null)
{
formToShow.Show();
}
You need to keep a reference to the first form when it's created and then the code that holds that reference can call Show on it.
If you don't open that form from somewhere but it's set as the startup form, then you either need to change it so that you have a Main method that opens that form or you can have that form store a reference to itself somewhere that can be accessed from other places.
For example, an quick and ugly way would be to, add a public static property to your mainform and then when you hide the form it also writes this to that property which can then be retrieved when needed by other parts of the code.
Practically This works for me....
public class MainWindow : Form
{
Form _mainMenuForm = new MainMenuForm();
}
calling it through a button click event.
private void buttonclick()
{
if (_mainMenuForm.Visible)
{
_mainMenuForm.Visible = false;
}
else
{
_mainMenuForm.Visible = true;
}
}
Store a reference to the form and call .Hide() and .Show() on that.
For example:
public class MainWindow : Form
{
private Form _mainMenuForm = new MainMenuForm();
public void btnShowMenuForm_Click(...)
{
_mainMenuForm.Show();
}
public void btnHideMenuForm_Click(...)
{
_mainMenuForm.Hide();
}
//etc
}
This example assumes you have a form which is launching the MainMenuForm.
Call the referenced form.
Like:
Calling parent
----------
public MyForm f {get;set;}
void DoStuff()
{
f = new MyForm();
f.Show();
}
MyForm
----------
void DoOtherStuff()
{
this.hide();
}
Parent
----------
void UnHideForm()
{
f.show();
}
Another simpler method to achieve this is to loop through the open forms to see which are still running and open it...
foreach (Form oForm in Application.OpenForms)
{
if (oForm is MainMenuForm)
{
oForm.Show();
break;
}
}

Categories