Reference to parent form from Class Library - c#

I've been trying to compile all my classes into a class library which is a really nice feature. My goal is to have all my code in there that doesn't include the code for a specific application. When I try to add a class that references the parent form I run into issues because there is no parent form in the class library. How do I create a reference to a form that it yet unknown until the parent class is created in the application?
public class Form1 : Form
{
private Child child;
public Form1()
{
child = new Child(this);
}
}
public class Child
{
private Form1 parent;
public Child(Form1 parent)
{
this.parent = parent;
}
}
This code works in a standard application, but when I add the Child class to the class library, the "Form1" text will not compile because Form1 is not included in the class library. Is there any way around this? Thank you for any help.

As Form1 derives from Form, why not take Form as a parameter to the constructor of Child?
public class Child
{
private Form parent;
public Child(Form parent)
{
this.parent = parent;
}
}
This will at least break the dependency on your application from your class library, but it will still require a dependency on WinForms for Form. It depends on what you intend to do with parent in your code though as to whether this is sufficient.

Use below code
Parent.FindForm()

Related

C# Inheriting a User Control that has variable set at runtime

I have a main form that acts as a "Wizard" for a bunch of different user controls. I have one user control with relatively basic operations, and I am trying to create a new user control that inherits this basic user control.
However, the base user control has a variable containing the main form (so the user control can access the wizard control functions in the main form). When I create a new "inherited user control" the Designer complains that the reference to the main for has not been set to an instance of the object. I set the reference to the MainForm during runtime when I create an instance of the base user control.
Is there a way to make this work? Below is some simplified code demonstrating my problem.
MainForm.cs:
public partial class MainForm : Form
{
public string exampleString = "From MainForm";
public MainForm()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
BaseControl base = new BaseControl();
base.mainForm = this;
{
}
BaseControl.cs
public partial class BaseControl : UserControl
{
public MainForm mainForm { get; set;}
public TestPanel()
{
InitializeComponent();
string needed = mainForm.exampleString; //Object reference not set to an instance of an object here
}
}
So when I try to create a user control that inherits BaseControl through Solution -> Add -> New Item -> Inherited User Control and select BaseClass, the designer complains of the "Object reference not set to an instance of an object" error at the string needed = mainForm.exampleString line in BaseControl.cs.
Any help with this would be greatly appreciated. Hopefully this is enough information for you to understand what I am trying to do.
Thanks.
The code which you shared will not work, neither at run-time nor in design-time.
You are trying to use mainForm.exampleString in constructor of BaseControl while mainForm will be assigned just after creating an instance of BaseControl.
In such cases, specially when you want to have design-time support, you can derive from ISupportInitialize interface and override BeginInit and EndInit.
Example
The following control implements ISupportInitialize. If you drop an instance of the control on the form, at run-time, it tries to find the parent form and if it was MainForm tries to use public members of the MainForm:
using System.ComponentModel;
using System.Windows.Forms;
public class MyControl : Control, ISupportInitialize
{
public void BeginInit()
{
}
public void EndInit()
{
var parent = this.FindForm() as MainForm;
if (parent != null)
{
//Access to MainForm members
}
}
}
This is just an example that shows how to use ISupportInitialize. In action, it's not a good idea to have a dependency to a specific type of parent form. A better idea as already mentioned in Jimi's comment is relying on interfaces. For example you can have a property of ISomeInterface in your control. The interface should contain the methods or properties which you want to have for the parent of your control. Then implement the interface in some forms. Then after you dropped an instance of your control at run-time or design-time, assign the form to the property.

Keyword 'this' is not available when passing it to child form

I have three forms, where one of them is the parent and the other two are the children. The reason I'm doing this is so that the parent form can reference the children, and vice versa (I actually ran into a infinite recursion error before doing this, but all gone).
I have written the code as below:
public partial class PerfilAcesso : Form
{
// this is the parent
BDE bdeForm = new BDE(this); //error line
Workshop workshopForm = new Workshop(this); //error line
// rest of the info
}
public partial class Workshop : Form
{
// this is one child
PerfilAcesso perfilAcesso;
public Workshop(PerfilAcesso parent)
{
InitializeComponent();
perfilAcesso = parent;
}
}
public partial class BDE : Form
{
// this is another child
PerfilAcesso perfilAcesso;
public BDE(PerfilAcesso parent)
{
InitializeComponent();
perfilAcesso = parent;
}
}
However, it won't compile, because it gives the following error
Keyword 'this' is not available in the current context
at lines 4 and 5, where I pointed out.
I tried setting the property IsMdiContainer in the parent form to true, but it didn't work.
Could someone give me any directions as to what I'm doing wrong? I've gone through questions about creating a parent/child form, and they all show the same.
this is not available in field initializations. You will need to move the initialization to a constructor if you need to use this:
public partial class PerfilAcesso : Form
{
public PerfilAcesso ()
{
bdeForm = new BDE(this);
workshopForm = new Workshop(this);
}
BDE bdeForm;
Workshop workshopForm;
}

How to get access to a subclass when the other class only knows the superclass?

I have a C# Windows Forms Application form1.cs with a Class Library (DLL) called class1.cs. Now on the UI side I do the following:
using System;
...
using System.Windows.Forms;
using ClassLibrary1;
namespace UI
{
public partial class Form1 : Form
{
MyLibraryClass mlc = null;
public Form1()
{
InitializeComponent();
mlc = new MyLibraryClass(this);
}
public void aMethod() {
Console.Write("Test");
}
}
}
In the Class Library I take the Form reference and want to call the method within, but I don't have access to it:
...
using System.Windows.Forms;
namespace ClassLibrary1
{
public class MyLibraryClass
{
private Form _form;
public MyLibraryClass(Form form)
{
this._form = form;
this._form.aMethod(); //Not working!
}
}
}
The reason as I understand it is that my ClassLibrary1 only knows Form but not Form1 and hence cannot call methods from Form1. The problem is, the UI knows the Class Library but not the other way around, since that would create a ring dependency as you certainly know. But how can I solve this problem?
Instead depeding of Form you can create an interface.
public interface IMyInterface {
void aMethod();
}
Form1 will implement the interface we created
public partial class Form1 : Form, IMyInterface
{
MyLibraryClass mlc = null;
public Form1()
{
InitializeComponent();
mlc = new MyLibraryClass(this);
}
public void aMethod() {
Console.Write("Test");
}
}
In MyLibraryClass now you will depend on the interface not the form. This way MyLibraryClass can use any form that respect the contract and we make sure that in MyClassLibrary will never be passed any intruder form.
public class MyLibraryClass
{
private IMyInterface _form;
public MyLibraryClass(IMyInterface form)
{
this._form = form;
this._form.aMethod(); // now is work :)
}
}
Notes:
The interface will be created in Class Library project (where MyClassLibrary is created).
I recommend you to take a look on SOLID principles.
Circular dependencies are something you will want to avoid whenever possible, but let's assume you still need this.
The easiest solution would be to put the MyLibraryClass and Form1 in the namespace, so you can replace the Form type parameter with a Form1. If you want to keep things nicely separate however, you will have to add a new type.
In you library you would have to add an interface that contains that method.
public interface IMyInterface
{
void aMethod();
}
If you then change the parameter to an IMyInterface instead, you have access to that method. If you need access to normal Form methods or the aMethod is always the same, you could opt for an abstract class that inherits from Form too.
Depend upon Abstractions. Do not depend upon concretions
public interface IMethod
{
void aMethod();
}
public partial class Form1 : Form,IMethod
public MyLibraryClass(IMethod form)
{
this._form = form;
this._form.aMethod();
}
If you can, you should enforce statically the Form1 class in the argument list:
public MyLibraryClass(Form1 form)
{
// ...
}
If you cannot (which is often the case when several assemblies are used) you should test and cast dynamically:
public MyLibraryClass(Form form)
{
if (form is Form1)
{
(form as Form1).aMethod();
}
}
BUT YOU REALLY SHOULD honor the DIP (Dependency inversion principle), instead: depend from abstractions. Implement an interface and depend from that instead of Form1.
But if you've had the issue in the first place, you probably haven't cleared out for yourself how dependencies are organized between assemblies or, worse, don't know exactly why some answers propose to use interfaces.
Read the link above to know more about why, because your problem really is not about HOW but WHY.

How to access parent form from the child form?

I've tried looking this up and I couldn't find anything that I understood.
But what I'm trying to do is create a class with all my functions in, then call it from the parent form.
And one of these functions contains adding controls to the parent form, but I cannot find out how to do this, can somebody help me please and explain it along the way?
Many thanks,
Jarrod
Typically, I'd just add a reference to the parent form in the lower class and initialize it in the constructor. Something like this:
public form MyForm : Form
{
Foo myFoo;
public MyForm()
{
this.myFoo = new Foo(this);
}
}
public class Foo
{
private MyForm parentForm;
public Foo(MyForm parent)
{
parentForm = parent;
}
}
Then you can reference the parent form and manipulate it how you wish. It also works for static classes, too.
Try this;
In your class use this method to add controls to Parent form
public static void AddControl(Form ParentForm,Control control,Point location)
{
control.Location=location;//This is only to show you
Parent.Controls.Add(control);//how it can be done.You can replace this logic with yours
//but make sure to add this Parent.Controls.Add(control),where control will be the name of your Control.
}
Then whenever you need to add a control call the function as;
ClassName.AddControl(this,new TextBox(),new Point(10,10));//Change ClassName to your class's name.
Anything else please let me know.

shared functionality on usercontrol and form

I need to add shared functionality to both Forms and UserControls. Since multiple inheritance isn't supported in .net I wonder how I best tackle this?
The shared functionality is a dictionary that is filled by the form or usercontrol and then processed.
Regards
public class SharedFunctionality
{
public void ImportantToCallThisOnLoad();
}
public class MyForm : Form
{
SharedFunctionality mySharedFunctionality = new SharedFunctionality();
public void OnLoad()
{
mySharedFunctionality.ImportantToCallThisOnLoad();
}
}
public class MyControl : Control
{
SharedFunctionality mySharedFunctionality = new SharedFunctionality();
public void OnLoad()
{
mySharedFunctionality.ImportantToCallThisOnLoad();
}
}
Instead of having the Forms & UserControls inherit from a base class can you encapsulate the logic inside of a self contained object so that each form will new up? Then you can limit in the base class just the instantion and interaction with this object which hopefuly is minimal so having it done twice isn't a big deal.

Categories

Resources