-1

I am trying to write a class NvApplicationContext which inherits from ApplicationContext, in a class library, and which I will use to monitor activity in multiple forms.

public class NvApplicationContext : ApplicationContext {
    // ...

    public NvApplicationContext(Form f) {

    }

    // ...
}

However, I can only seem to pass in one form (an instance of Form1) from my end projects:

NvApplicationContext nvca = new NvApplicationContext(new Form1()); 
Application.Run(nvca);

Are the rest of the forms supposed to be recognized automatically? Or, how can multiple forms be monitored by NvApplicationContext?

Zev Spitz
  • 13,950
  • 6
  • 64
  • 136
AKS
  • 63
  • 5
  • 2
    Can you be more specific about what you're trying to do? What do you mean by "monitor multiple forms"? –  Jul 25 '18 at 03:35
  • 1
    Your `ApplicationContext`-derived class needs to hold references to the new `Form`s you are creating; it won't automatically close all forms when it is finished. See [here](https://stackoverflow.com/a/13406508/111794) and [here](https://stackoverflow.com/a/13407161/111794). – Zev Spitz Jul 25 '18 at 03:52
  • Sorry, my bad. I have an application containing two forms and I want to monitor those two forms using a class library. The Application opens form1 on start and another form on button click. I am using ApplicationContext in this way :- NvApplicationContext nvca = new NvApplicationContext(new Form1()); Application.Run(nvca); and hence I am getting only reference of form1. How do I get the reference of form2 in class library. NVApplicationContext is extending ApplicationContext and this class is in class library. – AKS Jul 25 '18 at 04:40
  • The `ApplicationContext` pattern has already been covered by the (good, btw) example linked by @Zev Spitz. Another way is using [Automation](https://learn.microsoft.com/en-us/dotnet/api/system.windows.automation.automation?f1url=https%3A%2F%2Fmsdn.microsoft.com%2Fquery%2Fdev15.query%3FappId%3DDev15IDEF1%26l%3DEN-US%26k%3Dk(System.Windows.Automation.Automation);k(TargetFrameworkMoniker-.NETFramework&view=netframework-4.7.2)). But it depends on what you mean by *monitoring*. Try to explain it (by editing your question) in a more consistent way. – Jimi Jul 25 '18 at 05:17
  • @Jimi Would you suggest any improvements on either of the two linked answers? – Zev Spitz Jul 25 '18 at 05:24
  • @Zev Spitz I think that [this one](https://stackoverflow.com/a/13407161/7444103) is quite well implemented. But I can't express a qualified opinion without testing it. It's quite interesting, though (and the reason why I commented here), because just a few hours ago I answered a question (somewhat similar) about [*managing* an existing app Forms](https://stackoverflow.com/questions/51491566/add-an-event-to-all-forms-in-a-project?answertab=active#tab-top) (without editing the existing code). `ApplicationContext` was one of the methods that came to mind. Your solution is interesting. – Jimi Jul 25 '18 at 05:41
  • Again, your `NvApplicationContext` has to be told about new forms that you create. If you look at [this answer](https://stackoverflow.com/questions/9462592/best-practices-for-multi-form-applications-to-show-and-hide-forms/13407161#13407161), there are two additional members described: `CreateForm` creates new form instances through the context, which then registers the newly created forms; and `RegisterForm` which registers forms not created via the context. – Zev Spitz Jul 25 '18 at 05:54
  • @Zev I might get help with the first solution you provided. Its just I am struggling how do I pass context having reference to all the forms. – AKS Jul 25 '18 at 05:55
  • You could define `NvApplicationContext` as taking a variable number of arguments: `public NvApplicationContext(params Form[] forms) [ ... }` which would allow you to pass multiple forms into the constructor. Alternatively, instead of passing forms into the constructor, you could implement a `RegisterForm` method in `NvApplicationContext` (see [here](https://stackoverflow.com/a/13407161/111794)) and pass the newly created Form instances to the `RegisterForm` method. – Zev Spitz Jul 25 '18 at 06:01
  • Thanks @Zev. I am getting forms in my class library but none of the event handler is working. I mean on identification of forms, I am applying click handler on it which is not working when I am clicking on the form. Any comments on that? – AKS Jul 25 '18 at 14:33
  • @user10122634 I've expanded my comments into a full answer. If after that you are still having trouble, I suggest you ask a new question. – Zev Spitz Jul 25 '18 at 17:03
  • Also, I've rewritten your question; please make sure it reflects your original intention. – Zev Spitz Jul 25 '18 at 17:39

1 Answers1

0

Your NvApplicationContext needs to be told about any form instance that you want the context class to manage; it does not happen automatically.

I can think of multiple ways to structure this:

  • Allow your constructor to take multiple Form instances, using params
  • Add a RegisterForm method to NvApplicationContext and call whenever you create a form that needs to be monitored
  • Add a CreateForm method to NvApplicationContext and use it to create a form that needs to be monitored
  • In the class library, create a base form class that registers itself on creation, and have your Form1 and Form2 inherit from that base class

Allow constructor to take multiple Forms

In the class library:

public class NvApplicationContext : ApplicationContext {
    public NvApplicationContext(params Form[] forms) {
        // register event handler on each form here
    }
}

and used like this in the end projects:

var nvca = new NvApplicationContext(new Form1(), new Form2(), new Form3()); 
Application.Run(nvca);

Using a RegisterForm method

Define a static instance of NvApplicationContext:

public class NvApplicationContext : ApplicationContext {
    public static readonly NvApplicationContext Current = new NvApplicationContext();

    public void RegisterForm(Form frm) {
        // register event handler on form here
    }
}

and call RegisterForm once you've created the form. This could be before the call to Application.Run:

NvApplicationContext.Current.RegisterForm(new Form1());
NvApplicationContext.Current.RegisterForm(new Form2());
NvApplicationContext.Current.RegisterForm(new Form3());
Application.Run(NvApplicationContext.Current);

or anywhere in the application, because NvApplicationContext.Current is a static field and globally available.


Using a CreateForm method

Another option is to create any form that needs to be managed, via NvApplicationContext, and it will take care of registering the form. This assumes a static instance of the context, as in the previous section:

public class NvApplicationContext : ApplicationContext {
    public static readonly NvApplicationContext Current = new NvApplicationContext();

    public T CreateForm<T>() where T : Form, new() {
        var ret = new T();

        // register event handlers here

        return ret;
    }
}

and then call before Application.Run

NvApplicationContext.Current.CreateForm<Form1>();
NvApplicationContext.Current.CreateForm<Form2>();
NvApplicationContext.Current.CreateForm<Form3>();
Application.Run(NvApplicationContext.Current);

Using a base form

You could write a base form class like this (either in your class library, or in the end project), calling RegisterForm with a static instance from before:

public class BaseForm : Form {
    public BaseForm() {
        NvApplicationContext.Current.RegisterForm(this);
    }
}

and create forms that inherit from the base class either with the UI:

Visual Studio Add Item dialog box

Visual Studio Inheritance Picker dialog box

Or, you could do this from the code-behind of the form. Modify the base class from Form to BaseForm:

public partial class Form1 : BaseForm {
    public Form1() {
        InitializeComponent();
    }
}

Once you've set up the inheritance, whenever you create a new instance of the form it will automatically be registered with NvApplicationContext.Current.

new Form1();
new Form2();
new Form3();
Application.Run(NvApplicationContext.Current);
Zev Spitz
  • 13,950
  • 6
  • 64
  • 136
  • Thanks for the efforts. I did this way(tried 1st and 2nd method) only. It was registering events but none of the event is being identified by it. seems I have to add something additional for catching window events. Eg of Issue :- Form loads up, event handlers added up then but when I click on it nothing happens according to the click event handler. – AKS Jul 27 '18 at 05:43
  • @user10122634 This sounds like a new question. If this answer has answered your question, then accept it. If the answer is useful, then upvote it. Post your current problem as a new question, together with the code you are using to register the form. – Zev Spitz Jul 27 '18 at 05:48