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>
<DataTemplate x:DataType="PrimeCustomer">
<Image Source="GoldStar.png"/>
<TextBox Text="{Binding Name}"/>
</DataTemplate>
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.
Best Answer
The answer depends on what version of C# you are using.
The early versions required the
new RoutedEventHandler
while the newer versions don't.They compile to the same code.