Showing posts with label Windows Forms. Show all posts
Showing posts with label Windows Forms. Show all posts

Saturday, 27 September 2014

Announcing Windows Forms Best Practices

Those of you following my blog will know that I’ve been working on a course entitled Windows Forms Best Practices for Pluralsight. I’m pleased to announce that it is now live, and you can check out some of my ideas for how to write better Windows Forms applications (as well as how to incrementally migrate away to a newer technology).

The approach I took was to make a small Windows Forms demo application in the style often seen in typical line of business applications – all the code sits inside the code behind of a monolithic main form. And through the course I improve this application in various ways, both from a usability and a maintainability perspective.

Along the way I refactor it towards a Model View Presenter pattern, and improve it in various other ways such as better threading and exception handling, making it resizable and localizable.

One regret I do have is that there simply wasn’t time to show how the code could be refactored completely to MVP – I just did the first step. I have however since continued the refactoring and have a version of the demo application that uses MVP more extensively. I’ll try to make this available for viewers of my course, so do get in touch (@mark_heath on Twitter) if you’d like to get hold of this.

The course is available for viewing here. Hope you find it helpful.

Wednesday, 30 July 2014

Going Beyond the Limits of Windows Forms

One of the things I explore in my Windows Forms Best Practices course on Pluralsight (soon to be released) is how you can go beyond the limitations of the Windows Forms platform, and integrate newer technologies into your legacy applications. Here are three ways you can extend the capabilities of your Windows Forms applications.

1. Use Platform Invoke to harness the full power of the Windows Operating System

Because Windows Forms has not been significantly updated for several years now, many of the newer capabilities of Windows are not directly supported. For example, Windows Forms controls do not provide you with touch events representing your gestures on a touch screen.

However, this does not mean you are limited to using only what the System.Windows.Forms namespace has to offer. For example, with a bit of Platform Invoke, you can register to receive WM_TOUCH messages in your application with a call into the RegisterTouchWindow API in your Form load event. Then you can override the WndProc method on your form to detect the WM_TOUCH messages, and use another Windows API, GetTouchInputInfo, to interpret the message parameters.

This may sound a little complicated to you, but there is a great demo application that is part of the Windows 7 SDK which you can read about here. Of course it would be much nicer if Windows Forms had built-in touch screen support, but don’t let the fact that it doesn’t stop you from taking advantage of operating system features like this. Anything the Windows API can do, your Windows Forms application can do, thanks to P/Invoke.

2. Use the WebBrowser control to host Web Content

Many existing Windows Forms line of business applications are being gradually replaced over time with newer HTML 5 applications, allowing them to be accessed from a much broader set of devices. But the transition can be a slow process, and sometimes the time required to rewrite the entire application is prohibitive. However, with the WebBrowser Windows Forms control, you can host any web content you like, meaning that you could incrementally migrate certain parts of your application to web pages.

The WebBrowser control is essentially Internet Explorer hosted inside a Windows Forms control, and will use whatever version of IE you have installed. Frustratingly, it defaults to IE 7 compatibility mode, and there isn’t an easy programmatic way to change that. However, if you are in control of the HTML that is rendered, or are able to write a registry key, then you can use one of the two techniques described here to fix it.

The WebBrowser control actually has a few cool properties, such as the ability to let you explore and manipulate the DOM as a HtmlDocument using the WebBrowser’s Document property. You can even provide a .NET object that can be manipulated using JavaScript with the ObjectForScripting property. So two way communication from the your .NET code to the webpage, and vice versa are possible.

Obviously composing your application partly out of Windows Forms controls and partly out of hosted web pages won’t be a completely seamless user experience, but it may provide a way for you to incrementally retire various parts of a large legacy Windows Forms application and replace them with HTML 5.

3. Use the ElementHost control to host WPF content

Alternatively, you may wish to move away from Windows Forms towards WPF and XAML. Not all applications are suited to being web applications, and the WPF platform offers many advantages in terms of rendering capabilities that Windows Forms developers may wish to take advantage of. It also provides a possible route towards supporting other XAML based platforms such as Windows Store apps or Windows Phone apps.

