shared functionality on usercontrol and form - c#

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.

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.

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.

use Winform Objects inside an Static Method

I have a problem that I could ignore a long time but now I have to solve it.
I have 3 GUI (Winform) 1 Main 1 Settings and 1 for a Webbrowser.
I need to call a Method that is in my Webbrowser Form inside my Main Form for that reason the Method is a static one.
But if I set it to static it giveĀ“s me an error if I try to work with the Objects from the Form.
public partial class Form3 : Form
{
public Form3()
{
InitializeComponent();
}
public static void WebLyrics(string url){
webBrowser1.Navigate(url);
}
}
The easiest way is to:
Add a static Instance property to the webbrowser form:
public partial class Form3 : Form
{
public Form3()
{
InitializeComponent();
Instance = this;
}
public static Form3 Instance { get; private set; }
public void WebLyrics(string url)
{
webBrowser1.Navigate(url);
}
}
and call the WebLyrics method via the Instance property in the other form:
public partian class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Navigate()
{
Form3.Instance.WebLyrics("www.stackoverflow.com");
}
}
I assumed you create both forms somewhere somehow...
You should consider changing the code. Why is your Form having a static method? It doesn't make any sense. The easiest way to achieve it is to pass reference to the Webbrowser Form into the Main Form. Or you can instantiate the Webbrowser form inside you Main Form and then show it.
But I suggest that you introduce a way of separating the UI from the business logic layer. Consider to introduce MVC / MVP pattern, to have a clear separation, and then the forms do not need to have references to each other directly.
The easiest (= least code) way to solve it is probably to use singletons for the forms as other have suggested, or even simpler to use the built in forms registry:
var myForm3 = Application.OpenForms.OfType<Form3>.FirstOrDefault();
I would probably prefer to use a separate singleton for holding the forms, as I would find it more maintainable. This would be a better separation of concerns in that the forms would not have to be created as singletons and could be reused in other ways. It is truly your app's UI layout that is the singleton.
Something like this:
public class AppLayout
{
public static AppLayout Instance {
get { ... }
}
public WebBrowserForm WebBrowser {get;private set;}
public MainForm Main {get;private set;}
public SettingsForm Settings {get;private set;}
}
Think of it like a typed variant of the Application singleton.

Make usercontrols and forms inherit from a unique base control

My winform application contains usercontrols and forms.
Each usercontrol inherits a base usercontrol and each form inherits a base form.
The base usercontrol and the base form contain exactly the same properties and methods because what I want is to manage security and language settings at one single place.
This solution is working but I would like all my controls (usercontrols and forms) to inherit a unique base control in order to have these methods at one single place.
Is there a way to achieve this ?
Thanks !
Inheriting in this case doesn't make much sense from an OO perspective.
I suggest creating "SecurityManager" and "LanguageManager" classes and using them from your base form & usercontrol. They will have a clear role and let you control the logic from a single place.
I've run into this issue before. Unfortunately, since C# doesn't support multiple inheritance, your BaseForm and BaseUserControl cannot inherit from BaseFunctions, and Form and UserControl (respectively).
The work around I use is to create a IBaseFunctions interface with the methods needed and place the functionality in a helper class.
You still have a lot of copy-pasta, but at least it's just the wrapping and not the needed logic.
ex:
public interface IBaseFunctions
{
IUser GetCurrentUser();
void ShowMessage(String message);
}
public class BaseFunctionsHelper : IBaseFunctions
{
public IUser GetCurrentUser()
{
// Get Current User
}
public void ShowMessage(String message)
{
// Show message
}
}
public class BaseForm : Form, IBaseFunctions
{
private readonly IBaseFunctions _helper = new BaseFunctionsHelper();
public IUser GetCurrentUser()
{
return _helper.GetCurrentUser();
}
public void ShowMessage(String message)
{
return _helper.ShowMessage(message);
}
}
public class BaseControl : UserControl, IBaseFunctions
{
private readonly IBaseFunctions _helper = new BaseFunctionsHelper();
public IUser GetCurrentUser()
{
return _helper.GetCurrentUser();
}
public void ShowMessage(String message)
{
return _helper.ShowMessage(message);
}
}

C# Component Container

I have a windows form and my own class in my project
I have a method in my own class
public object Sample(Form MyForm,string ComponentName)
{
}
I want to get components of the "MyForm" from another class How Can I Make THIs?
form class
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
}
MyOwnClass
public class Sample
{
public object GetComponentMethod(Form form,string ComponentName)
{
////
}
}
Have you tried with:
Control myControl= form.controls.Find(...)?
updated
Sorry but in this case I cannot understand what are you looking for!
updated
you have to create a public property Components! So you can retrieve data you need!
It looks like you are just trying to access members of one object from another object.
If so you need to expose some way of accessing a specific instance of a class.
If you will only ever have one instance (of say your Form1) the simplest way is to expose that single instance via a public static property. This is called a singleton pattern:
public partial class Form1 : Form
{
public static Form1 Singleton { get; private set; }
public Form1()
{
Form1.Singleton = this;
InitializeComponent();
}
}
You can the access your Form1 instance using Form1.Singleton.SomeProperty from anywhere.
I am not promoting any specific Singleton pattern here, as there are too many issues over thread safety, but for your simple example this will do the job. Call the static property "Singleton" or "This" or "SolutionToMyWoes" or whatever you like!

Categories

Resources