This article is for the WinForms developer learning WPF.
It introduces important new concepts, and lists differences, pitfalls & work-arounds.
Contributed to by those that have [or are still] taking that same journey.
If you are on that journey and know of anything that is missing, please add it to the article.
Or if your still searching, please return and add what you didn't find here! For the next weary traveler ;)
Leave "tutorial style specifics" out, but link to the best resources you found helped you.
Moving from Windows Forms to Windows Presentation Foundation can be a daunting and often confusing journey for even the most skilled developer. In fact the more hard core you are at Windows Forms, the more set in your ways you are in how to achieve the desired
result. At first, many controls and events seem so similar that a WinForm developer can get started straight away, and produce results very quickly. However, it is then common to hit a brick wall, or unknown exception that, once researched, the answer is unfortunately
to tear it all down and code it another way, the WPF way.
The first resources you should read and bookmark are these essential resources from MSDN:
You will see that some controls do not have a direct equivalent in WPF. However, there are many great solutions provided.
Here are the main, non-commercial sources:
This is a list of other aspects of development that differ between WinForms and WPF.
Windows Forms was all about rigidly positioned Location.X and Location.Y.
WPF is all about flexible, adaptable Grids and Panels.
In WinForms you can use containers like
TableLayoutPanel to group and dock controls into areas of the window. Also, a few controls use the
AutoSize property. But when you run the application and stretch the window out, the limitations are obvious. Which is why some WinForm developers just set Minimum and Maximum form size to the same.
When Windows Forms was conceived, there was not such a demand for different screen sizes and resolutions. With today's vast array of form factors and platforms, an application needs to adapt to many different screens and orientations. That is why WPF is
much more powerful than WinForms. Controls are laid out in flexible containers, and layout changes can be responsive to change, like orientation from Landscape to Portrait may mean moving some controls from an outer column to a bottom row. This is something
you must consider very early in design, or it will come back to bite you in production.
When picking up WPF, a WinForm developer will often adopt the Canvas as their first container, as controls within it have Canvas.Left and Canvas.Top to act as X and Y. Many early and basic tutorials use Canvas frequently. However, the WPF Canvas is rarely
needed in most applications unless you have good reason to need absolute positioning, like a graph, chessboard or drawing application (see InkCanvas). The Grid control is almost always the first choice for most experienced WPF'ers. With the
Grid you can chop up the page like a TableLayoutPanel, and it stretches in the same way.
What is very different is how the Children (the controls contained within each cell) react to change.
FPF child controls use HorizontalAlignment,
Margin. Parent containers usually have a
Padding property. These combined make the application adaptable and attractive through a much better range of window sizes. A child control, can
still be 'absolutely' positioned by setting
VerticalAlignment=Top, then setting the Margin.Left and Margin.Top (properties of
Thickness). However, the default
Alignment=Stretch, which when designing works best most often. The exception being Buttons and TextBoxes, which usually need at least a
The most important first step is to cut out your layout in terms of a
Grid. For example, a
Menu or RibbonControl may be in the first row or column,
as discussed here. Then each 'cell' of that parent (LayoutRoot) Grid may have another Grid or
StackPanel to group the next controls, then more within them. It is not uncommon to have StackPanels within StackPanels, within Grids, within Grids, etc, etc. It means when you stretch your window, everything just flows, it's a beautiful sight and a big
delight to many a Winform mover.
Grid rows and columns are measured by
GridLength and can be
Star, Pixel or Auto sized. Autosizing is a powerful tool to help the UI adapt to changes. Auto will take as much space as it needs, but no more than it requires. Star is a percentage (or weighted number) which defines how much of the total available space
it takes up, from the total of the other combined starred sections. This is a powerful concept new to WPF and needs a clear and early understanding.
In WinForms, code was used to generate DataGridView.Rows and you could add extra rows and delete them and traverse them to extract the controls and their data. All very long winded and prone to bugs.
In WPF the emphasis is on separating the User Interface from the Data. Rows in WPF DataGrids are usually generated out of bound collections of data, automatically from
DataTemplates and ColumnDefinitions, using the DataGrid's ItemsSource property.
WPF DataGrids have two states, read and edit. Data is automatically passed back through the bindings to the source data that is bound to it. This means you should work with the data, instead of traversing the control to extract data. This is particularly
relevant to list controls like DataGrid and ListBox, because they use Virtualization to destroy rows that are not scrolled into view. This is a much better and simpler way to manage data and it much more testable. If correctly wired up, a simple "Create, Update,
Delete" (CRUD) data browse add and edit application can be made with practically no lines of code at all.
Once fully understood, DataTemplates are one of the most powerful aspects of WPF that save heaps of development code, hundreds of "control creation" and "data shuffling" lines of code. This all means less mistakes, fewer tests, easier to understand code,
faster deployment time and less maintenance.
The emphasis on "separation of the data from the UI" means an application can much more easily be re-skinned. It also means application developers and UI designers can work independently of each other, in parallel, which can mean twice as fast development.
One of the popular design patterns for WPF is
Model View ViewModel (MVVM).
The View (Page/Window/Control) 'consumes' the ViewModel, to produce controls shown on the user interface. The ViewModel is the interface between View and Model (data). The ViewModel is responsible for collecting the data and presenting it [through
public properties] for the View to consume. Events are replaced with Commands. Styling, DataTemplates and Triggers give greater flexability to the designer, and keep all UI related 'business logic' in the UI.
For example, a [C#/VB.net] developer may expose a boolean IsReady property. It is up to the [XAML] designer how he consumes it. In one Control like the header bar, it may flash a green indicator. In the Window itself, it may trigger a new section to open.
The developer can then free themselves from shuffling data in and out of controls, and concentrate on data and application/enterprise level business logic, and wraping tests around the ViewModel much better than messy methods in a code-behind file. As long
as the developer and designer agree on which properties will be exposed, they can both work independently, with the designer using dummy data to produce his UI, while he waits for the real data to test his UI against.
Note that in teams which have no separate designers there is still a substantial development advantage from the clear separation of concerns mark up allows. One substantial benefit afforded by loosely coupled View and Code is that automated testing of the
code can be carried out without faking or mocking any UI. Obviating testing via the front end makes writing BDD and or TDD tests far easier. Such tests will readily run as "quick tests" so a developer can repeatedly write a test, change, test, fix and iterate
without leaving the development environment.
Naturally enough separation of concerns also offers it's usual benefits in terms of quicker development and easier maintenance of smaller pieces of code.
Be sure to read
Josh Smith's superb article about MVVM and WPF.
A very important concept to embrace in WPF is HOW controls are made.
This article is not to teach them, but to emphasize it's importance and provide some good starting references.
The visual element of a control is defined by it's
Elements in the ControlTemplate bind their properties to
TemplateBindings, to properties of the control like
Triggers which can react to changes in control properties like
MouseEnter, and affect other properties with setters, or
Exit actions, like running a
StoryBoard to animate a menu opening.
Property changes can be grouped into a
Style. A Style uses
Setters to change control properties. So you may have a "Red Button" style that sets
Button.Background to Red.
As ControlTemplate is also a property of the control, Styles can define that too, and change it based on a
Themes define the base controls. If Styling and Templating is [rarely] not enough, you can change the core Window control theme like Aero, or even define your own.
Commands are an alternative to events like the Click event, but are also more specific, like "Copy, "Cut" & "Paste". Commands don't have to be handled by the code-behind, they can come from a static resource, or a binding from your ViewModel or business
object. In WPF, you can define and reuse DataTemplates and ControlTemplates from Dictionaries. A button defined in a Template from another file cannot therefore have a Click event, if you don't know where it may be used, so the alternative is to use a Command,
which simply travels up the normal binding (VisualTree) path, only when it needs to.
Animation allows developers to enhance user experience by making the UI more attractive and focussing attention on the most important thing which is changing.
Expression Blend is a very powerful and useful tool for WPF UI developers.
For many developers Blend is very different from the Visual Studio environment they are used to. Blend can be somewhat daunting since it looks a "designer" orientated tool best left to graphic artists. At some point, the developer will wish to learn how to
extract templates from controls so they can understand how they work.
If you adopt Blend early, it will help you understand Templates, Styles, Triggers and Layout much faster. You can copy a template and see how a control is made, you can make animations with point and click and test your creations in real time and watch the
storyboard get scripted for you.
The visual studio designer in more recent versions of visual studio is the same as Blend and will run the Window/Page/Control's constructor. This can have implications to someone wishing to design even in visual studio because a clean constructor is necessary
for the designer to work properly. This is best explained by Laurent Bugnion in some of his videos where he describes writing for "blendability" and embodied in the MVVM Light toolkit templates.
Say you are working on a control which uses an RSS feed. Your RSS feed can load directly into your control within the designer, and you can work as shows live feeds - so long as it works using only objects supplied from that constructor.