The ElementHost control allows you to host any WPF control inside a Windows Forms application. It’s extremely simple to use, and with the exception of a few quirks here and there, works very well. If you made use of a Model View Presenter pattern, where your Views are entirely passive, then migrating your application to WPF from Windows Forms is not actually as big a task as you might imagine. You simply need to re-implement your view interfaces with WPF components instead of Windows Forms. In my Pluralsight course I show how easy this is, simply swapping out part of the interface for the demo application with a WPF replacement.

So if you are working on a Windows Forms application and find yourself frustrated by the limitations of the platform, remember that you aren’t limited to what Windows Forms itself has to offer. Consider one of these three techniques to push the boundaries of what is possible, and start to migrate towards more modern UI development technologies at the same time.

Friday, 18 July 2014

10 Ways to Create Maintainable and Testable Windows Forms Applications

Most Windows Forms applications I come across have non-existent or extremely low unit test coverage. And they are also typically very hard to maintain, with hundreds if not thousands of lines of code in the code behind for the various Form classes in the project. But it doesn’t have to be this way. Just because Windows Forms is a “legacy” technology doesn’t mean you are doomed to create an unmaintainable mess. Here’s ten tips for creating maintainable and testable Windows Forms applications. I’ll be covering many of these in my forthcoming Pluralsight course on Windows Forms best practices.

1. Segregate your user interface with User Controls

First, avoid putting too many controls onto a single form. Usually the main form of your application can be broken up into logical areas (which we could call “views”). You will make life much easier for yourself if you put the controls for each of these areas into their own container, and in Windows Forms, the easiest way to do this is with a User Control. So if you have an explorer style application, with a tree view on the left and details view on the right, then put the TreeView into its own UserControl, and create a UserControl for each of the possible right-hand views. Likewise if you have a tab control, create a separate UserControl for each page in the tab control.

Doing this not only keeps your classes from getting unmanageably large, but it also makes tasks like setting up resizing and tab order much more straightforward. It also allows you to easily disable whole sections of your user interface in one go where necessary. You’ll also find when you break up your user interface into smaller UserControls containing logically grouped controls, that it becomes much easier to redesign the UI layout of your application.

2. Keep non UI code out of code behind

Invariably in Windows Forms applications you’ll find code accessing the network, database or file system in the code behind of a form. This is a serious violation of the “Single Responsibility Principle”. The focus of your Form or UserControl class should simply be the user interface. So when you detect non UI related code exists in your code behind, refactor it out into a class with a single responsibility. So you might create a PreferencesManager class for example, or a class that is responsible for calls to a particular web service. These classes can then be injected as dependencies into your UI components (although this is just the first step – we can take this idea further as we’ll see shortly). 

3. Create passive views with interfaces

One particularly helpful technique is to make each of the forms and user controls you create implement a view interface. This interface should contain properties that allow the state and content of the controls in the view to be set and retrieved. It may also include events to report back user interactions such as clicking on a button or moving a slider. The goal is that the implementation of these view interfaces is completely passive. Ideally there should be no conditional logic whatsoever in the code behind of your Forms and UserControls.

Here’s an example of a view interface for a new user entry view. The implementation of this view should be trivial. Any business logic doesn’t belong in the code behind (and we’ll discuss where it does belong next).

interface INewUserView
{
    string FirstName { get; set; }
    string LastName { get; set; }
    event EventHandler SaveClicked;
}

By ensuring that your view implementations are as simple as possible, you will maximise your chances of being able to migrate to an alternative UI framework such as WPF, since the only thing you will need to do is recreate the views in the new technology. All your other code can be reused.

4. Use presenters to control the views

So if you have made all your views passive and implement interfaces, you need something that will implement the business logic of your application and control the views. And we can call these “presenter” classes. This is the pattern known as “Model View Presenter” or MVP.

In Model View Presenter your views are completely passive, and the presenter instructs the view what data to display. The view is also allowed to communicate back to the presenter. In my example above it does so by raising an event, but often with this pattern your view is allowed to make direct calls into the presenter.

What is absolutely not allowed is for the view to start directly manipulating the model (which includes your business entities, database layer etc). If you follow the MVP pattern, all the business logic in your application can be easily tested because it resides inside presenter or other non-UI classes.

5. Create services for error reporting

Often your presenter classes will need to display error messages. But don’t just put a MessageBox.Show into a non-UI class. You’ll make that method impossible to unit test. Instead create a service (say IErrorDisplayService) that your presenter can call into whenever it needs to report a problem. This keeps your presenters unit testable, and also provides flexibility to change the way errors are presented to the user in the future.

6. Use the Command pattern

If your application contains a toolbar with a large number of buttons for the user to click, the Command pattern may be a very good fit. The command pattern dictates that you create a class for each command. This has the great benefit of segregating your code into small classes each with a single responsibility. It also allows you to centralise everything to do with a particular command. Should the command be enabled? Should it be visible? What is its tooltip and shortcut key? Does it require a specific privilege or license to execute? How should we handle exceptions thrown when the command runs?

The command pattern allows you to standardise how you deal with each of these concerns that are common to all the commands in your application. Your command object will have an Execute method that actually contains the code to perform the required behaviour for that command. In many cases this will involve calling into other objects and business services, so you will need to inject those as dependencies into your command object. Your command objects themselves should be possible (and straightfoward) to unit test.

7. Use an IoC container to manage dependencies

If you are using Presenter classes and Command classes, then you will probably find that the number of classes they depend on grows over time. This is where an Inversion of Control container such as Unity or StructureMap can really help you out. They allow you to easily construct your views and presenters no matter how many levels of dependencies they have.

8. Use the Event Aggregator pattern

Another design pattern that can be really useful in a Windows Forms application is the event aggregator pattern (sometimes also called a “Messenger” or an “event bus”). This is a pattern where the raiser of an event and the handler of an event do not need to be coupled to each other at all. When an “event” happens in your code that needs to be handled elsewhere, simply post a message to the event aggregator. Then the code that needs to respond to that message can subscribe and handle it, without needing to worry about who is raising it.

An example might be that you send a “help requested” message with details of where the user currently is in the UI. Another service then handles that message and ensures the correct page in the help documentation is launched in a web browser. Another example is navigation. If your application has many screens, a “navigate” message can be posted to the event aggregator, and then a subscriber can respond to that by ensuring that the new screen is displayed in the user interface.

As well as radically decoupling publishers and subscribers of events, the event aggregator also has the great benefit of creating code that is extremely easy to unit test.

9. Use Async and Await for threading

If you are targeting .NET 4 and above and using Visual Studio 12 or newer, don’t forget that you can make use of the new async and await keywords which will greatly simplify any threading code in your application, and automatically handle the marshalling back onto the UI thread when the background tasks have completed. They also hugely simplify handling exceptions across multiple chained background tasks. They are a great fit for Windows Forms applications and well worth checking out if you haven’t already.

10. Don’t leave it too late

It is possible to retrofit all the patterns and techniques I described above to an existing Windows Forms application, but I can tell you from bitter experience, it can be a lot of work, especially once the code behind for forms gets into the thousands of lines of code territory. If you start off building your applications with patterns like MVP, event aggregators and the command pattern you’ll find it a lot less painful to maintain as they grow bigger. And you’ll also be able to unit test all your business logic which which is critical for on-going maintainability.

Friday, 6 June 2014

Running Windows Forms on Linux with Mono

Although WinForms may be “dead”, it does have one trick up its sleeve that WPF doesn’t, and that is you can run WinForms apps on mono. Here’s a simple guide to running a Windows Forms application on Ubuntu

Step 1 - Install Mono

Open a terminal window, and make sure everything is up to date with the following commands:

sudo apt-get update
sudo apt-get upgrade

Now you can install mono with the following command:

sudo apt-get install mono-complete

Step 2 - Create an Application

