I dislike WPF. I’ve always found it overly complex and over-engineered, with a steep learning curve. The Visual Studio designer often struggles to render XAML forms effectively. For lightweight client applications, an HTML5 Single Page Application (SPA) using a modern JavaScript framework is typically sufficient. This approach can even be suitable for some desktop applications. If not, and for applications purely on the client-side, you could explore HTML5 combined with Node.js options like [discussed here](URL_PLACEHOLDER_0). However, in the business world, Windows desktop applications remain necessary and in demand. Even then, I’d rather stick with Windows Forms over WPF, and it seems I’m not alone.
There are plenty of poorly designed Windows Forms applications out there, often carrying over the issues from the old VB5 and VB6 days. But that’s not the fault of Windows Forms itself. Many developers have created well-designed WinForms applications. The use of MVC (or more accurately, MVP) patterns, as shown in [here](URL_PLACEHOLDER_1), is similar to what I’ve used in my own WinForms projects.
This led me to question the advantages of WPF over WinForms. My research yielded no definitive answers but did refresh my understanding of how Windows GUI applications work.
Besides XAML, recommended patterns, and newer controls, the main difference between WinForms and WPF is the rendering approach. WPF utilizes DirectX, which can offload rendering to the GPU, while WinForms relies on GDI, which uses the CPU for rendering. Theoretically, WPF should have faster drawing performance. However, WPF objects are inherently heavier than WinForms objects in .NET. You can delve deeper into this in these Stack Overflow discussions: [[1]](URL_PLACEHOLDER_2) and [[2]](URL_PLACEHOLDER_3).
An interesting point raised there is:
That being said, if you have a LOT of controls, WPF can actually outperform Windows Forms by a fair amount. In Windows Forms, each control requires a separate window handle, and receives its own message sets. With a lot of controls, this can actually slow things down pretty dramatically.
So, in the Windows world, WPF controls are lighter-weight. But what’s the deal with window handles and messages?
The core of any Windows GUI application (whether .NET or native) is the [Message Loop](URL_PLACEHOLDER_4). The main thread of your application continuously checks for messages (like clicks, timer events, refresh requests, etc.). When a message is detected, it’s forwarded to the code (Windows Procedure) associated with the relevant Window. The concept of a “Window” is crucial here. In this context, a “Window” (a Win32 Window) isn’t just your typical window with a title bar and buttons. It also includes controls like buttons, combo boxes, and text boxes. You can see this here: [CreateWindow](URL_PLACEHOLDER_5). They are instantiated using the Win32 function CreateWindow. This is how frameworks like WinForms, classic VB, and MFC create their controls.
Both WinForms and WPF rely on the Windows message loop (which Application.Run manages behind the scenes). However, WinForms operates closer to the underlying Win32 mechanisms. It predominantly utilizes the CreateWindowEx function from user32.dll to create controls. This function, in turn, uses GDI for rendering. As stated elsewhere:
User32.dll is a core Windows DLL responsible for windowing and user interactions. WPF doesn’t use it extensively. Windows.Forms primarily acts as a .NET wrapper around User32 and thus relies entirely on GDI, GDI+, and window handles.
WPF, on the other hand, utilizes CreateWindow only for creating top-level windows. It then renders its controls within these windows using DirectX, essentially drawing them like shapes. Imagine how HTML controls work: An HTML button or textbox might resemble its WinForms counterpart, but it’s not a true Windows Control; it’s a shape drawn by the browser (using, for instance, [Cairo](URL_PLACEHOLDER_7) in Firefox).
You can observe this difference using a tool like [Winspector](URL_PLACEHOLDER_8). Try selecting a control within both a WinForms application and a WPF application.
In WinForms, you can directly select individual controls, like a button:
However, in WPF, you can only select the overall window:



