Windows Form inheritance - c#

I want to create a bunch of forms that all have the same properties and initialize the properties in the forms constructor by assigning the constructor's parameters.
I tried creating a class that inherits from form and then having all of my forms inherit from that class, but I think since I couldn't call InitializeComponent(), that I was having some problems.
What is some C# code on how to do this?

The parent's InitializeComponent should be called by having your constructor call base() like this:
public YourFormName() : base()
{
// ...
}
(Your parent Form should have a call to InitializeComponent in its constructor. You didn't take that out, did you?)
However, the road you're going down isn't one that will play nicely with the designer, as you aren't going to be able to get it to instantiate your form at design time with those parameters (you'll have to provide a parameterless constructor for it to work). You'll also run into issues where it assigns parent properties for a second time, or assigns them to be different from what you might have wanted if you use your parametered constructor in code.
Stick with just having the properties on the form rather than using a constructor with parameters. For Forms, you'll have yourself a headache.

An alternate pattern from inheritance here would be to use a factory to create the forms. This way your factory can set all the properties

Create an interface and pass that into the constructor of the form.
interface IFormInterface
{
//Define Properties here
}
public MyForm(IFormInterface AClass)
{
//Set Properties here using AClass
}
Though I'm usually doing more than just setting properties when I want to do something like this, so I end up creating an abstract class for default behaviors.

Related

What is the purpose of empty constructor of DbContext Class in EF Code First Approach?

I have the simple context class definition:
namespace PowerSupply.Persistance.Facade
{
class PowerSupplyDBContext : DbContext
{
public PowerSupplyDBContext() : base("PowerSupplyDatabase")
{
}
}
}
There is nothing inside the body of
public PowerSupplyDBContext() : base("PowerSupplyDatabase")
{
what is the purpose of this empty constructor. How does this empty constructor works?
It calls the constructor of the base class. So it is not empty. It just doesnt add something new.
There are many reasons you could use that "empty" constructor.
You may not have any new properties, or you instantiate those properties somewhere else (i dont recommend)
You may just want to add functionality (new methods) so you extend the class, and implement new methods using the properties and methods of base class. So you dont need the constructor to do something new, opposed to the base class.
Or it has many constructors, and you use the empty constructor in circumstances you need to use limited functionality of the class, or default values.
It's best practice to include an empty constructor in any class that might be used by a third party / other project / anywhere that the compiler can't catch a change in the class.
If you omit the empty constructor, and that class is used by a third party or in another one of your projects/applications, then you can't later change that class to include a constructor with arguments. Otherwise, all the uses of this class that previously did not rely on passing constructor arguments will break, because they will have no empty-constructor to reference.

One base class for both forms and user controls

I have a Form with several methods for input validation. I want this validation logic to be shared between several Forms and UserControls. What should be the type of the base class? It cannot be Form since it will also be used for UserControls and it cannot be UserControl since it will also be used for Forms.
My instinct tells me that a solution might involve generics, but I am not sure.
Note: By "validation logic" I refer to the implementation, so interfaces are not a solution.
Edit (to make the question a bit clearer): I do have a separate class for actually validating the input. However, I use an ErrorProvider to indicate the user that the input is invalid. My InputValidator class calls a method inside the Form/UserControl that shows the error to the user, using the ErrorProvider. I just do not want to copy-paste this method for every Form/UserControl.
You cannot create a base class that handles both Forms and UserControls. However, you could create a base class for your Forms and another one for your UserControls.
In addition, create an interface that both base classes implement and that publishes the members that you need to use in the validator.
By this approach, the amount of code that is duplicated is at least reduced to two locations. Please note, that there are some OOP practices that will not work in the context of Windows Forms (e.g. abstract classes) because the designer introduces some limitations.
Original answer:
In this case, the best option is to move the validation logic to a separate class of its own. You can use this new class from both the Forms and the UserControls.
If you need to refer to the Form or UserControl during validation, you can use a parameter of type ContainerControl. This class is the base class of both Form and UserControl. This way, you can create shared logic that works for all classes that inherit from ContainerControl.
Use composition instead of inheritance. See: Composition over inheritance (wikipedia).
Your forms must inherit from Form or from another form which inherits from Form. Your user controls must inherit from UserControl or from another user control which inherits from UserControl. You cannot change this and therefore you cannot supply your own base class for both of them.
Instead, implement your validation logic in a separate class, and use it inside your forms and user controls.
public partial class MyForm : Form
{
private readonly MyValidation _validation;
public Myform()
{
InitializeComponent();
_validation = new MyValidation(errorProvider1);
}
//TODO: use _validation instead of inherited validation logic.
}
I cannot give you more details on how to implement this exactly, as I don't know what your validation is.
First thing is first - I think Olivier's answer is a very good one, and I would advise you to use it.
However, while you can't change the base classes of Form and UserControl, there is still a way to write your method only once using an interface and an extension method - and this is what I wanted to show in my answer here.
The interface:
internal interface IValidatable
{
ErrorProvider ErrorProvider {get;}
}
The extension class:
internal static class IValidatableExtensions
{
internal void ShowValidationResult(this IValidatable self, ValidationResult result)
{
// Here you can use self.ErrorProvider to show your results
}
}
Now you can have your forms and user controls implement the IVilidatable interface, and in the validation class simply call the ShowValidationResult method.
Again, I would simply send the validation instance a reference to the errorProvider as Olivier has demonstrated in his answer, but this technique might be useful in other cases, so I thought I better add an answer myself.

How to deal with base non-virtual/non-abstract properties when need override and implicit class usage?

I want to track TopMost property changes in my custom forms which are referred as (Form). I cannot use override, because TopMost isn't abstract or virtual, I can't use new keyword because it has no effect while implicit referring.
What is the best way to deal with such a task? We can substitute any property instead TopMost as long as base class (Form) has neither "change"-event, nor ONSomething virtual method to override, and our property isn't marked as abstract or virtual.
Example:
I have many classes based on Form
MyForm1:Form, class MyForm2:Form, class MyForm_n:Form
Some "factory" returns instances of Form type
Form f = GetMyForm();
And finally i do
f.TopMost = !f.TopMost;
The deal is that I can't really use any other return type for Form GetMyForm(). I can't use interface or other base class except actual Form one (in fact, there is no factory, I use .ParentForm property of some control).
What is the best way to acheive task and keep my code as clean as possible? Thanks in advance.
It sounds like you might want to introduce a new abstract class between your concrete classes and Form. That could have an ObservedTopMost property or something like that, which delegates to TopMost but also raises an event.
It's important to note that that this will only be useful when the new property is used; it won't magically spot changes to the existing property from elsewhere. It might be good enough for your purposes though.

Explicitly call interface methods from a winforms base class

I have a winforms baseform that contain calls to certain methods that need to be implemented in derived forms. I want to ensure that my derived forms do indeed implement those methods with as much compile time support as possible. We all know the problem of not being able to define a winforms class as abstract if you want to be able to use the designer (see this question).
I created an Interface that contains the method signatures that need to be implemented in a derived form. I then call the Interface methods directly from the base class like such:
((IMyFormInterface)this).SomeInterfaceMethod();
(Note that my base class does not inherit IMyFormInterface. If it did, then derived classes wouldn't be forced to implement it.)
And then I inherit from the Interface in my derived form (which the compiler forces me to implement):
public partial class TestForm : BaseForm, IMyFormInterface
The only thing I (or other users) have to remember is to inherit IMyFormInterface.
Is it acceptable to call interface methods directly like this? My goal in all of this is to be able to get as close as possible to ensuring derived forms implement these "abstract" form methods at compile time, not run time.
That's one way to work around the designer restriction. Another would be to use the designer to build a UserControl, and then let your form base class be abstract and instantiate the control docked to the full client area.
If you use this approach, I'd assert (this is IMyFormInterface) in your constructor to catch that error as early as possible.
I had the same problem with a base control.
Because Designer does not like abstract base control classes I refactored the abstract methods to virtual methods that throw a NotImplementedException.
I don't know which way is the best.

When calling a static method on parent class, can the parent class deduce the type on the child (C#)?

Suppose we have 2 classes, Child, and the class from which it inherits, Parent.
class Parent
{
public static void MyFunction(){}
}
class Child : Parent
{
}
Is it possible to determine in the parent class how the method was called? Because we can call it two ways:
Parent.MyFunction();
Child.MyFunction();
My current approach was trying to use:
MethodInfo.GetCurrentMethod().ReflectedType; // and
MethodInfo.GetCurrentMethod().DeclaringType;
But both appear to return the Parent type.
If you are wondering what, exactly I am trying to accomplish (and why I am violating the basic OOP rule that the parent shouldn't have to know anything about the child), the short of it is this (let me know if you want the long version):
I have a Model structure representing some of our data that persists to the database. All of these models inherit from an abstract Parent. This parent implements a couple of events, such as SaveEvent, DeleteEvent, etc. We want to be able to subscribe to events specific to the type. So, even though the event is in the parent, I want to be able to do:
Child.SaveEvent += new EventHandler((sender, args) => {});
I have everything in place, where the event is actually backed by a dictionary of event handlers, hashed by type. The last thing I need to get working is correctly detecting the Child type, when doing Child.SaveEvent.
I know I can implement the event in each child class (even forcing it through use of abstract), but it would be nice to keep it all in the parent, which is the class actually firing the events (since it implements the common save/delete/change functionality).
No - calling Child.MyFunction() results in IL which calls Parent.MyFunction() directly. The resulting binary is basically indistinguishable.
The last thing I need to get working is correctly detecting the Child type, when doing Child.SaveEvent.
You could use a generic base class or make the method generic.
I don't know the code at all obviously, but I question the wisdom of using static methods in this case. Perhaps you need a separate "Manager" class which is a singleton which goes the event stuff as well as other co-ordination tasks for all the model objects.
I don't think that this is possible, for the simple reason that Child.SaveEvent doesn't really exist. SaveEvent is only declared in Parent, though the compiler allows you to call it as Child.SaveEvent.
To do what you need to do, you really shouldn't be using a static method. You could easily define a non-static SaveEvent that would behave exactly as needed. If you really need a static wrapper, you could use a singleton.

Categories