Posted by: Zeeshan Amjad | October 11, 2009

Creating Debugger Visualizer in WPF: Part 4


Till now our visualizer were limited to only one data type i.e. integer data type. But any good visualizer is not limited to only one data type. Let’s extend our visualizer little bit more and handle more than one data type with it. In this case we are going to add the string data type support in our visualizer. This time we are going to display the string in upper case, lower case, its length and in base 64 encoded format.

We defined the attributes in our namespace which defined the supported data type by the visualizer. If we want to make our visualizer supported more than one data type, then we have to define that attribute more than once with different data type.

  1: [assembly: System.Diagnostics.DebuggerVisualizer(
  2: typeof(MyVisualizer.MyInt32Class), typeof(VisualizerObjectSource),
  3: Target = typeof(System.Int32),Description = "My Visualizer")]
  4: [assembly: System.Diagnostics.DebuggerVisualizer(
  5: typeof(MyVisualizer.MyStringClass), typeof(VisualizerObjectSource),
  6: Target = typeof(System.String), Description = "My Visualizer")]
  7: namespace MyVisualizer
  8: {
  9: }
 10: 

Our this visualizer supports two data type integer and string. To our simplicity we created different classes to handle string and integer data type. Our string class is almost similar to integer class display information in different format. Just for the simplicity we use the same window class for both integer and string type, but this is not a requirement.

  1: System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
  2: List<TypeValue> listType = new List<TypeValue>();
  3: 
  4: listType.Add(new TypeValue("String", obj));
  5: listType.Add(new TypeValue("Upper", obj.ToUpper()));
  6: listType.Add(new TypeValue("Lower", obj.ToLower()));
  7: listType.Add(new TypeValue("Length", obj.Length.ToString()));
  8: listType.Add(new TypeValue("Base 64 Encoding", Convert.ToBase64String(encoding.GetBytes(obj))));
  9: 

Here is a complete XAML file for our project.

  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="400" Width="400" Background="Wheat" 
  5:   WindowStartupLocation="CenterScreen">
  6:     <StackPanel>
  7:         <Border Margin="10" Background="AliceBlue" BorderBrush="Navy" BorderThickness="5" CornerRadius="5">
  8:             <StackPanel>
  9:                 <TextBlock Margin="5">Enter new Value</TextBlock>
 10:                 <TextBox Name="txtValue" Margin="5"/>
 11:             </StackPanel>    
 12:         </Border>
 13:         
 14:         <ListBox Name="listBox" Margin="10" HorizontalContentAlignment="Stretch">
 15:         <ListBox.ItemTemplate>
 16:             <DataTemplate>
 17:                 <Border Background="LightYellow" BorderBrush="Brown" BorderThickness="5">
 18:                     <StackPanel Margin="5">
 19:                         <TextBlock Foreground="Black" FontWeight="Bold" Text="{Binding Path=Type}"/>
 20:                         <TextBlock Foreground="Black" Text="{Binding Path=Value}"/>
 21:                     </StackPanel>
 22:                 </Border>
 23:             </DataTemplate>
 24:         </ListBox.ItemTemplate>
 25:     </ListBox>
 26:     <Button Name="btnOK" Margin="10" Width="75">OK</Button>
 27:     </StackPanel>
 28: </Window>
 29: 

