Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

WPF Glimps - A Debugger Visualizer for WPF

0.00/5 (No votes)
15 Nov 2007 1  
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:

// 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:

// 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