Click here to Skip to main content
15,883,769 members
Articles / Desktop Programming / WPF
Article

WPF Glimps - A Debugger Visualizer for WPF

Rate me:
Please Sign up or sign in to vote.
4.10/5 (7 votes)
15 Nov 20072 min read 46.6K   741   31   5
A debugger visualizer that displays a preview of a WPF visual in the debugger
Screenshot - display_in_visualizer.gif

Introduction

WpfVisualVisualizer "Glimps" enables you to preview a WPF control within the Visual Studio debugger while stepping through the application code, making it easier to debug complex WPF user interfaces.

Screenshot

Josh Smith has already written an excellent debugger visualizer, that allows you to inspect properties of WPF elements, which can be found here.

Background

In WPF applications, there are often lots and lots of visuals. When you're debugging, it is often hard to know which visual element is referenced by a certain variable.

WpfVisualVisualizer renders a Visual or Control to a small image that you can preview in the debugger. This works with any kind of Visual, even Videos or 3D, once it is initialized and loaded.

Deploying Glimpse

Please see Josh Smith's article on how to deploy a Visual Studio debugger visualizer here. It is a great read, anyway.

How to Use It

When Glimps is installed, you can select it from the tooltip if you hover over a WPF visual in the debugger, as seen in the screenshot at the top of the page.

Limitations

UIElements and FrameworkElements must be initialized and loaded before they can be displayed. As a result, when you put a breakpoint in the constructor, you won't see anything.

How it Works

A debugger visualizer consists of two parts:

The first part (IVisualizerObjectProvider) runs within the process of your application. This part is responsible for gathering and serializing the required information that will be displayed in Visual Studio.

The second part (DialogDebuggerVisualizer) runs within the Visual Studio debugger and is responsible for displaying the information. This is the actual Visualizer.

In order to display a WPF visual as a thumbnail image in Visual Studio, it must be rendered to bitmap in the context of the application, then converted to a GDI image. This will be sent over the wire to the visualizer, which is a simple WinForms dialog.

The DebuggerVisualizer requests the data it will visualize by calling the GetData method on the ObjectProvider. GetData returns a Stream which contains the serialized data.

The visualizer and object provider are tightly coupled, so the visualizer knows that the Stream contains an image and will display it in a PictureBox:

C#
// Display the visual in Visual Studio
protected override void Show(IDialogVisualizerService windowService, 
    IVisualizerObjectProvider objectProvider)
{
    // read the serialized (GDI-)image from the stream
    Stream s = objectProvider.GetData();
    Image image = Image.FromStream(s);
  
    // prepare the form 
    Form form = new Form();
    form.Text = "WPF Visual";
    form.ClientSize = new DrawingSize
        (WpfVisualObjectSource.MaxSize.Width, image.Height);
    form.FormBorderStyle = FormBorderStyle.FixedToolWindow;
    if (image != null)
    {
        PictureBox pictureBox = new PictureBox();
        pictureBox.Image = image;
        pictureBox.Parent = form;
        pictureBox.Dock = DockStyle.Fill;
        form.Controls.Add(pictureBox);
    }
    // show the form
    windowService.ShowDialog(form);
}

On the ObjectProvider side, the targeted WPF visual needs to be rendered to a BitmapSource and then converted to a GDI image that we can display in WinForms:

C#
// create image data from WPF visual
public override void GetData(object target, Stream outgoingData)
{
    Image img = null;
    
    // target is a bitmap source: convert it to a GDI image
    if (target is BitmapSource)
    {
        img = BitmapSourceToGdiImage((BitmapSource)target);
    }

    if (target is FrameworkElement)
    {
        FrameworkElement fe = (FrameworkElement)target;
        if (!fe.IsLoaded) img = CreateEmptyBitmap();
    }
    
    // target is a visual: render it to a RenderTargetBitmap and 
    // convert to GDI
    if (img==null && target is Visual)
    {
        BitmapSource bmpSource = CreateBitmapSource((Visual)target);
        img = BitmapSourceToGdiImage(bmpSource);
    }            

    if (img == null) img = new Bitmap(0, 0);

    // save image to stream and dispose of GDI image
    img.Save(outgoingData, ImageFormat.Bmp);
    img.Dispose();
}

History

  • 11/15/2007 - Uploaded first version
  • 11/16/2007 - Josh Smith added Glimps to Woodstock for WPF and also made some improvements in the code. He was kind enough to add me as an author.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Germany Germany
Florian Krüsch works as a Freelance Software Architect, Developer and Consultant in Düsseldorf, Germany.

He is excited about WPF, Silverlight and ASP.net as well as Enterprise Development on the .NET platform.

When not thinking, coding or listening to podcasts, he enjoys spending his time with his family and his little son Nicki.



Comments and Discussions

 
GeneralAmazing Pin
Rama Krishna Vavilala15-Nov-07 11:07
Rama Krishna Vavilala15-Nov-07 11:07 
GeneralRe: Amazing Pin
Steve Hansen15-Nov-07 11:58
Steve Hansen15-Nov-07 11:58 
GeneralRe: Amazing Pin
Sacha Barber15-Nov-07 20:43
Sacha Barber15-Nov-07 20:43 
GeneralNice Job Pin
Josh Smith15-Nov-07 10:23
Josh Smith15-Nov-07 10:23 
GeneralRe: Nice Job Pin
Zajda8215-Nov-07 20:08
Zajda8215-Nov-07 20:08 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.