Now we need to create our C# source file. You can use any text editor you like, but if like me you aren’t familiar with Linux text editors like vi or emacs, gedit is a simple notepad-like application which is easy to use. Launch it with the following command: (the ampersand at the end tells the terminal not to wait for gedit to close before letting us continue)

gedit wf.cs &

Now let’s create a very simple application:

using System;
using System.Windows.Forms;

public class Program
{
    [STAThread]
    public static void Main()
    {
        var f = new Form();
        f.Text = "Hello World";
        Application.Run(f);
    }
}

Step 3 - Compile and Run

Now we’re ready to compile. The C# compiler in mono is gmcs. We’ll need to tell it we’re referencing the Windows Forms DLL:

gmcs wf.cs –r:System.Windows.Forms.dll

To run the application, simply call mono, passing in the executable:

mono wf.exe

And that’s all there is to it! We have a WinForms app running on Linux.

image

Although mono doesn’t support everything in WinForms, you can use most standard controls, so you can easily add further UI elements:

image

Taking it Further

Obviously writing applications by hand like this is a bit cumbersome, but there is an IDE you can use for Linux called monodevelop. You install it like this:

sudo-apt-get install monodevelop

This then gives you a nice editing environment, allowing you to debug, and manage project references (you’d usually add System.Windows.Forms and System.Drawing). Unfortunately it doesn’t offer a WinForms designer – for desktop apps it prefers you to use GTK#. Nevertheless, it’s a nice free IDE allowing you to experiment with getting your existing Windows Forms applications working cross-platform on Linux. (It seems this will also work on OS X with mono installed but I don’t have a Mac so I haven’t tried it out)

image

Thursday, 5 June 2014

Is Windows Forms Dead Yet?

Everyone knows WinForms is dead, right? It’s been dead ever since WPF was launched eight years ago, and now everyone has completely abandoned WinForms and is writing everything in XAML using MVVM.

Except they’re not. For starters, there are still a huge number of existing legacy applications that are built using WinForms, many of which are hundreds of thousands of lines of code in size. The amount of time required to port them to WPF would be prohibitively large. And there might not even be much of a point anyway. A lot of business apps don’t have a pressing need for the fancy animation capabilities that WPF offers. And while MVVM may make the developers happy, the customers don’t really care what UI design pattern you used so long as the thing works.

Even more surprisingly perhaps, I’m still seeing a large number of companies creating brand new applications in WinForms. Why? Well it’s a programming model they know and understand, does everything they need, and runs everywhere they need it to. So why should they invest the time learning XAML and dependency properties and attached behaviours, if what they already know can get the job done?

So is WinForms dead or not? Well it depends…

Of course it’s dead!

It’s dead in the sense that it is getting no more new features. It is however still picking up bugfixes. Even as recently as .NET 4.5.2, Microsoft made some improvements to WinForms. But don’t expect any new controls or improvements to the programming model (no strongly typed collections coming soon).

It’s also dead in the sense that certain new types of application can’t be built with WinForms. Most notably you can’t create a Windows Store application using WinForms. You also can’t use it on the Windows Phone or the XBox. Of course, for many line of business applications, these platforms were never being targetted in the first place.

No, it’s still alive (just)!

So why are people still using WinForms? The answer is simple: return on investment. Many companies and developers have invested heavily into Windows Forms over the years, and want to maximise their return on that investment. This investment includes…

  • Time invested learning the WinForms programming model
  • Time invested developing existing WinForms applications and controls
  • Money invested in buying suites of custom WinForms controls

So WinForms stubbornly persists, despite having been superseded by WPF (and possibly both will be eclipsed by HTML 5 in the not too distant future). And despite all its frustrating flaws and limitations, I believe it is still possible to create good quality Windows desktop applications using WinForms.

In fact, I’m working on a new course for Pluralsight which will highlight some of what I consider to be best practices for Windows Forms development. I hope to provide guidance for all developers who are still building stuff with it, whether by choice, or through gritted teeth. And I hope to show in the course how you might write your code in such a way that migration to a newer UI framework isn’t impossible. So watch this space if you’re still a WinForms developer, and do feel free to put in any requests for topics you think should be covered in the course.

Monday, 6 June 2011

So … is Silverlight dead then?

Microsoft’s Windows 8 announcement has generated a surprising amount of controversy given that what was shown (a fancy new start menu that can be navigated using touch alone) was exactly what everyone was expecting. The only thing that could conceivably be described as a surprise was that Microsoft’s offering for the slate will be the “full” Windows OS, rather than the Windows Phone 7 OS adapted for a larger screen.

Apparently you will be able to make stuff for this new touch interface with HTML5 and JavaScript. Quite how that makes Silverlight dead I am not sure. I certainly don’t see any reason to panic. Given that it is full Windows, you will be able to write apps for it in VB6, Delphi or QBasic if you really want to. If you can’t write Windows 8 apps in Silverlight I’ll eat my hat. And if there is, as expected, a Windows 8 app store, you can be sure you’ll be able to sell Silverlight apps on it (in fact, if they base it on the Windows Phone app store, then Silverlight might even be the preferred/required dev platform).

I suppose it is possible that you won’t be able to make “tiles” using Silverlight (though they haven’t announced that you can’t), but I can’t get too worked up about that. I don’t want my applications consuming loads of memory and CPU cycles before I load them. Tiles should only be doing minimal processing.

Which brings us to the question everyone is asking. Is Silverlight dead?

When people call a technology “dead”, what they often really mean is “stable” and “mature”. I still develop WinForms apps on a daily basis. The API is effectively complete. It hasn’t had any meaningful new features for years. But it is a mature framework. It does what it does well enough, and if Microsoft were still actively trying to shoehorn new features into it that would be a bad thing. After a while, what is needed is not new features, but a new development paradigm.

WPF was, at first, that new paradigm, making it easy to do what was a nightmare in WinForms. And it followed a similar path to maturity. It’s got all the main capabilities you need to build impressive looking LOB apps. Microsoft got some things right with WPF, but like WinForms, it too has its limitations. I am not concerned that there isn’t a vast number of new features being announced for it every six months.

And guess what, Silverlight is on the same trajectory. Early releases picked up new capabilities at rapid pace. The fact it was chosen as the Windows Phone 7 dev platform has given it a new lease of life. But already it is reaching the stage where new versions are more incremental than revolutionary. That’s a good thing – the technology is approaching maturity.

To summarise: no need to panic. Keep building apps with the most appropriate technology that is available now. Those apps will continue to work just fine for years to come. Don’t worry that new technologies come along every few years that seem to “kill” older ones. I for one am glad that I am not currently developing using Visual Basic 16 or MFC version 23. And in 5 years time, I fully expect that there will be something even better than Silverlight to write Windows apps in. If there isn’t, it will be Microsoft, not Silverlight that is dead.

Tuesday, 22 January 2008

Refactoring Windows Forms

I have been attempting to refactor some Windows Forms classes that contain hundreds of controls and have thousands of lines of code behind. What I would like to do is to group a load of controls together and make a new UserControl that contains them. The only trouble is, there seems no easy way to do this. None of the refactoring tools seem support it, and if you were to simply try to cut and paste the controls using the Windows Forms designer you would end up losing all your event handlers and potentially messing up the relative positioning of all your controls (lots of docking and anchoring is going on).

My approach in the end was to make a complete copy of the entire class in question and delete parts from it. Then I have spent two whole days trying to reduce the compiler error count to zero (I'm down to just 19 now from 387). Even so I now have a whole bunch of event handlers that need to be hooked up and a horrible feeling that my new panel will not quite work exactly like the old one did.

So what's the point of this post? Well just to say, wouldn't it be nice if one of the .NET refactoring tool companies would implement this? Allow you to select a bunch of GUI components on a form to move to a new UserControl, expose the appropriate properties and events, and hook up the old code to access the new control. Obviously you would want to perform more refactoring after doing this, to clean up the interface to your new UserControl, but it would be an invaluable tool in managing Windows Forms projects that have got out of control.