Posted by: Zeeshan Amjad | October 8, 2009

Creating Debugger Visualizer in WPF: Part 2


We already saw how to create a visual studio debugging visualizer in WPF. In that example we did everything in the C# code including defining data template. Although we can define data template in code completely, but it is not only recommended but we have to write lots of code.

Now lets 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.

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

  1: <Window 
  2:   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3:   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4:   Title="My Vsualizer" Height="300" Width="400" Background="Blue" 
  5:   WindowStartupLocation="CenterScreen">
  6:     
  7:     <ListBox Name="listBox" Margin="10" HorizontalContentAlignment="Stretch">
  8:         <ListBox.ItemTemplate>
  9:             <DataTemplate>
 10:                 <Border Background="LightYellow" BorderBrush="Brown" BorderThickness="5">
 11:                     <StackPanel Margin="5">
 12:                         <TextBlock Foreground="Black" FontWeight="Bold" Text="{Binding Path=Type}"/>
 13:                         <TextBlock Foreground="Black" Text="{Binding Path=Value}"/>
 14:                     </StackPanel>
 15:                 </Border>
 16:             </DataTemplate>
 17:         </ListBox.ItemTemplate>
 18:     </ListBox>    
 19: </Window>
 20: 

Now we are going to load the XAML file using XamlReader class. Here is a code to load the XAML file at run time.

  1: Window win = null;
  2: 
  3: FileStream fs = new FileStream("C:\\zamjad\\Projects\\MyVisualizer\\MyVisualizer\\VisualWindow.xaml", FileMode.Open, FileAccess.Read);
  4: 
  5: win = (Window)XamlReader.Load(fs);            
  6: 
  7: fs.Close();
  8: 

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.

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

Here is a complete C# code to load XAML file runtime and display the integer value in different formats.

  1: using System;
  2: using System.Collections.Generic;
  3: using System.Linq;
  4: using System.Text;
  5: using Microsoft.VisualStudio.DebuggerVisualizers;
  6: using System.Windows;
  7: using System.Windows.Controls;
  8: using System.Windows.Markup;
  9: using System.IO;
 10: 
 11: [assembly: System.Diagnostics.DebuggerVisualizer(
 12: typeof(MyVisualizer.MyVisualizerClass), typeof(VisualizerObjectSource),
 13: Target = typeof(System.Int32),Description = "My Visualizer")]
 14: namespace MyVisualizer
 15: {
 16:     public class MyVisualizerClass : DialogDebuggerVisualizer
 17:     {
 18:         private Int32 obj;
 19: 
 20:         protected override void Show(IDialogVisualizerService windowService, IVisualizerObjectProvider objectProvider)
 21:         {
 22:             obj = (Int32)objectProvider.GetObject();
 23: 
 24:             List<TypeValue> listType = new List<TypeValue>();
 25: 
 26:             listType.Add(new TypeValue("Decimal", obj.ToString()));
 27:             listType.Add(new TypeValue("Hex", obj.ToString("X")));
 28:             listType.Add(new TypeValue("Octal", DecimalToBase(obj, 8)));
 29:             listType.Add(new TypeValue("Binary", DecimalToBase(obj, 2)));
 30: 
 31:             Window win = null;
 32: 
 33:             FileStream fs = new FileStream("C:\\zamjad\\Projects\\MyVisualizer\\MyVisualizer\\VisualWindow.xaml", FileMode.Open, FileAccess.Read);
 34: 
 35:             win = (Window)XamlReader.Load(fs);            
 36: 
 37:             fs.Close();
 38: 
 39:             ListBox listBox = win.FindName("listBox") as ListBox;
 40: 
 41:             listBox.ItemsSource = listType;
 42:             win.ShowDialog();
 43:         }
 44: 
 45:         // This function is only for debugging purpose
 46:         public static void TestShowVisualizer(object obj)
 47:         {
 48:             VisualizerDevelopmentHost host = new VisualizerDevelopmentHost(obj, typeof(MyVisualizerClass));
 49:             host.ShowVisualizer();
 50:         }
 51: 
 52:         // Orignally written by Balamurali Balaji
 53:         // Changed little bit to handle the negative sign
 54:         // http://www.codeproject.com/KB/cs/balamurali_balaji.aspx
 55:         private string DecimalToBase(int number, int basenumber)
 56:         {
 57:             string strRetVal = "";
 58:             const int base10 = 10;
 59:             char[] cHexa = new char[] { 'A', 'B', 'C', 'D', 'E', 'F' };
 60:             int[] result = new int[32];
 61:             int MaxBit = 32;
 62:             bool isNegative = false;
 63: 
 64:             if (number < 0)
 65:             {
 66:                 isNegative = true;
 67:                 number *= -1;
 68:             }
 69: 
 70:             for (; number > 0; number /= basenumber)
 71:             {
 72:                 int rem = number % basenumber;
 73:                 result[--MaxBit] = rem;
 74:             }
 75: 
 76:             for (int i = 0; i < result.Length; i++)
 77:             {
 78:                 if ((int)result.GetValue(i) >= base10)
 79:                 {
 80:                     strRetVal += cHexa[(int)result.GetValue(i) % base10];
 81:                 }
 82:                 else
 83:                 {
 84:                     strRetVal += result.GetValue(i);
 85:                 }
 86:             }
 87: 
 88:             strRetVal = strRetVal.TrimStart(new char[] { '0' });
 89: 
 90:             if (isNegative)
 91:             {
 92:                 strRetVal = strRetVal.Insert(0, "-");
 93:             }
 94: 
 95:             return strRetVal;
 96:         }
 97:     }
 98: 
 99:     public class TypeValue
100:     {
101:         public TypeValue()
102:         {
103:         }
104: 
105:         public TypeValue(String type, String value)
106:         {
107:             Type = type;
108:             Value = value;
109:         }
110: 
111:         public String Type
112:         { get; set; }
113: 
114:         public String Value
115:         { get; set; }
116:     }
117: }
118: 

Wehn 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 will the “My Visualizer” option in context menu.

Visualizer_01

It is also available at watch window.

Visualizer_02

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.

Visualizer_03

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: