Introduction

Windows Presentation Foundation (WPF) is a joy to develop rich user experiences with. Animations, bindings, reskinnable codeless interfaces, all backed up with traditional .Net programming all make for a very rapid development cycle. However, when something
goes wrong in that autogenerated super-sexy front-end, it is not always clear where the problem is.

This article will cover some of the methods for analyzing your WPF application, troubleshooting issues, and debugging seemingly obscure errors.

Binding Errors

When an error occurs in the binding framework, the notification is usually "silent", in that is doesn't pop up an error dialog to the user. The error is instead displayed in the
Output Window of Visual Studio. Although the errors seem obscure at first, there are only a few common ones and they are quite helpful messages.

This is a ComboBox inside a DataGridTemplateColumn. I am binding its ItemsSource to a property called PartIds.
It is erroring when looking for the binding source, in other words the physical object to find the property on.
In this example, the error was because the source is a Window, not a UserControl.

This is when the property name in the binding expression is wrong, or the property does not exist in the source object.
In this example, the property name was misspelled with a 'z'.

Sometimes you will need a more detailed debugging output for binding. There are two ways to do this.

1. Changing Trace Level for All in Options

Click the Visual Studio menu Tools / Options, then open
Debugging and Output Window. In there you can change the
DataBinding output settings to Verbose or
All.

(click to enlarge)

2. Changing Trace Level on a Specific Binding

If you increase the trace level that way, you will get a WHOLE LOAD of messages for everything. Far better to target the specific binding where the error is. To do this, you can call on an Attached Property PresentationSources.TraceLevel and set it for just
the one binding.

Inner Exceptions

When your application raises an exception, and you are debugging in Visual Studio, you get the usual error dialog with the details. However, when the error is a XAML error, it is most frequently buried deeper in the exception details.

Within each exception is an Inner Exception, which is just another exception, but from a layer further down. If XAML throws an error about a missing resource, it re-raises the error as a meaningless "XAML Markup error". When you drill down deeper, you find
what resource the actual error relates to.

In the examples below, I show how to try and mark the exceptions as handled/observed, and continue execution. However, you may just want to close "gracefully", with a polite message, instead of an all-out crash.

One thing is certain, you will probably want a unified way of handling the exceptions, wherever they come from, as shown below.

Drilling down to include the Inner Exceptions

As mentioned before, the real reason for an error could be buried several layers down in Inner Exceptions. The three handlers above shared one error logging method, shown below, which iterates down till there are no more Inner Exceptions.

privatevoid
ProcessError(Exception exception)

{

var error =
"Exception = "
+ exception.Message;

while(exception.InnerException !=
null)

{

exception = exception.InnerException;

error +=
" : Inner Exception = "
+ exception.Message;

}

//This is where you save to file.

MessageBox.Show(error);

}

Early attention to error handling in your application will always help production, because most bugs occur during development.

Commenting Out and Binary Chopping

If a bug in your application is being particularly hard to find, there may be only one way left to find the culprit. It's very simple, and is often simply the fastest way to drill down to the offender.

The method is simply to remove (or comment out) sections of your code, or XAML, until you get execution PAST the error.

Then you start replacing parts of the removed code, until you find the exact control or method that is causing the problem.

It is referred to as binary chopping because you cut the code into two, to get past the error, then in two again, replacing half of the removed code, and so on until you get down to the offending code/xaml.

You can comment out huge chunks of your code or markup in Visual Studio with ctrl-k + c, then ctrl-k + u to uncomment. Both functions also available in the edit / advanced menu.

This is one of the advantages of writing your application to the MVVM design pattern. MVVM separates your UI (View) from the business logic supplied by the ViewModel, or the Model itself. This means the View is much more loosely coupled, and there are no hooks
from code-behind, acting directly on controls, like referring to controls by name (x:Name) like MyTextBox.Text = "hello". In MVVM the emphasis is all on the bindings, so commenting out half your XAML just means less binding requests, and commenting out half
your code/properties means more binding errors, but not a crash.

Even an MVVM setup can have problems when you try to comment out half the markup. Controls may be relying on other controls, with direct biding in XAML. So there is always a certain amount of "knock-on" effects that also need commenting out, but experience
often shows it is quite simply a very fast and effective way to find the sinner.

Just make sure you keep a copy of the original file (or have recently committed your code to source control) before such dramatic actions. Just in case you make an edit that looses your comment/cut history ;)

Is It Reproducable?

When you hit a brick wall, many people turn to the
MSDN forums, for help and advice from other developers. Often, just the act of trying to put a problem into words for others to understand is equivalent to having a colleague look over your shoulder, which often catches those obvious "too close to the trees"
kind of mistakes that we all make.

However, if the problem isn't obvious from your description, you will get a much quicker and accurate response from the forum if you supply a
reproducable example of your problem in a few code snippets.

Quite often, when you try to reproduce the problem in a new project, you will often find the culpret anyway!

Logging

The other age old method of tracing bugs in your application, both in development and once released, is to keep a log of messages from every notable step of your application.

If your bug is of a composite nature (comprising of several different causes), or developing after several iterations, or at an unknown point, you will need to build a picture of what is happening, before you can even know where to start.

Logging Level

Writing comments and session data to a log file means scattering "WriteToLog" type methods throughout your code. It is therefore common to build a "LogLevel" parameter into your methods, allowing you to control the amount of spam that gets written. In a
published application you would only want to capture critical messages, but with a config file flag or startup parameter that allows you to crank up the debug logging (logging ALL messages), for a client that experiences a bug.

Repository Choice

A log repository can be anything from a text file, to a database. One word of caution however. It is no good logging errors to a database if it was a database connection error. So file based logging for critical errors is strongly advised. Then you simply
have a check method on application startup, for any waiting critical error files, that may have been generated when the application crashed. You can then 'process' them (into a database, or send by email) and then delete.

It is as explained, quite simple to create your own logging architecture for your application. The key to success is to START EARLY! Don't try to strap error handling or logging on later, as it will never be as useful as if you had started from the outset.
Also, the majority of bugs are caused during development anyway, so early attention to error handling and logging may take slightly longer to code, but will help speed up the overall prodiuction process.

Why Reinvent the Wheel

You could have a lot of fun building your own error logging framework, that is thread safe and foolproof. Or if you're pushed for time or more interested in higher things, why not just adopt a tried and tested logging framework. Here are some options, but
you should shop around, as new kids often come on the block.

One of the most established frameworks."log4net is a tool to help the programmer output log statements to a variety of output targets. In case of problems with an application, it is helpful to enable logging so that
the problem can be located. With log4net it is possible to enable logging at runtime without modifying the application binary. The log4net package is designed so that log statements can remain in shipped code without incurring a high performance cost. It follows
that the speed of logging (or rather not logging) is crucial. At the same time, log output can be so voluminous that it quickly becomes overwhelming. One of the distinctive features of log4net is the notion of hierarchical loggers. Using these loggers it is
possible to selectively control which log statements are output at arbitrary granularity. log4net is designed with two distinct goals in mind: speed and flexibility"

A very popular framework. "Stands for Logging Modules and Handlers. An application-wide error logging facility that is completely pluggable. It can be dynamically added to a running ASP.NET web application, or even all ASP.NET web applications
on a machine, without any need for re-compilation or re-deployment."

Newer but 3rd popular "A logging platform for .NET with rich log routing and management capabilities. It can help you produce and manage high-quality logs for your application regardless of its size or complexity."

All of the above frameworks are available through NuGet. If you don't already have NuGet, it is like an App store for Visual Studio application development. If you want a logging framework, or an MVVM framework, simply open the package manager and search.
Results are listed by popularity. Click to install, and the package gets downloaded and integrated into your current project. That means all the dlls are added and registered, and any supporting files are added to your project. It takes all the pain out of
adding supporting packages to your project. This is a must for all developers. No excuses, get it naow!!