Writing a Debugger Visualizer in WPF: Part 1

Wednesday Jun 23rd 2010 by Zeeshan Amjad

Share:

There are lots of good examples of creating a debugger visualizer for Visual Studio, but one thing that this is common is that all of them are written using Windows form. It is, however, possible to make a debugger visualizer in WPF, and thus display data in a much more sophisticated way using modern technology.

1. Introduction

There are a lot of good examples of how to create a debugger visualizer for Visual Studio. One thing that is common among all of them, is that they are all written using Windows form. I got a question on the Microsoft forum asking whether it is possible to make debugger visualizer in WPF. I decided to do an experiment. After playing with it a little bit, I realized that it is possible to make a debugger visualizer even in WPF. This opens a whole new door for me, because now data can be displayed in a much more sophisticated way using modern technology.

2. Background

Let's take a look at the first step. To make a debugger visualizer, we have to create a class that is inherited by DialogDebuggerVisualizer class. This class is defined in using Microsoft.VisualStudio.DebuggerVisualizers; namespace, so we have to include its reference too. This namespace defines other classes and interfaces for not only writing the debuger visualizer, but also to debug the visualizer itself. Here is a block diagram to show the classes and interfaces in this namespace.

All of these classes are inherited directly by Object class the grand daddy of .Net framework.Here is a class diagram of all classes define in Microsoft.VisualStudio.DebuggerVisualizer namespace.

There is only one method to overload in the DialogDebuggerVisualizer class, and here is the signature of that method.

The class diagram of this class is very simple. Here is a class diagram of this class.
The method inherited by Object class isn't shown.

Now here is a little catch. In a traditional Windows form debugger, we are going to call
the ShowDialog method of IDialogVisualizerService interface that will internally call the Windows form. IdialogVisualizerService interface has only one method ShowDialog. This method is overloaded and can accept only CommonDialog, Control or Form. Here is a class diagram of this interface.

If we want to make a WPF based visualizer, then we have to create a Window object and call it ourselves.
In its simplest way it is something like this:

Don't forget to add the references of "WindowsBase", "PresentationCore", "PresentationFramework" and "Microsoft.VisualStudio.DebuggerVizualiers", in the project.Here is a screen shot of Solution Explorer after adding the reference of WPF dlls and debugger vizualisers dll.

This will display the WPF visualizer window with a blue background. Let's do little bit more and make one working application. This is just a proof of concept, so we are making one small application. Our visualizer works only with Int32 data type. We defined it at the form of attribute when defining the namespace for our visualizer.

Here text set into the "Description" property will display as a context menu when this vizualizer
is loaded during the debugging. We select Int32 data type just for simplicity because this type is also serializeable. If we want to make visualizer of our custom data type or any other non serializeable data type then we have to override GetData method of class that implements IVisualizerObjectProvider interface.

Now we have two ways to display our data if we are going to use any template to for better output. One simple, fast and preferred way is to write XAML and load that XAML programmatically. The other approach is to make everything programmatically.

3. Defining Data template with Code

Our target is to display the value of integer variable in four different formats. We will display integer in decimal, hex decimal, octal and binary format. Let's first make a small function for base conversion. I picked this function from
CodeProject originally written by "Balamurali Balaji" and modified it little bit to handle the negative number. Here is modified version of base convertor.

When we copy the visualizer DLL at specified location (in my computer it is C:\Program Files\Microsoft Visual Studio 9.0\Common7\Packages\Debugger\Visualizers) then for all integer variable we can see the "My Visualizer" option in context menu during debugging.

[DebuggerVisualizers_06.gif]

It is also available at watch window as shown in this screen shot.

[DebuggerVisualizers_07.gif]

And when we clicked on it then we can see our visualizer window with list box in it to display the value of integer in hex, octal and binary format. Here is the output of this.

4. Defining Data Template with XAML

Although we can define data template in code completely, but it is not recommended. In addition we have to write lots of code. Now let's take a look at recommended approach. This time we are going to make XAML file and load that file at run time. This approach will make our work easier and we can use the full power of not only XAML, but also WPF very easily.

Let's first make a XAML file and notice this code is very small as compare to define everything in C#. Here is our XAML file.

If we want to access any control defined in that XAML file then we can use the FindName function. Here is a code to access the ListBox define in the XAML file.

ListBox listBox = win.FindName("listBox") as ListBox;

We also have to include two more namespaces to read the XAML file. These namespaces are System.IO and System.Windows.Markup. Here is a complete C# code to load XAML file runtime and display the integer value in different formats.

We have to copy the VisualWindow.xaml file in the same folder where the dll reside. i.e. in the debugger visualer folder. Now if user clicks on the MyVisualizer menu items either at the code window or watch window then one WPF window will pop and its output would be something like this.

[DebuggerVisualizers_08.gif]

5. Summary

We created one simple Debugger visualizer in WPF with integer data type,
but this is a read-only visualizer and supports only one data type. In the comming article
I will extend this concept to add support of more than one data type. In addition we will also add the support for editing data.