And here is complete C# code of our project.

  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.MyInt32Class), typeof(VisualizerObjectSource),
 13: Target = typeof(System.Int32),Description = "My Visualizer")]
 14: [assembly: System.Diagnostics.DebuggerVisualizer(
 15: typeof(MyVisualizer.MyStringClass), typeof(VisualizerObjectSource),
 16: Target = typeof(System.String), Description = "My Visualizer")]
 17: namespace MyVisualizer
 18: {
 19:     public class MyStringClass : DialogDebuggerVisualizer
 20:     {
 21:         private Window win;
 22:         private String obj;
 23:         private IVisualizerObjectProvider objProvider;
 24: 
 25:         protected override void Show(IDialogVisualizerService windowService, IVisualizerObjectProvider objectProvider)
 26:         {
 27:             objProvider = objectProvider;
 28:             obj = (String)objProvider.GetObject();
 29: 
 30:             System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
 31:             List<TypeValue> listType = new List<TypeValue>();
 32: 
 33:             listType.Add(new TypeValue("String", obj));
 34:             listType.Add(new TypeValue("Upper", obj.ToUpper()));
 35:             listType.Add(new TypeValue("Lower", obj.ToLower()));
 36:             listType.Add(new TypeValue("Length", obj.Length.ToString()));
 37:             listType.Add(new TypeValue("Base 64 Encoding", Convert.ToBase64String(encoding.GetBytes(obj))));
 38: 
 39:             FileStream fs = new FileStream("C:\\zamjad\\Projects\\MyVisualizer\\MyVisualizer\\VisualizerWindow.xaml", FileMode.Open, FileAccess.Read);
 40: 
 41:             win = (Window)XamlReader.Load(fs);
 42:             win.Height = 450;
 43: 
 44:             fs.Close();
 45: 
 46:             ListBox listBox = win.FindName("listBox") as ListBox;
 47: 
 48:             listBox.ItemsSource = listType;
 49: 
 50:             Button buttonOK = win.FindName("btnOK") as Button;
 51: 
 52:             buttonOK.Click += new RoutedEventHandler(buttonOK_Click);
 53: 
 54:             win.ShowDialog();
 55: 
 56:         }
 57: 
 58:         void buttonOK_Click(object sender, RoutedEventArgs e)
 59:         {
 60:             TextBox text = win.FindName("txtValue") as TextBox;
 61: 
 62:             String newValue = text.Text;
 63: 
 64:             if (objProvider.IsObjectReplaceable)
 65:             {
 66:                 objProvider.ReplaceObject(newValue);
 67:             }
 68: 
 69:             win.Close();
 70:         }
 71: 
 72:         // This function is only for debugging purpose
 73:         public static void TestShowVisualizer(object obj)
 74:         {
 75:             VisualizerDevelopmentHost host = new VisualizerDevelopmentHost(obj, typeof(MyStringClass));
 76:             host.ShowVisualizer();
 77:         }
 78:     }
 79: 
 80:     public class MyInt32Class : DialogDebuggerVisualizer
 81:     {
 82:         private Int32 obj;
 83:         private Window win;
 84:         private IVisualizerObjectProvider objProvider;
 85: 
 86:         protected override void Show(IDialogVisualizerService windowService, IVisualizerObjectProvider objectProvider)
 87:         {
 88:             objProvider = objectProvider;
 89:             obj = (Int32)objProvider.GetObject();
 90: 
 91:             List<TypeValue> listType = new List<TypeValue>();
 92: 
 93:             listType.Add(new TypeValue("Decimal", obj.ToString()));
 94:             listType.Add(new TypeValue("Hex", obj.ToString("X")));
 95:             listType.Add(new TypeValue("Octal", DecimalToBase(obj, 8)));
 96:             listType.Add(new TypeValue("Binary", DecimalToBase(obj, 2)));
 97: 
 98:             FileStream fs = new FileStream("C:\\zamjad\\Projects\\MyVisualizer\\MyVisualizer\\VisualizerWindow.xaml", FileMode.Open, FileAccess.Read);
 99: 
100:             win = (Window)XamlReader.Load(fs);            
101: 
102:             fs.Close();
103: 
104:             ListBox listBox = win.FindName("listBox") as ListBox;
105: 
106:             listBox.ItemsSource = listType;
107: 
108:             Button buttonOK = win.FindName("btnOK") as Button;
109: 
110:             buttonOK.Click += new RoutedEventHandler(buttonOK_Click);
111: 
112:             win.ShowDialog();
113:         }
114: 
115:         void buttonOK_Click(object sender, RoutedEventArgs e)
116:         {
117:             TextBox text = win.FindName("txtValue") as TextBox;
118: 
119:             Int32 newValue = Convert.ToInt32(text.Text);
120: 
121:             if (objProvider.IsObjectReplaceable)
122:             {
123:                 objProvider.ReplaceObject(newValue);
124:             }
125: 
126:             win.Close();
127:         }
128: 
129:         // This function is only for debugging purpose
130:         public static void TestShowVisualizer(object obj)
131:         {
132:             VisualizerDevelopmentHost host = new VisualizerDevelopmentHost(obj, typeof(MyInt32Class));
133:             host.ShowVisualizer();
134:         }
135: 
136:         // Orignally written by Balamurali Balaji
137:         // Changed little bit to handle the negative sign
138:         // http://www.codeproject.com/KB/cs/balamurali_balaji.aspx
139:         private string DecimalToBase(int number, int basenumber)
140:         {
141:             string strRetVal = "";
142:             const int base10 = 10;
143:             char[] cHexa = new char[] { 'A', 'B', 'C', 'D', 'E', 'F' };
144:             int[] result = new int[32];
145:             int MaxBit = 32;
146:             bool isNegative = false;
147: 
148:             if (number < 0)
149:             {
150:                 isNegative = true;
151:                 number *= -1;
152:             }
153: 
154:             for (; number > 0; number /= basenumber)
155:             {
156:                 int rem = number % basenumber;
157:                 result[--MaxBit] = rem;
158:             }
159: 
160:             for (int i = 0; i < result.Length; i++)
161:             {
162:                 if ((int)result.GetValue(i) >= base10)
163:                 {
164:                     strRetVal += cHexa[(int)result.GetValue(i) % base10];
165:                 }
166:                 else
167:                 {
168:                     strRetVal += result.GetValue(i);
169:                 }
170:             }
171: 
172:             strRetVal = strRetVal.TrimStart(new char[] { '0' });
173: 
174:             if (isNegative)
175:             {
176:                 strRetVal = strRetVal.Insert(0, "-");
177:             }
178: 
179:             return strRetVal;
180:         }
181:     }
182: 
183:     public class TypeValue
184:     {
185:         public TypeValue()
186:         {
187:         }
188: 
189:         public TypeValue(String type, String value)
190:         {
191:             Type = type;
192:             Value = value;
193:         }
194: 
195:         public String Type
196:         { get; set; }
197: 
198:         public String Value
199:         { get; set; }
200:     }
201: }
202: 

Now if we use this visualizer for string data type then its output will be something like this.

Visualizer_05

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: