9

I remember learning VB4 and dragging a button onto a form, double-clicking on that button, and typing code into that event handler I had just been magically blessed with. Coming from QBASIC I was thrilled with the "V" in "VB", the visual designer was literally the best thing since sliced bread.

Of course you could do all that programmatically but the magic of the "V" was so appealing you just couldn't help but drag that button. We were encouraged to take that route.

But then a few years ago I started learning about C# and the .net framework and was fascinated by the way everything I thought I knew had just gone out the window. There's a lot of magic going on in VB6 that's completely unveiled in .net: take constructors and the InitializeComponents method for example. In the latter you'd find all the control instances you've dragged from the toolbox, all the events you've registered and the properties you've set in the designer.

And that's fine... I guess. It's just, I feel like I don't "own" what's going on, this code that I can only modify via the designer annoys the heck out of me. Every time you copy a button that says "Ok" from one form to another (sometimes along with its brother "Cancel"), you are actually duplicating code, and that's a sin isn't it? DRY, don't repeat yourself, says the Pope.

Religions and schools of thought aside, in all objectivity, shouldn't we derive forms from base forms instead, and have the "Ok" button (and all of its friends) live on the base form? Something like a FormBase from which derives a DialogFormBase; all classes created in no time... by typing code. The buttons are created depending on how the class is instanciated (i.e. a constructor enum argument determines which buttons are to be created), controls are laid out inside an arrangement of split panels and flow layout panels, injected into the form as Content that fits into the main content panel. Isn't this what ASP.net does with master pages and content placeholders? I'd derive a form when I need a new "master page", but this new "master page" still derives from a base form class so the visuals are consistent across the entire application.

To me that's much more code reuse than anything else I've ever done with the designer in WinForms, and it wasn't even hard, and code isn't cluttered with a 200-lines method that I have no control over, I can put comments where I like, they won't get overwritten by a designer. I guess it's just a matter of patterns and architecture, which is what brought me to this link: Best design for Windows forms that will share common functionality, where I realized I was spot on, except the answer there, suggests exactly what I'm doing, but it's advising against form inheritance because of designer considerations. That's the part I don't get. I would rather advise against using the designer because of code structure considerations, especially in regards with form and control inheritance, which I see no reason to avoid other than well it breaks the designer.

We can't all be just lazy, so what part am I missing?

7
  • I don't understand. Are you implying that we should not use visual designers and write all GUI code by hand?
    – Euphoric
    Commented Mar 23, 2013 at 16:41
  • Pre .NET where was the code that controlled the all the objects dragged on the form?
    – JeffO
    Commented Mar 24, 2013 at 19:21
  • 1
    @JeffO judging from the legacy code I have dealt with, I'd say right on the form, somewhere between ad-hoc inline SQL and business logic. Point is, WinForms is .net; so if the designer is working well with what nowadays smells like "bad code" and "bad coding habits" and actually breaks when you start structuring things up, I say drop the designer and treat forms as what they are (classes!)... and how is coding a UI layer in C# so different from coding a UI layer in ExtJS, anyway? It's "tedious" to do that in WinForms because "hey look there's a designer"? Is coding a ExtJS UI tedious? Commented Mar 24, 2013 at 22:13
  • I am going to quote another user: CodeCaster ; An event handler is meant to connect the GUI to your business logic. If you have a textbox to enter a user's name and an Add button, clicking the Add button should merely call _userRepository.AddUser(UsernameTextbox.Text). You don't want business logic in event handlers. stackoverflow.com/questions/8048196/…
    – Pieter B
    Commented Mar 25, 2013 at 10:16
  • @Pieter doesn't that put a DAL dependency into your presentation layer? Commented Mar 25, 2013 at 18:26

4 Answers 4

10

I'm gonna oppose you with different paradigm : Favor composition over inheritance.

Even when you start writing GUI code by hand and use inheritance to share behavior and visuals between forms, you will hit same problem as normal OOP design. Lets say you have DialogForm, that has OK/Cancel buttons and GridForm, that has grid. You derive all dialogs from DialogForm and all forms with Grid from GridForm. And then you find out you want form with both. How would you solve it? If you are using form inheritance, then there is no way solve it. On the other side, if you are using UserControls, then you can simply put GridControl on your form and be done with it. And you can still use designer with UserControls, so you don't have to waste time writing tedious GUI code.

6
  • Well the base form merely has a SplitContainer with Panel2 fixed, containing a FlowLayoutPanel called BottomPanel and hosting the common Ok/Cancel/Apply/Close behaviors; Panel1 contains a SplitContainer with Panel1 fixed (to host common "instructions" label, or menus, toolbars, whatever goes on top) and Panel2 holding a protected Panel called MainContent; each actual implementation decides how to fill it up. All content can be injected into the implementation and yes, this can be a user control made with the designer to save time, good point.. but what about the form itself? Commented Mar 23, 2013 at 17:31
  • The problem here is scale. When you take application with 10 forms, then having single common form is no big deal. The problems start when you have application with dozens or hundreds of forms. Then, you will have forms that have pieces common, but never enough to create base form. In you case, it might happen you want to use different layout or different buttons, but keep everything else same. And thats when the problems start.
    – Euphoric
    Commented Mar 23, 2013 at 17:41
  • 2
    The 'problem with scale" does not exist if you have a halfway decent design. We have a project where I work with a few hundred forms. We use form inheritance heavily to provide consistency and common functionality, and we've never had any problems with it. Commented Mar 23, 2013 at 19:01
  • 2
    @MasonWheeler I had exactly opposite experience. We tried to use form inheritance in one of our applications, and every time we did even little change in the base forms, the whole thing broke down and we had to manually fix all other forms. Also, designer behaves weird when you work with inherited form.
    – Euphoric
    Commented Mar 23, 2013 at 21:40
  • 1
    @Euphoric: Which designer? We use Delphi, and its designer works just fine with inherited forms. And again, you don't have these problems if you have a good design. If you don't plan anything out, of course it's all going to be brittle and break anytime you touch it, but that's no different from any other code. Commented Mar 23, 2013 at 23:07
2

Much of this is tied to the technology stack of choice.

WinForms and WPF may both be .NET UI frameworks but vary greatly in how you achieve the end goal. Certain paradigms move between technologies just fine but others don't and you shouldn't try and force a paradigm simply because you feel it's meant to exist in every framework. There is a reason that MVVM is geared at WPF/SL and MVC is a seperate concept in ASP.NET from WebForms and so on. Certain technologies work better with certain paradigms.

Keep in mind that generated code should generally be removed from your DRY concerns. While applicable in some instances, more often than not it should be ignored. DRY concepts should certainly remain a focus outside your Presentation layer but at the Presentation layer generated code is more often than not a byproduct of the framework you are working in. This is not to say you can't apply DRY principles in your approach but remain cautious. Could you create a base Form and inherit from it indefinitely? Yes. Could you drag and drop components on a new Form each and every time as needed? Yes. Keep focused on the end goal, avoiding potential defects, making it easy to refactor downstream, and scalability while working within the confines of the technology stack of choice.

0

You can use inheritance providing you correctly encapsulate your fields and populate accordingly. If you were keen to use inheritance my suggestion would be to have the base form and a corresponding Model for that form, and for each derivation derive both the form and the Model.

A far better alternative would be to group related controls into one or more UserControl controls. You just need a little bit of logic to put the relevant data into it.

0

I totally agree with Mason Wheeler, although in three years maybe even himself had changed his mind.

I´m trying to look for alternatives to migrate from Delphi executables to the WEB.

Up to now I decided myself for UNIGUI, because I can still use form inheritance. I would like Delphi to have Mixins like Dart, as it would let me have less form ancestors. But I feel people write much more code in MVC than with Visual Form Inheritance, since most of the navigation, calls to the validation rules in the datamodule(applyupdates), sql filtering criteria, searching the client dataset, everything is written in 5 maybe 6 Form ancestors.

Even the "With MVC it will be easier for you to leave Delphi in the Feature" for me don´t work as an argument, since people invited OOP, everything are classes, properties, methods. So all I need is a translator. Really could not find any advantage, maybe for websites which are much less complicated but change in a Daily base.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.