Posted by: Zeeshan Amjad | October 9, 2009

Creating Debugger Visualizer in WPF: Part 3


In previous discussion we created one visualizer using XAML file. Now lets move forward and improve the functionality of our visualizer. Our previous visualizer was the read only visualizer i.e. we can only view the data in it. Now we are going to make a visualizer that is interactive, i.e. it has a feature to change the value of variable.

The basic concept behind this is to use the ReplaceObject function of IVisualizerObjectProvider interface. We added one text box in our WPF window to enter data. Here is a piece of code of that new text box.

  1: <Border Margin="10" Background="AliceBlue" BorderBrush="Navy" BorderThickness="5" CornerRadius="5">
  2:     <StackPanel>
  3:         <TextBlock Margin="5">Enter new Value</TextBlock>
  4:         <TextBox Name="txtValue" Margin="5"/>
  5:     </StackPanel>    
  6: </Border>
  7: 

The name of our new text box is “txtValue”. We use the same FindWindow technique to get the value of this text box and then call ReplaceObject. After that we close the window.

  1: TextBox text = win.FindName("txtValue") as TextBox;
  2: 
  3: Int32 newValue = Convert.ToInt32(text.Text);
  4: 
  5: if (objProvider.IsObjectReplaceable)
  6: {
  7:     objProvider.ReplaceObject(newValue);
  8: }
  9: 
 10: win.Close();
 11: 

Here is a complete XAML code of this program.

  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: 

Here is complete C# code of this 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.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:         private Window win;
 20:         private IVisualizerObjectProvider objProvider;
 21: 
 22:         protected override void Show(IDialogVisualizerService windowService, IVisualizerObjectProvider objectProvider)
 23:         {
 24:             objProvider = objectProvider;
 25:             obj = (Int32)objProvider.GetObject();
 26: 
 27:             List<TypeValue> listType = new List<TypeValue>();
 28: 
 29:             listType.Add(new TypeValue("Decimal", obj.ToString()));
 30:             listType.Add(new TypeValue("Hex", obj.ToString("X")));
 31:             listType.Add(new TypeValue("Octal", DecimalToBase(obj, 8)));
 32:             listType.Add(new TypeValue("Binary", DecimalToBase(obj, 2)));
 33: 
 34:             FileStream fs = new FileStream("C:\\zamjad\\Projects\\MyVisualizer\\MyVisualizer\\VisualWindow.xaml", FileMode.Open, FileAccess.Read);
 35: 
 36:             win = (Window)XamlReader.Load(fs);            
 37: 
 38:             fs.Close();
 39: 
 40:             ListBox listBox = win.FindName("listBox") as ListBox;
 41: 
 42:             listBox.ItemsSource = listType;
 43: 
 44:             Button buttonOK = win.FindName("btnOK") as Button;
 45: 
 46:             buttonOK.Click += new RoutedEventHandler(buttonOK_Click);
 47: 
 48:             win.ShowDialog();
 49:         }
 50: 
 51:         void buttonOK_Click(object sender, RoutedEventArgs e)
 52:         {
 53:             TextBox text = win.FindName("txtValue") as TextBox;
 54: 
 55:             Int32 newValue = Convert.ToInt32(text.Text);
 56: 
 57:             if (objProvider.IsObjectReplaceable)
 58:             {
 59:                 objProvider.ReplaceObject(newValue);
 60:             }
 61: 
 62:             win.Close();
 63:         }
 64: 
 65:         // This function is only for debugging purpose
 66:         public static void TestShowVisualizer(object obj)
 67:         {
 68:             VisualizerDevelopmentHost host = new VisualizerDevelopmentHost(obj, typeof(MyVisualizerClass));
 69:             host.ShowVisualizer();
 70:         }
 71: 
 72:         // Orignally written by Balamurali Balaji
 73:         // Changed little bit to handle the negative sign
 74:         // http://www.codeproject.com/KB/cs/balamurali_balaji.aspx
 75:         private string DecimalToBase(int number, int basenumber)
 76:         {
 77:             string strRetVal = "";
 78:             const int base10 = 10;
 79:             char[] cHexa = new char[] { 'A', 'B', 'C', 'D', 'E', 'F' };
 80:             int[] result = new int[32];
 81:             int MaxBit = 32;
 82:             bool isNegative = false;
 83: 
 84:             if (number < 0)
 85:             {
 86:                 isNegative = true;
 87:                 number *= -1;
 88:             }
 89: 
 90:             for (; number > 0; number /= basenumber)
 91:             {
 92:                 int rem = number % basenumber;
 93:                 result[--MaxBit] = rem;
 94:             }
 95: 
 96:             for (int i = 0; i < result.Length; i++)
 97:             {
 98:                 if ((int)result.GetValue(i) >= base10)
 99:                 {
100:                     strRetVal += cHexa[(int)result.GetValue(i) % base10];
101:                 }
102:                 else
103:                 {
104:                     strRetVal += result.GetValue(i);
105:                 }
106:             }
107: 
108:             strRetVal = strRetVal.TrimStart(new char[] { '0' });
109: 
110:             if (isNegative)
111:             {
112:                 strRetVal = strRetVal.Insert(0, "-");
113:             }
114: 
115:             return strRetVal;
116:         }
117:     }
118: 
119:     public class TypeValue
120:     {
121:         public TypeValue()
122:         {
123:         }
124: 
125:         public TypeValue(String type, String value)
126:         {
127:             Type = type;
128:             Value = value;
129:         }
130: 
131:         public String Type
132:         { get; set; }
133: 
134:         public String Value
135:         { get; set; }
136:     }
137: }
138: 

Now when we click on the MyVisualizer either on Watch window or context menu which appears when click on the integer variable then we will see the following window.

Visualizer_04

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: