I am using Visual Studio to create a GUI application in C#. The Toolbox serves as a nifty component palette that allows me to easily drag and drop buttons and other elements (for clarity I'll say button whenever I mean "control") onto my form, which makes static forms quite easy to do. However, I run into two problems:

  • Creating the buttons in the first place is a lot of work. When I have a form that is not static (ie. buttons or other controls are created at run time according to what the user does) I cannot use the palette at all. Instead I have to create each button manually, by calling the constructor in whatever method I am using, and then manually initialize by specifying button height, width, position, label, event handler and so on. This is extremely tedious because I have to guess at all these cosmetic parameters without being able to see what the form will look like, and it also generates many lines of repetitive code for each button.
  • Making the buttons do something is also a lot of work. Dealing with events in a full-featured application is a huge pain. The only way I know how to do this is to select a button, go to the events tab in its properties, click the OnClick event so that it generates the event in the Form's code, then fill in the body of the event. Since I want to separate logic and presentation, all of my event handlers end up being single-line calls to the appropriate business logic function. But using this for many buttons (for instance, imagine the number of buttons present in an application like MS Word) pollutes the code of my Form with dozens of boilerplate event handler methods and it's difficult to maintain this.

Because of these, any GUI program more complicated than Hello World is very impractical to actually make for me. To be clear, I have no problems whatsoever dealing with complexity in programs that I write which have minimal UI - I feel like I am able to use OOP with a fair degree of competence to neatly structure my business logic code. But when developing the GUI, I'm stuck. It seems so tedious that I feel like I'm reinventing the wheel, and there's a book somewhere out there explaining how to do GUI properly that I haven't read.

Am I missing something? Or do all C# developers just accept the endless lists of repetitive event handlers and button creation code?

As a (hopefully helpful) hint, I expect that a good answer will talk about:

  • Using OOP techniques (such as the factory pattern) to simplify repeated button creation
  • Combining many event handlers into a single method that checks Sender to figure out which button called it, and behaves accordingly
  • XAML and using WPF instead of Windows Forms

You don't have to mention any of these, of course. It's just my best guess as to what sort of answer I'm looking for.

  • As i see it yes Factory would be a good pattern but i see much more a Model-View-Controller pattern with Commands hooked to controls instead of events directly. WPF is usually MVVM but MVC is well possible. We currently have a huge software in WPF using MVC at 90%. All commands are forwarded to the controller and he handle everthing – Franck Jan 13 '15 at 19:21
  • Can't you create the dynamic form with all possible buttons with a GUI editor, and just make things you don't need dynamically invisible? Sounds like much less work. – Hans-Peter Störr Jan 19 '15 at 20:01
  • @hstoerr But it would be hard to get the layout to work. A lot of the buttons would overlap. – Superbest Jan 20 '15 at 20:53
up vote 22 down vote accepted

There are several methodologies that have evolved over the years to deal with these issues you've mentioned, which are, I agree, the two main issues that UI frameworks have had to address in recent years. Coming from a WPF background, these are approached as follows:

Declarative design, rather than imperative

When you describe painstakingly writing code to instantiate controls and set their properties, you're describing the imperative model of UI design. Even with the WinForms designer, you're just using a wrapper over that model - open the Form1.Designer.cs file and you see all that code sitting there.

With WPF and XAML - and similar models in other frameworks, of course, from HTML onwards - you're expected to describe your layout, and let the framework do the heavy lifting of implementing it. You use smarter controls such as Panels (Grid, or WrapPanel, etc) to describe the relationship between UI elements, but the expectation is that you don't manually position them. Flexible concepts such as repeatable controls - like ASP.NET's Repeater or WPF's ItemsControl - help you create dynamically scaling UI without writing repeating code, allowing dynamically growing data entities to be represented dynamically as controls.

WPF's DataTemplates allow you to define - again, declaratively - little nuggets of UI goodness and match them to your data; for instance, a list of Customer data objects might be bound to an ItemsControl, and a different data template invoked depending on whether he's a regular employee (use a standard grid row template with name and address) or a Prime Customer, whereas a different template, with a picture and easy-to-access buttons are displayed. Again, without writing code in the specific window, just smarter controls that are aware of their data-context, and thus allow you to simply bind them to your data and let them perform relevant operations.

Data Binding and Command Separation

Touching on data binding, WPF's databinding (and, again, in other frameworks as well, like AngularJS) allows you to state your intent by linking a control (say, a textbox) with a data entity (say, the Customer's Name) and let the framework handle the plumbing. Logic is handled similarly. Instead of manually wiring up code-behind event-handlers to Controller-based business-logic, you use the Data Binding mechanism to link a controller's behavior (say, a button's Command property) to a Command object which represents the nugget of activity.

It allows this Command to be shared between windows without rewriting the event handlers every time.

Higher Level of Abstraction

Both of these solutions to your two problems represent a move to a higher level of abstraction than the event-driven paradigm of Windows Forms that you rightfully find tiresome.

The idea is that you don't want to define, in code, every single property that the control has, and every single behavior starting from the button click and onwards. You want your controls and underlying framework to do more work for you and allow you to think in more abstract concepts of Data Binding (which exists in WinForms, but is nowhere near as useful as in WPF) and the Command pattern to define links between UI and behavior that don't require getting down to the metal.

The MVVM pattern is Microsoft's approach to this paradigm. I suggest reading up on that.

This is a rough example of how this model would look and how it would save you time and lines of code. This won't compile, but it's pseudo-WPF. :)

Somewhere in your application resources, you define Data Templates:

<DataTemplate x:DataType="Customer">
   <TextBox Text="{Binding Name}"/> 

<DataTemplate x:DataType="PrimeCustomer">
   <Image Source="GoldStar.png"/>
   <TextBox Text="{Binding Name}"/> 

Now, you link your main screen to a ViewModel, a class which exposes your data. Say, a collection of Customers (simply a List<Customer>) and a Command object (again, a simple public property of type ICommand). This link allows binding:

public class CustomersnViewModel
     public List<Customer> Customers {get;}
     public ICommand RefreshCustomerListCommand {get;}  

and the UI:

<ListBox ItemsSource="{Binding Customers}"/>
<Button Command="{Binding RefreshCustomerListCommand}">Refresh</Button>

And that's it. The ListBox's syntax will grab the list of Customers off of the ViewModel and attempt to render them to the UI. Because of the two DataTemplates we defined earlier, it will import the relevant template (based on the DataType, assuming PrimeCustomer inherits from Customer) and put it as the contents of the ListBox. No looping, no dynamic generation of controls via code.

The Button, similarly, has preexisting syntax to link its behavior to an ICommand implementation, which presumably knows to update the Customers property - prompting the data-binding framework to update the UI again, automatically.

I've taken some shortcuts here, of course, but this is the gist of it.

First, I recommend this article series: http://codebetter.com/jeremymiller/2007/07/26/the-build-your-own-cab-series-table-of-contents/ - it does not address the detail problems with your button code, but it gives you a systematic strategy for designing and implementing your own application framework, especially for GUI applications, showing you how to apply MVC, MVP, MVVM to your typical Forms application.

Addressing your question about "dealing with events": if you have a lot of forms with buttons working in a similar manner, it will probably pay off to implement the event handler assignment in your "application framework" by yourself. Instead of assigning the click events using the GUI designer, create a naming convention how a "click" handler has to be named for a button of a specific name. For example - for button MyNiftyButton_ClickHandler for the button MyNiftyButton. Then it is not really hard to write a reusable routine (utilizing reflection) which iterates over all buttons of a form, check if the form contains a related click handler and assign the handler to the event automatically. See here for an example.

And if you just want to use only one event handler for a bunch of buttons, that will be also possible. Since each event handler gets the sender passed, and the sender is always the button which was pressed, you can dispatch to the business code by utilizing the "Name" property of each button.

For the dynamic creation of buttons (or other controls): you can create buttons or other controls with the designer on an unused form just for the purpose of beeing a template. Then, you use reflection (see here for an example) to clone the template control and change only the properties like location or size. That will probably be much simpler than to initialize two or three dozen properties manually in code.

I wrote this above by having Winforms in mind (just as you, I guess), but the general principles should apply to other GUI environments like WPF with similar capabilities.

  • Indeed possible to do in WPF and it's even much easier. You simply fill a list of commands (pre coded specific functions) and set the source on your window. You create a nice simple visual template and all you need to take care of is filling a collection with commands you want and the great WPF binding take care of the rest for you visually. – Franck Jan 13 '15 at 20:00

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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