aspatz

I build an MDI Application. Each different kind of MDI Child should be able to selfregister in a global menu bevor a concret Instance is created. Is this possible, and how. The best form me would be a base class for all MDI Childs where this functionality is covered.

I am looking forward for your help.
Thanks.


Re: Windows Forms General MDI Client should manually register in menu without beeing instantiated

nobugz

The ability to have an MDI child merge itself into the parent's menu is fully supported..





Re: Windows Forms General MDI Client should manually register in menu without beeing instantiated

aspatz

thank you for your reply. But this was not the problem for me.

I have am Main Menu and i want to show in this main menu all different available childs. For example i have a customer childform and an invoice childform.
I want that this two childforms have the ability to register in this main menu, without beeing intantiated.

In a Timeline like:
- the MainForm was Initialized.
- now all the ChildForms were researched and the Menuinformations registered in some global data construct (A).
- now a special ChildForm will be intantiated and showed which contains some special Menue with all the available ChildForms. (Data from the "some global data construct (A)".

There should be some properties in the childform which can be set during design time including "Name in the Menu", "Name of the childform" and some others.





Re: Windows Forms General MDI Client should manually register in menu without beeing instantiated

theblueeyz

I see what you want to do.

While the typical approach to this is to just hardcode the list of available MDI forms, you want a more dynamic approach - you want your program to populate the menu with possible MDI children at runtime.

Do I have it about right

It sounds to me like what you're looking for is a plugin-based approach, or, if you'll only ever be using the MDI children you build into your own application, you could use Reflection to discover all types in your project's namespace that implement a particular interface or inheritance structure. (of course, that would beg the question - why not just hardcode the list).

If you want a plugin-based approach, there are some good articles on TheCodeProject on how to create a plugin system.

What are your thoughts on that





Re: Windows Forms General MDI Client should manually register in menu without beeing instantiated

nobugz

I'm guessing you're looking for a way to dynamically add MDI forms to a parent that doesn't know about them. It is difficult to query a class for a property without instantiating it. Even more difficult if you don't know the class name. Reflection could help out. You can add a constant to a class and retrieve its value. Something like this:

public partial class Form2 : Form {
private const string FindMe = "nobugz";
public Form2() {
InitializeComponent();
}
}

To search the available forms, you'd have to iterate through the types in the assembly. This code can find both the form and the "FindMe" constant:

using System.Reflection;
...
Assembly asm = Assembly.GetExecutingAssembly();
foreach (Type t in asm.GetTypes()) {
if (t.BaseType == typeof(Form)) {
FieldInfo fi = t.GetField("FindMe", BindingFlags.Static | BindingFlags.NonPublic);
if (fi != null) {
string value = (string)fi.GetValue(null);
Console.WriteLine("Found form {0} with value {1}", t.Name, value);
}
}
}

Output is:
Found form Form2 with value nobugz

Use the string constant(s) to initialize your menu. Store the Type instance too, you'll need it later to create the form with Activator.CreateInstance(). If the forms are defined in a different assembly, you'll need to iterate through the assemblies returned by AppDomain.GetAssemblies. If those assemblies aren't loaded yet, you'll need to figure out a way to get them loaded before executing this code with AppDomain.LoadAssembly().





Re: Windows Forms General MDI Client should manually register in menu without beeing instantiated

aspatz

thanks, that' s completely what i mean.

I dont wanted to hardcode it, because i thougt it was a better way to build the system in that way.
Can you give me some advice of how i can implement this solution with a sepcial Interface.

Can i create a basic class for my ChildForms which implements this Interface or is it better to create the ChildForms like "public class SomeClientTestForm : Form, ISomeInterface{}"

Could you give me an idea how and in which point of the initialization of the main form i can analyse the forms with reflections
Thanks for your understanding and help.






Re: Windows Forms General MDI Client should manually register in menu without beeing instantiated

aspatz

thank you for your help. I thought this will help me build my system.
Arnold




Re: Windows Forms General MDI Client should manually register in menu without beeing instantiated

aspatz

nobugz wrote:
I'm guessing you're looking for a way to dynamically add MDI forms to a parent that doesn't know about them. It is difficult to query a class for a property without instantiating it. Even more difficult if you don't know the class name. Reflection could help out. You can add a constant to a class and retrieve its value. Something like this:

public partial class Form2 : Form {
private const string FindMe = "nobugz";
public Form2() {
InitializeComponent();
}
}

To search the available forms, you'd have to iterate through the types in the assembly. This code can find both the form and the "FindMe" constant:

using System.Reflection;
...
Assembly asm = Assembly.GetExecutingAssembly();
foreach (Type t in asm.GetTypes()) {
if (t.BaseType == typeof(Form)) {
FieldInfo fi = t.GetField("FindMe", BindingFlags.Static | BindingFlags.NonPublic);
if (fi != null) {
string value = (string)fi.GetValue(null);
Console.WriteLine("Found form {0} with value {1}", t.Name, value);
}
}
}

Output is:
Found form Form2 with value nobugz

Use the string constant(s) to initialize your menu. Store the Type instance too, you'll need it later to create the form with Activator.CreateInstance(). If the forms are defined in a different assembly, you'll need to iterate through the assemblies returned by AppDomain.GetAssemblies. If those assemblies aren't loaded yet, you'll need to figure out a way to get them loaded before executing this code with AppDomain.LoadAssembly().