One base class for both forms and user controls - c#

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.

Related

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.

Multiple inheritance problem in C#

I am in a situation where i need to use multiple inheritance in C# with WPF.
I am making a control lets say Control-1 that is derived from combobox control. I added some dependency properties as well as methods to the my control Control-1 class. Most of the properties and methods(infact the same implementation of properties and methods) in my control-1 can also be used in another control called Control-2 but that control should not be derived from combobox control (as is the case with Control-1).
I want to seperate the common dependency properties and methods in another class but seperating it in another class require me to derive my control class (control-1) from combobox control and the common class containing properties and methods.
Is there a design that can solve my problem.
Note: The question is about C# using the WPF framework's dependency properties, which require static members and not just on C# in general.
Related
How to reuse code when multiple inheritance is not an option?
Multiple Inheritance in C#
How To Implement Shared Behavior Between Classes (Without Multiple Inheritance Of Course) in C#
What are some good alternatives to multiple-inheritance in .NET?
One solution that may work for you is to create an interface instead, and put your implementation in extension methods.
sounds to me like a good time to use the decorator pattern here are some resources:
http://www.c-sharpcorner.com/UploadFile/rmcochran/csharp_wrapper302122006080905AM/csharp_wrapper3.aspx
http://andrewtroelsen.blogspot.com/2009/04/decorator-pattern-extension-methods.html
I can't speak directly to the Dependency Property situation, so I'll talk about the general problem, if that's helpful.
You can't do multiple inheritance of implementation in C#. However, you can attach an interface.
So you can define the interface:
interface IWhatever
{
...
}
And then, you can implement the functions of that interface in a class like so:
class M : IWhatever
{
}
And, now, you take the classes that you would like to have this additional functionality on:
class B : MustExtend, IWhatever
{
private M myMImpl = new M();
// implement functions, call to 'myMImpl' for implementation.
}
This is called 'composition'. It can be useful in some circumstances, and is generally underused, I'd think :)
I've used stubs that are called from the derived class and take the class of base type as an argument. This leaves me with several one line functions. Too bad.
The problem with extension methods and interfaces is that dependency properties require the declaration of static members and public properties, for example:
public PermissionEnum Permission
{
get { return (PermissionEnum)GetValue(PermissionProperty); }
set { SetValue(PermissionProperty, value); }
}
public static readonly DependencyProperty PermissionProperty =
DependencyProperty.Register("Permission", typeof(PermissionEnum), typeof(SecurityMenuItem), new FrameworkPropertyMetadata(PermissionEnum.DeliveryView));

Windows Form inheritance

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.

internal constructor

Yesterday I thought it would be nice to implement my own Trigger in a WPF app. I created a class MyTrigger which inherited TriggerBase. TriggerBase is a public abstract class. So inheritance isn't a problem. But the constructors inside this class are marked internal. The compiler throws an error because the is no valid constructor. Why does anyone create a public class but marks the constructors as internal?
If you want the class to be visible, but only allow it to be subclassed within your own assembly. The subclasses may have public constuctors themselves - or they may be accessed with a factory.
I can't comment on whether that's a good design decision for TriggerBase in WPF, but it's at least reasonable in some situations.
One reason that I could think of is that the actual creation of new instances would be handled by another public class in the same assembly. This would force that you create the instance through this other class - possibly some sort of a factory pattern implementation.
It's public because it's used as a base class for the triggers that ship with WPF (Trigger, MultiTrigger, EventTrigger, DataTrigger etc). It it wasn't public then you wouldn't be able to flag these classes as public.
The constructors are internal because they don't intend for you to use it yourself. I'd guess you're suppose to derive from one of the classes mentioned above.

Categories