manually firing the event in c# - c#

i want to fire an event manually using c#. For instance, say if i want to fire a Form_closing event of Form A from Form B. How to do it ??
After getting some comments. I think i need to explain more on this.
Since my Form A is reference to a .dll which creates a custom taskbar in the desktop,
There is a situation for me to close the that custom taskbar from Form B.
i already tried FormA.Close() from Form B. when i do this, the .dll is unloaded from the app domain and due to this the space occupied by the custom task bar is blocked.
But that is not the case when i click the close button in the custom task bar. when i do this the space is freed up.
This is the reason i want to fire the close event of Form A manually from Form B which will solve my issue.
Thanks.

We did the following in one project:
There was a GlobalNotifier class, which defined events we wanted to use in different modules of the application, like this
public static class GlobalNotifier
{
public static event VoidEventHandler EnvironmentChanged;
public static void OnEnvironmentChanged()
{
if (EnvironmentChanged != null)
{
EnvironmentChanged();
}
}
}
Then, you could raise this event anywhere when you needed to let the rest of the application know that the environment has changed, like this
GlobalNotifier.OnEnvironmentChanged();
And also you could subscribe to this event wherever you wanted to be notified about the fact that the environment has changed.
public ReportingService()
{
GlobalNotifier.EnvironmentChanged += new VoidEventHandler(GlobalNotifier_EnvironmentChanged);
}
void GlobalNotifier_EnvironmentChanged()
{
//reset settings
_reportSettings = null;
}
So, whenever you changed the environment, you raised the event, and everyone who needed to know about that and perform some actions, was notified.
Might be similar to what you need to achieve.
Also, if you need to pass parameters, you can define the event any way you like, basically -
public static event VoidEventHandler<SomeObject, List<OtherObject>> SomethingUpdated;
public static void OnSomethingUpdated(SomeObject sender, List<OtherObject> associations)
{
if (SomethingUpdated != null)
{
SomethingUpdated(sender, associations);
}
}
// ...
MyClass.SomethingUpdated+= new VoidEventHandler<SomeObject, List<OtherObject>>(MyClass_SomethingUpdated);
// ...
void MyClass_SomethingUpdated(SomeObject param1, List<OtherObject> param2)
{
//do something
}

You would call the OnFormClosing() method of the Form class. You can do this with any event that has a paired On...() method.

It sounds to me, from your comments, like you don't want to raise one form's event from the other; you just want to handle one form's event from the other.
Yes, you can do that. FormB needs to have a reference to FormA. There are several ways you can do this; one easy way is to have a FormA type property in your FormB class, like this:
public FormA TheOtherForm { get; set; }
You set that property to your instance of FormA, and then you add the event handler as you've described in the comments.
You don't have to use FormA as the type of your property; any form has the FormClosing event, so you can just use Form as the type if you want.

Close the form. That will raise the event. If you want to raise the event separately from closing the form, you're doing something wrong; move that code to a separate method that you can call from the event and from FormB.
FormAInstance.Close()
Starting with Visual Studio 2005 (.Net 2.0), forms have automatic default instances. It sounds like that's what you're using. You should know that this feature exists mainly for backwards compatibility with VB6. You're really better off creating and using a new instance of the form. When you do that, you should just be able to call the .Close() method on that instance without it's app domain closing.
If you want to re-use this space, you might also try simply .Hide()-ing the form rather than closing it.

Related

Use a NotifyIcon between two forms in C#

I plan to use this method to display a notify icon so it can be accessed between the main form and child forms (found from another SO post)
public partial class MainForm : Form {
public MainForm() {
InitializeComponent();
notifier = this.notifyIcon1;
this.FormClosed += delegate { notifier = null; };
}
public static NotifyIcon Notifier { get { return notifier; } }
private static NotifyIcon notifier;
}
Is it necessary to add the FormClosed delegate? I would think that when the form everything else gets destroyed and freed up?
Edit: For clarification - I can confirm that using the code without the delegate above, when i close the form the system tray icon does disappear, also I did use the VS UI to drag/drop a NotifyIcon from toolbox so designer is handling initialization for me and I am using the constructor like above to access it.
If the notify icon is logically tied to this instance of the form then you shouldn't have it be a static field. Marking it as static is done to specifically say that it's not tied to one instance, but rather is shared between all instances.
I would think that when the form everything else gets destroyed and freed up?
If it were instance data it would be, but because it's static, and therefore not tied to the instance, it will not be cleaned up when the form goes away.
Of course, if this is the main form (and not a misnomer) then the entire application will end when the form closes, which will clean up everything regardless, static or not.
You need to set
nutifier.Visible = false;
notifier = null;
on closing. If not, the icon stays after the application was closed

How to declare an event mandatory

I have a user control that has a contextmenustrip that is displayed on every right click. When the user select an item on this menu, I have to pass this info to the parent control so it can react according to this.
So I need the parent to mandatory subscribe to this event. Is there a way to tell that?
If there is no way to do that, should I throw an exception or just check for null value (of the event handler) and do nothing?
Thanks.
There is no way to enforce this at compile time - meaning that there is nothing in the .NET framework/C# language that can perform static checks at compilation to ensure that this logic is implemented in your code.
At run-time you can perform the necessary validation. For instance you might inspect the invocation list of the delegate to ensure that the parent is in that list.
You can create a specific constructor for your user control to prevent instantiation unless an event handler is given, like this.
public partial class MyUserControl : UserControl {
public MyUserControl (ToolStripItemClickedEventHandler handler) {
InitializeComponent ();
myContextMenuStrip.ItemClicked += handler;
}
}
Do note though: this won't work very well with Visual Studio's form designer, as the form designer generally expects parameter-less constructors. Instead, you need to manually create the control instance from code.

Chain a custom event to be passed back up through multiple forms to the parent

I have a MDImain(Form1) for that handles a custom event generated by children. When I create an instance of a child form I attach the child event to the parent handler. All works great parent catches the event generated by the child. Code in the parent looks like this.
ChildForm instanceChildForm = new ChildForm();
instanceChildForm.Feedback += new EventHandler<feedback>(MainMessageHandler);
then I show the child form... (The Main message handler is in the parent form)
Now I want my child form to show a third form call it child 2. It's instantiated from childForm, but I want the parent MDI to still catch this event. How to I get the vent back to the mdi parent.
All I can think of would be to make the MainMessageHandler routine public on the main form, but then I still need a ref to the main form ... child3.parent = child2parent then attach the event like so:
ChildForm2 instanceChildForm2 = new ChildForm2();
instanceChildForm2.Feedback += new EventHandler<feedback>(this.parent.MainMessageHandler);
or something like that.
OR would this be a good use for a delegate kind of thing? If so I'm not sure how to pull that off.
Thanks for your help !
There's a million and one ways to do it. In my opinion, in any Windows app, you need to be aware of all the forms, their state and be able to past messages between them without creating dependencies. Something like:
public class FormManager
{
List<Form> _forms = new List<Form>();
public void CreateForm<T>() where T : Form, new()
{
var form = new T();
_forms.Add(form);
AttachEvents(form);
form.Show();
}
...methods for attaching events, responding to them, and DETACHING on form.Closed
}
instead of new() ing up forms, you use FormManager.CreateForm<Form1>();
Now, when one of your forms raises an event, you have access to all the forms, both parent and children, and you can make decisions about what to do about that event. You can make those decisions in the FormManager if you want it to be smart, or you can push it down to the forms themselves.

Calling controls from a hidden form in C#

I am designing a Windows form application wherein I need to call, from Form A, a click event for a command button on Form B. Form B needs to remain hidden at all times. It was simple to do this in Visual Basic, I'd just call it like this: "FormName.ControlName.Event/Method".
This isn't working for me now in C#, Visual Studio 8. Can anyone help?
All you need to do is give Form A a reference to Form B. Presumably there is some startup code in your application that is aware of both forms. If so, you could have code like this:
// starting up
FormB b = new FormB();
b.Visible = false;
FormA a = new FormA();
a.FormBInstance = b; // you would have to add the 'FormBInstance' property to Form A class yourself
a.Show();
// Now, if Form A needs to do something with FormB, it just needs to use the FormBInstance property.
Make sense?
Sounds pretty wacky, but with a reference to the instance of Form B and the Button control being made public:
b.myButton.PerformClick();
You should create a public method on FormB that does what you need. This way, you get rid of the need to directly call the click event handler, which is not a great thing to do.
You can't raise events from a different class directly, they have special access level that means you can only subscribe/unsubscribe. You would need method on formB that can raise the event.

Load a form without showing it

Short version: I want to trigger the Form_Load() event without making the form visible. This doesn't work because Show() ignores the current value of the Visible property:
tasksForm.Visible = false;
tasksForm.Show();
Long version: I have a WinForms application with two forms: main and tasks. The main form is always displayed. The user can either click a button to open the tasks form, or click some buttons that just run a task directly without opening the tasks form.
When a user asks to run a task directly, I'd like to just call some public methods on the tasks form without showing it. Unfortunately, the task logic depends on stuff that happens in the Form_Load() event. The only way I can find to trigger Form_Load() is to call Show(). The best I've been able to do is to show the form in the minimized state:
tasksForm.WindowState = FormWindowState.Minimized;
tasksForm.Show();
I suppose the cleanest solution would be to pull the tasks logic out of the tasks form and into a controller class. Then I can use that class from the main form and from the tasks form, and only load the tasks form when I need it visible for the user. However, if it's an easy thing to load the form without displaying it, that would be a smaller change.
Perhaps it should be noted here that you can cause the form's window to be created without showing the form. I think there could be legitimate situations for wanting to do this.
Anyway, good design or not, you can do that like this:
MyForm f = new MyForm();
IntPtr dummy = f.Handle; // forces the form Control to be created
I don't think this will cause Form_Load() to be called, but you will be able to call f.Invoke() at this point (which is what I was trying to do when I stumbled upon this SO question).
It sounds to me like you need to sit down and re-think your approach here. I cannot imagine a single reason your public methods need to be in a form if you are not going to show it. Just make a new class.
I totally agree with Rich B, you need to look at where you are placing your application logic rather than trying to cludge the WinForms mechanisms. All of those operations and data that your Tasks form is exposing should really be in a separate class say some kind of Application Controller or something held by your main form and then used by your tasks form to read and display data when needed but doesn't need a form to be instantiated to exist.
It probably seems a pain to rework it, but you'll be improving the structure of the app and making it more maintainable etc.
From MSDN:
Form.Load
Occurs before a form is displayed for the first time.
Meaning the only thing that would cause the form to load, is when it is displayed.
Form.Show(); and Form.Visible = true; are the exact same thing. Basically, behind the scenes, Show checks for various conditions, then sets Visible to true. So obviously, setting visible to false (which it already is) before showing the form is meaningless.
But let's forget the technicalities. I completely agree with Rich B and Shaun Austin - the logic shouldn't be in that form anyway.
Sometimes this would be useful without it being bad design. Sometimes it could be the start of a migration from native to managed.
If you were migrating a c++ app to .NET for example, you may simply make yourwhole app a child window of the .NET form or panel, and gradually migrate over to the .NET by getting rid of your c++ app menu, status bar, toolbar and mapping teh .NEt ones to your app using platform invoke etc...
Your C++ app may take a while to load, but the .NET form doesn't..in which you may like to hide the .NEt form until your c++ app has initialised itself.
I'd set opacity=0 and visible=false to false after calling show, then when your c++ app loads, then reverse.
If you make the method public, then you could access it directly.... however, there could be some unexpected side effects when you call it. But making it public and calling it directly will not draw the screen or open the form.
Move mandatory initialization code for the form class out of the Load event handler into the constructor. For a Form class, instantiation of an instance (via the constructor), form loading and form visibility are three different things, and don't need to happen at the same time (although they do obviously need to happen in that order).
None of the answers solved the original question, so, add the below, call .Show() to load the form without showing it, then call .ShowForm() to allow it to be visible if you want to after:
private volatile bool _formVisible;
protected override void SetVisibleCore(bool value)
{
base.SetVisibleCore(_formVisible);
}
public void ShowForm()
{
_formVisible = true;
if (InvokeRequired)
{
Invoke((Action) Show);
}
else
{
Show();
}
}

Categories