<?xml version="1.0"?>
<rss version="2.0">
<channel>
<title>Theo Gray</title>
<link>http://www.theogray.com/blog/</link>
<description></description>
<copyright>Copyright 2010, Theo Gray</copyright>
<generator>Blog Admin v2.0</generator>
<ttl>60</ttl>
<lastBuildDate>Mon, 26 Jul 2010 13:35:49 GMT</lastBuildDate>
<pubDate>Mon, 26 Jul 2010 13:35:49 GMT</pubDate>
<language>en-us</language>
<image>
  <title>Theo Gray</title>
  <url>http://www.theogray.com/i/tg150x50.gif</url>
  <link>http://www.theogray.com/blog/</link>
</image>
<item>
  <title>The International Routing System scam</title>
  <link>http://www.theogray.com/blog/2010/07/international-routing-system</link>
  <description>&lt;p&gt;I've just had a call from a charming Indian gentlemen telling me he was from the &lt;b&gt;International Routing System&lt;/b&gt; and that my computer was generating a lot of traffic which was disrupting the "International Routing Systems".&lt;/p&gt;
&lt;p&gt;Apparently he had my phone number because my IP address was creating all this traffic and so he wanted to show me how to cleanup my machine. I thought it could be fun to find out how he was going to try to scam me, so let him continue...&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Me: "So what's my IP address?"&lt;/li&gt;
  &lt;li&gt;IG: "I don't have that in front of me at the moment"&lt;/li&gt;
  &lt;li&gt;Me: "riigggt... so what would you like me to do to stop all this traffic blocking up the International Routings Systems?"&lt;/li&gt;
  &lt;li&gt;IG: "Please press the flag key and R on your keyboard"&lt;/li&gt;
  &lt;li&gt;Me: "OK"&lt;/li&gt;
  &lt;li&gt;IG: "type the letters 'i', 'n', 'f' - it stands for 'infection'"&lt;/li&gt;
  &lt;li&gt;Me: "OK, I've done that"&lt;/li&gt;
  &lt;li&gt;IG: "Now click OK"&lt;/li&gt;
  &lt;li&gt;Me: "Uh huh"&lt;/li&gt;
  &lt;li&gt;IG: "What do you see?"&lt;/li&gt;
  &lt;li&gt;Me: "A list of all the drivers installed on my computer"&lt;/li&gt;
  &lt;li&gt;IG: "You're wasting my time and your time, now bugger off"... beeeeeeeeeeeep&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Unfortunately caller ID only showed he was calling from an "International" number so I couldn't call him back to find out more about his wonderful International Routing System or what other things he was going to get me to do to my computer.&lt;/p&gt;</description>
  <pubDate>Mon, 26 Jul 2010 13:17:53 GMT</pubDate>
  <category>Telephone Scams</category>
  <category>Internet Scams</category>
  <guid isPermaLink="true">http://www.theogray.com/blog/2010/07/international-routing-system</guid>
  <comments>http://www.theogray.com/blog/2010/07/international-routing-system#readercomments</comments>
</item>
<item>
  <title>The Secret Diary of Michael Schumacher... returns</title>
  <link>http://www.theogray.com/blog/2010/01/secret-diary-of-michael-schumacher-returns</link>
  <description>&lt;p&gt;&lt;img src="http://www.theogray.com/formula-1/images/part2010-0120.jpg" width="240" height="180" alt="Michael Schumacher" align="right" class="inline_right" /&gt;With the 2010 return of &lt;a href="http://www.theogray.com/formula-1/schumacher-secret-diary.asp"&gt;The Secret Diary of Michael Schumacher&lt;/a&gt; on Planet-F1, I've just added another year's worth of old entries back onto the interweb for your reading pleasure.&lt;/p&gt;
&lt;p&gt;Read all his entries from 2002 to 2004, plus links to the latest entries in &lt;a href="http://www.theogray.com/formula-1/schumacher-secret-diary.asp"&gt;The Secret Diary of Michael Schumacher&lt;/a&gt;.&lt;/p&gt;</description>
  <pubDate>Thu, 21 Jan 2010 00:00:00 GMT</pubDate>
  <category>Formula 1</category>
  <category>Michael Schumacher</category>
  <guid isPermaLink="true">http://www.theogray.com/blog/2010/01/secret-diary-of-michael-schumacher-returns</guid>
  <comments>http://www.theogray.com/blog/2010/01/secret-diary-of-michael-schumacher-returns#readercomments</comments>
</item>
<item>
  <title>Manual tagging on Facebook</title>
  <link>http://www.theogray.com/blog/2010/01/manual-tagging-on-facebook</link>
  <description>&lt;p&gt;Tagging of people in the text of status updates has been available on Facebook for a while now, but it still isn't available everywhere, such as comments and photo descriptions.&lt;/p&gt;
&lt;p&gt;Luckily if you really want to tag someone in text in some of these other places (I've only made it work in photo descriptions so far) then you can do so. In addition you can manually tag people within status updates giving them whatever name you want.&lt;/p&gt;
&lt;p&gt;All you have to do is include the following format in your text and Facebook will automatically display tag links:&lt;/p&gt;
&lt;pre class="brush:vb;light:true;"&gt;
Tagging @[USERID:blah] in a comment
&lt;/pre&gt;
&lt;p&gt;Where &lt;tt&gt;USERID&lt;/tt&gt; is the numeric Facebook ID of the user you want to tag, and &lt;tt&gt;blah&lt;/tt&gt; can be any string.&lt;/p&gt;
&lt;p&gt;So, for example:&lt;br /&gt;
&lt;tt&gt;Tagging @[721981740:Theo] in a comment&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;is displayed in Facebook as:&lt;br /&gt;
&lt;tt&gt;Tagging &lt;a href="http://www.facebook.com/profile.php?id=721981740"&gt;Theo&lt;/a&gt; in a comment&lt;/tt&gt;&lt;/p&gt;</description>
  <pubDate>Sat, 02 Jan 2010 10:42:22 GMT</pubDate>
  <category>Facebook</category>
  <guid isPermaLink="true">http://www.theogray.com/blog/2010/01/manual-tagging-on-facebook</guid>
  <comments>http://www.theogray.com/blog/2010/01/manual-tagging-on-facebook#readercomments</comments>
</item>
<item>
  <title>The Our Domain Set</title>
  <link>http://www.theogray.com/blog/2009/12/our-domain-set</link>
  <description>&lt;p&gt;It has to be said that over the years I have purchased quite a few domain names, but there was one that I have wanted for a while to add to the set of OurCarnival.co.uk, OurChurch.co.uk and OurPanto.co.uk - that being OurVillage.co.uk.&lt;/p&gt;
&lt;p&gt;And yesterday I managed to buy it off the current owner, so finally the Eaton Bray website is available via &lt;a href="http://www.ourvillage.co.uk/"&gt;www.ourvillage.co.uk&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;And if you hadn't heard yet, the &lt;a href="http://www.christmaspuzzle.co.uk/"&gt;Christmas Puzzle&lt;/a&gt; is now available to download!&lt;/p&gt;</description>
  <pubDate>Tue, 08 Dec 2009 11:08:27 GMT</pubDate>
  <category>Eaton Bray</category>
  <category>Domain Names</category>
  <guid isPermaLink="true">http://www.theogray.com/blog/2009/12/our-domain-set</guid>
  <comments>http://www.theogray.com/blog/2009/12/our-domain-set#readercomments</comments>
</item>
<item>
  <title>Christmas Puzzle 2009 - Time gentlemen please</title>
  <link>http://www.theogray.com/blog/2009/12/christmas-puzzle-2009-time-gentlemen-please</link>
  <description>&lt;p&gt;&lt;a href="http://www.christmaspuzzle.co.uk/"&gt;&lt;img alt="Christmas Puzzle" hspace=12 src="http://www.eatonbray.com/news/images/christmas-puzzle.gif" width="200" align="right" class="inline_right noborder" /&gt;&lt;/a&gt;This year's annual Charity &lt;a href="http://www.christmaspuzzle.co.uk/"&gt;Christmas Puzzle&lt;/a&gt; has now been posted, and is available to download. 
&lt;p&gt;This, the 19th annual Puzzle that Gordon Gray has set, has a theme designed to help completion and will appeal to people who enjoy doing Crossword puzzles, such as in the Daily Telegraph (though it is not a Crossword puzzle). Puzzlers have plenty of time to find the answers and Puzzles should be returned, with donation, by 24 January. 
&lt;p align="center"&gt;&lt;b&gt;Four winners will each receive a &amp;pound;25 prize.&lt;br /&gt;Everyone who enters will qualify for a &amp;pound;25 prize draw.&lt;/b&gt; 
&lt;p&gt;So what are you waiting for, give it a go and download the &lt;a href="http://www.christmaspuzzle.co.uk/"&gt;Christmas Puzzle&lt;/a&gt; now.&lt;/p&gt;</description>
  <pubDate>Tue, 08 Dec 2009 11:01:22 GMT</pubDate>
  <category>Hobbies</category>
  <category>Christmas</category>
  <guid isPermaLink="true">http://www.theogray.com/blog/2009/12/christmas-puzzle-2009-time-gentlemen-please</guid>
  <comments>http://www.theogray.com/blog/2009/12/christmas-puzzle-2009-time-gentlemen-please#readercomments</comments>
</item>
<item>
  <title>COMException Class not registered on 64-bit Windows</title>
  <link>http://www.theogray.com/blog/2009/10/comexception-regdbeclassnotreg-on-64-bit-windows</link>
  <description>&lt;p&gt;Having finally got myself running live on Windows 7, this morning it was time to fix the one problem remaining - &lt;b&gt;Visual Studio 2008 throwing the COMException "Class not registered"&lt;/b&gt; (REGDB_E_CLASSNOTREG) when trying to call InitializeComponent on a form which has an ActiveX control on it:&lt;/p&gt;
&lt;pre class="brush:js;light:true;"&gt;
System.Runtime.InteropServices.COMException (0x80040154): Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG))
   at System.Windows.Forms.UnsafeNativeMethods.CoCreateInstance(Guid&amp;amp; clsid, Object punkOuter, Int32 context, Guid&amp;amp; iid)
   at System.Windows.Forms.AxHost.CreateWithoutLicense(Guid clsid)
   at System.Windows.Forms.AxHost.CreateWithLicense(String license, Guid clsid)
   at System.Windows.Forms.AxHost.CreateInstanceCore(Guid clsid)
   at System.Windows.Forms.AxHost.CreateInstance()
   at System.Windows.Forms.AxHost.GetOcxCreate()
   at System.Windows.Forms.AxHost.TransitionUpTo(Int32 state)
   at System.Windows.Forms.AxHost.CreateHandle()
   at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
   at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
   at System.Windows.Forms.AxHost.EndInit()
   at OCXWrappers.TXTextControl.InitializeComponent() in C:\Users\...\Form1.Designer.vb:line 42
&lt;/pre&gt;
&lt;p&gt;Hunting around Google turned up nothing (the OCX was definately registered correctly), but I did twig after a few minutes... The ActiveX control in question was 32-bit, whereas Visual Studio defaults to compile to "Any CPU" and I was now running 64-bit Windows.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Solution&lt;/b&gt;: Go into the Project Properties, Compile tab and click "Advanced Compile Options...". Change "Target CPU" to x86, click OK, save and try again.&lt;/p&gt;
&lt;p&gt;Presumably this is the same problem as others have had when trying to run on Windows XP / Server 2003 and above when the customer is running 64-bit and the development environment is 32-bit.&lt;/p&gt;</description>
  <pubDate>Mon, 05 Oct 2009 11:53:02 GMT</pubDate>
  <category>VB</category>
  <category>Net</category>
  <category>Microsoft</category>
  <guid isPermaLink="true">http://www.theogray.com/blog/2009/10/comexception-regdbeclassnotreg-on-64-bit-windows</guid>
  <comments>http://www.theogray.com/blog/2009/10/comexception-regdbeclassnotreg-on-64-bit-windows#readercomments</comments>
</item>
<item>
  <title>Custom DataGridViewColumn &amp;amp; IDataGridViewEditingControl classes</title>
  <link>http://www.theogray.com/blog/2009/06/custom-datagridviewcolumn-idatagridvieweditingcont</link>
  <description>&lt;p&gt;Having just spent the last few hours getting my head round how custom &lt;tt&gt;DataGridView&lt;/tt&gt; column code fitted together in VB.Net I thought it only fair to share in the hope that I can speed up the process for others.&lt;/p&gt;
&lt;h3&gt;The setup&lt;/h3&gt;
&lt;p&gt;In my case I was looking to use a custom usercontrol in an editable grid; a custom usercontrol that extends the standard &lt;tt&gt;ComboBox&lt;/tt&gt; in all sorts of ways (and is already written &amp;amp; tested).&lt;/p&gt;
&lt;p&gt;Unlike examples such as the &lt;a href="http://msdn.microsoft.com/en-us/library/7tas5c80.aspx" target="_blank"&gt;DateTimePicker column&lt;/a&gt; and others such as the Colour Pickers on CodeProject etc, I was looking to both display a plain text value in the cell when not in edit mode and also to store/load a completely different numeric lookup value within the bound data. &lt;a href="#_note1"&gt;[1]&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Useful points&lt;/h3&gt;
&lt;p&gt;A few points that I would have found useful to know before starting are:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;What is &lt;tt&gt;FormattedValue&lt;/tt&gt;?&lt;/b&gt;&lt;br /&gt;
  It appears that &lt;tt&gt;FormattedValue&lt;/tt&gt; is the information stored within the bound data which is also referred to as just &lt;tt&gt;Value&lt;/tt&gt; in other places. &lt;a href="#_note2"&gt;[2]&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;At what point should I replace standard columns with custom ones?&lt;/b&gt;&lt;br /&gt;
  Use the &lt;tt&gt;DataGridView.DataSourceChanged&lt;/tt&gt; event. &lt;a href="#_note3"&gt;[3]&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;How many instances of each control will be created?&lt;/b&gt;&lt;br /&gt;
    The creation of the &lt;tt&gt;Cell&lt;/tt&gt; and &lt;tt&gt;EditingControl&lt;/tt&gt; control instances is handled by the &lt;tt&gt;DataGridView&lt;/tt&gt; control and is out of the developer's hands. This gives you:&lt;ul&gt;
    &lt;li&gt;One &lt;tt&gt;ComboBoxColumn&lt;/tt&gt; instance per column.&lt;/li&gt;
    &lt;li&gt;One &lt;tt&gt;ComboBoxCell&lt;/tt&gt; instance per cell.&lt;/li&gt;
    &lt;li&gt;One &lt;tt&gt;ComboBoxEditingControl&lt;/tt&gt; instance &lt;b&gt;PER GRID&lt;/b&gt;.&lt;br /&gt; This last one is very important to recognise as it affects decisions later.&lt;/li&gt;
  &lt;/ul&gt;&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;How does the &lt;tt&gt;DataGridView&lt;/tt&gt; know which &lt;tt&gt;Cell&lt;/tt&gt; and &lt;tt&gt;EditingControl&lt;/tt&gt; classes to instantiate?&lt;/b&gt;&lt;ul&gt;
  &lt;li&gt;[line 46 below]: The &lt;tt&gt;CellTemplate&lt;/tt&gt; property of the custom &lt;tt&gt;Column&lt;/tt&gt; class defines the custom &lt;tt&gt;Cell&lt;/tt&gt; class to use. This can be specified in the &lt;tt&gt;DataGridViewColumn&lt;/tt&gt; constructor.&lt;/li&gt;
  &lt;li&gt;[line 95 below]: The &lt;tt&gt;EditType&lt;/tt&gt; property in the custom &lt;tt&gt;Cell&lt;/tt&gt; class tells &lt;tt&gt;DataGridView&lt;/tt&gt; which class to use as the editing control for the cell.&lt;/li&gt;
  &lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;On to the code&lt;/h3&gt;
&lt;p&gt;A note about the Extended ComboBox control: The control supports properties such as an &lt;tt&gt;ImageList&lt;/tt&gt; used for displaying images in the drop down, and a &lt;tt&gt;SelectedIDValue&lt;/tt&gt; which is forced to be either &lt;tt&gt;DBNull.Value&lt;/tt&gt; or a &lt;tt&gt;Long&lt;/tt&gt; value for easy binding to a field in a database.&lt;/p&gt;
&lt;p&gt;To walk through the code, we'll start at the outer &lt;tt&gt;DataGridView&lt;/tt&gt; level and work inwards.&lt;/p&gt;
&lt;h3&gt;DataSourceChanged event&lt;/h3&gt;
&lt;p&gt;First the &lt;tt&gt;DataSourceChanged&lt;/tt&gt; event handler which we use to replace the standard &lt;tt&gt;DataGridViewTextColumn&lt;/tt&gt;s with custom columns. The code is structured with a &lt;tt&gt;Select Case&lt;/tt&gt; so that other custom column types (like &lt;tt&gt;CalendarColumn&lt;/tt&gt; for &lt;tt&gt;DateTime&lt;/tt&gt; types) are simple to add later.&lt;/p&gt;
&lt;pre class="brush:vb;"&gt;
Private Sub OnDataSourceChanged(ByVal sender As Object, _
    ByVal e As System.EventArgs) Handles DataGridView1.DataSourceChanged

    Dim OriginalColumn, NewColumn As DataGridViewColumn
    Dim ColumnIndex As Integer

    For Each OriginalColumn In DataGridView1.Columns
        'Reset the NewColumn variable
        NewColumn = Nothing 

        'Decide if we need to replace the current column
        Select Case GetDBType(OriginalColumn.ValueType)
            Case SqlDbType.BigInt, SqlDbType.Int
                'Replace BigInt and Int columns with the ComboBoxColumn type
                'Pass the Sql used to display the content of the drop down
                NewColumn = _
                    New ComboBoxColumn(GetLookupSql(OriginalColumn.Name))

        End Select

        'If we have a new column to replace
        If NewColumn IsNot Nothing Then
            'Get the current index of the old column
            ColumnIndex = MyBase.Columns.IndexOf(OriginalColumn)
            'Copy the basic information from the old column
            NewColumn.DataPropertyName = OriginalColumn.DataPropertyName
            NewColumn.HeaderText = OriginalColumn.HeaderText
            NewColumn.Name = OriginalColumn.Name
            'Remove the old column
            MyBase.Columns.Remove(OriginalColumn)
            'Add the new one where the old one used to be
            MyBase.Columns.Insert(ColumnIndex, NewColumn)
        End If
   Next
End Sub
&lt;/pre&gt;
&lt;p&gt;See CodeProject for the implementation of &lt;tt&gt;&lt;a href="http://www.codeproject.com/KB/vb/ConvToSqlDbType.aspx" target="_blank"&gt;GetDbType&lt;/a&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;h3&gt;ComboBoxColumn class&lt;/h3&gt;
&lt;p&gt;Next we need to create the basic &lt;tt&gt;ComboBoxColumn&lt;/tt&gt; class. Line 46 is important to hooking the Column to its related CellTemplate class, and the rest of the code allows us to simply pass in the Sql to use for populating the drop down list.&lt;/p&gt;
&lt;pre class="brush:vb;first-line:40;"&gt;
Public Class ComboBoxColumn
    Inherits DataGridViewColumn

    Friend DropDownDataSource As DataTable

    Public Sub New(ByVal DataSource As String)
        MyBase.New(New ComboBoxCell())

        'Open a DataTable from the specified Sql
        DropDownDataSource = OpenLookupDataTable(DataSource)
    End Sub
End Class
&lt;/pre&gt;
&lt;p&gt;We should override the &lt;tt&gt;CellTemplate&lt;/tt&gt; property and check that the value being passed to it is of the correct type, but I leave that for the reader to add if they want (along with the simple code for things like &lt;tt&gt;OpenLookupDataTable&lt;/tt&gt; [ln49] and &lt;tt&gt;GetLookupSql&lt;/tt&gt; [ln17]). This article is keeping to the basics of what we need to get things working and show how the classes interact.&lt;/p&gt;
&lt;h3&gt;ComboBoxCell class&lt;/h3&gt;
&lt;p&gt;Next we need the &lt;tt&gt;ComboBoxCell&lt;/tt&gt; class. This is where most of the extra work is done.&lt;/p&gt;
&lt;pre class="brush:vb;first-line:60;"&gt;
Public Class ComboBoxCell
    Inherits DataGridViewTextBoxCell

    Private DisplayValue As String = Nothing

    Public Overrides Sub InitializeEditingControl(ByVal rowIndex As Integer, _
        ByVal initialFormattedValue As Object, _
        ByVal dataGridViewCellStyle As DataGridViewCellStyle)
        
        MyBase.InitializeEditingControl(rowIndex, _
            initialFormattedValue, _
            dataGridViewCellStyle)

        'Cast the EditingControl to a variable we can work with
        Dim ctl As ComboBoxEditingControl = _
            DirectCast(DataGridView.EditingControl, ComboBoxEditingControl)

        'Cast the OwningColumn to a variable we can work with
        Dim col As ComboBoxColumn = DirectCast(Me.OwningColumn, ComboBoxColumn)

        'Tell the ComboBox what to display in the drop down
        ctl.DataSource = col.DropDownDataSource
        
        'Important: Tell the ComboBoxEditingControl that this is now 
        '           the owner cell for the control
        ctl.OwnerCell = Me
    End Sub

    Friend Sub SetDisplayValue(ByVal NewValue As String)
        DisplayValue = NewValue
    End Sub

    Public Overrides ReadOnly Property EditType() As Type
        Get
            ' Return the type of the editing contol that ComboBoxCell uses.
            Return GetType(ComboBoxEditingControl)
        End Get
    End Property

    Public Overrides ReadOnly Property ValueType() As Type
        Get
            ' Return the type of the value that ComboBoxCell contains.
            Return GetType(Long)
        End Get
    End Property

    Public Overrides ReadOnly Property DefaultNewRowValue() As Object
        Get
            ' Use DBNull as the default cell value.
            Return DBNull.Value
        End Get
    End Property

    Protected Overrides Sub Paint(ByVal graphics As System.Drawing.Graphics, _
        ByVal clipBounds As System.Drawing.Rectangle, _
        ByVal cellBounds As System.Drawing.Rectangle, ByVal rowIndex As Integer, _
        ByVal cellState As DataGridViewElementStates, _
        ByVal value As Object, ByVal formattedValue As Object, _
        ByVal errorText As String, ByVal cellStyle As DataGridViewCellStyle, _
        ByVal advancedBorderStyle As DataGridViewAdvancedBorderStyle, _
        ByVal paintParts As DataGridViewPaintParts)
        
        'The first time in, make sure that we get the initial DisplayValue
        If DisplayValue Is Nothing Then SetDisplayValue(LookupDisplayValue(value))
        
        'Override paint to pass DisplayValue instead of formattedValue
        MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, _
            DisplayValue, errorText, cellStyle, advancedBorderStyle, paintParts)
    End Sub

End Class
&lt;/pre&gt;
&lt;p&gt;The reason we have to reset &lt;tt&gt;ComboBox.DataSource&lt;/tt&gt; [ln81] every time is due to the fact that the &lt;tt&gt;DataGridView&lt;/tt&gt; only creates a single instance of &lt;tt&gt;ComboBoxEditingControl&lt;/tt&gt; regardless of which cell the user attempts to edit.&lt;/p&gt;
&lt;p&gt;We use the &lt;tt&gt;OwnerCell&lt;/tt&gt; property [ln85] to ensure that the &lt;tt&gt;ComboBoxEditingControl&lt;/tt&gt; knows which &lt;tt&gt;ComboBoxCell&lt;/tt&gt; to communicate with when the user selected a new item in the drop down list.&lt;/p&gt;
&lt;p&gt;Using the &lt;tt&gt;Paint&lt;/tt&gt; method in this way allows us to keep the styling of the cells controlled by the underlying Microsoft provided code. &lt;a href="#_note6"&gt;[6]&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The &lt;tt&gt;LookupDisplayValue&lt;/tt&gt; method finds the text to display using &lt;tt&gt;OwningColumn.DropDownDataSource&lt;/tt&gt; so that the first time the cell is painted we know which value to display.&lt;/p&gt;
&lt;h3&gt;ComboBoxEditingControl class&lt;/h3&gt;
&lt;p&gt;And finally, the class that only has a single instance during the lifetime of the grid... &lt;a href="#_note7"&gt;[7]&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In a similar way to the &lt;tt&gt;CalendarColumn&lt;/tt&gt; from MSDN we inherit from the underlying extended &lt;tt&gt;ComboBox&lt;/tt&gt; control and then use the &lt;tt&gt;SelectedValueChanged&lt;/tt&gt; event to update the currently connected &lt;tt&gt;ComboBoxCell&lt;/tt&gt;.&lt;/p&gt;
&lt;pre class="brush:vb;first-line:150"&gt;
Public Class ComboBoxEditingControl
    Inherits ExtendedComboBox
    Implements IDataGridViewEditingControl

    Private dataGridViewControl As DataGridView
    Private valueIsChanged As Boolean = False
    Private rowIndexNum As Integer
    Private currentCell As ComboBoxCell = Nothing

    Public Property OwnerCell() As ComboBoxCell
        Get
            Return currentCell
        End Get
        Set(ByVal value As ComboBoxCell)
            'Clear currentCell so DoSelectedValueChanged doesn't cause an endless loop
            currentCell = Nothing
            'Set SelectedIDValue
            MyBase.SelectedIDValue = value.Value
            'Show that the value hasn't changed yet
            valueIsChanged = False
            'Finally remember the new Owner Cell
            currentCell = value
        End Set
    End Property

    Public Sub ApplyCellStyleToEditingControl(_
        ByVal dataGridViewCellStyle As DataGridViewCellStyle) _
        Implements IDataGridViewEditingControl.ApplyCellStyleToEditingControl
        
        Me.Font = dataGridViewCellStyle.Font
        Me.ForeColor = dataGridViewCellStyle.ForeColor
        Me.BackColor = dataGridViewCellStyle.BackColor
    End Sub

    Public Property EditingControlDataGridView() As DataGridView _
        Implements IDataGridViewEditingControl.EditingControlDataGridView
        Get
            Return dataGridViewControl
        End Get
        Set(ByVal value As DataGridView)
            dataGridViewControl = value
        End Set
    End Property

    Public Property EditingControlFormattedValue() As Object _
        Implements IDataGridViewEditingControl.EditingControlFormattedValue
        Get
            Return MyBase.SelectedIDValue
        End Get
        Set(ByVal value As Object)
            MyBase.SelectedIDValue = value
        End Set
    End Property

    Public Property EditingControlRowIndex() As Integer _
        Implements IDataGridViewEditingControl.EditingControlRowIndex
        Get
            Return rowIndexNum
        End Get
        Set(ByVal value As Integer)
            rowIndexNum = value
        End Set
    End Property

    Public Property EditingControlValueChanged() As Boolean _
        Implements IDataGridViewEditingControl.EditingControlValueChanged
        Get
            Return valueIsChanged
        End Get
        Set(ByVal value As Boolean)
            valueIsChanged = value
        End Set
    End Property

    Public Function EditingControlWantsInputKey(ByVal keyData As Keys, _
        ByVal dataGridViewWantsInputKey As Boolean) As Boolean _
        Implements IDataGridViewEditingControl.EditingControlWantsInputKey
       
        Return True
    End Function

    Public ReadOnly Property EditingPanelCursor() As Cursor _
        Implements IDataGridViewEditingControl.EditingPanelCursor
        Get
            Return MyBase.Cursor
        End Get
    End Property

    Public Function GetEditingControlFormattedValue( _
        ByVal context As DataGridViewDataErrorContexts) As Object _
        Implements IDataGridViewEditingControl.GetEditingControlFormattedValue
        
        Return MyBase.SelectedIDValue
    End Function

    Public Sub PrepareEditingControlForEdit(ByVal selectAll As Boolean) _
        Implements IDataGridViewEditingControl.PrepareEditingControlForEdit
    End Sub

    Public ReadOnly Property RepositionEditingControlOnValueChange() As Boolean _
        Implements IDataGridViewEditingControl.RepositionEditingControlOnValueChange
        Get
            Return False
        End Get
    End Property

    Private Sub DoSelectedValueChanged(ByVal sender As Object, _
        ByVal e As System.EventArgs) Handles Me.SelectedValueChanged

        If currentCell IsNot Nothing Then
            'Remember that the value has changed
            valueIsChanged = True
            'Pass back the new ID
            currentCell.Value = MyBase.SelectedIDValue
            'Pass back the new display value
            currentCell.SetDisplayValue(MyBase.Text)
        End If
    End Sub
End Class
&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;I hope these four blocks of code give a simple overview of how the custom &lt;tt&gt;DataGridViewColumn&lt;/tt&gt; classes connect and interact and will make the setup a little easier for at least one other person!&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;hr class="required" /&gt;
&lt;h3&gt;Footnotes&lt;/h3&gt;
&lt;ol style="list-style-type:decimal;"&gt;
&lt;li id="_note1"&gt;One option would have been to extend the &lt;tt&gt;DataGridViewComboBoxColumn&lt;/tt&gt; and &lt;tt&gt;DataGridViewComboBoxCell&lt;/tt&gt; classes, but this would have meant duplicating the majority of the code from the already tested control.&lt;/li&gt;
&lt;li id="_note2"&gt;There are many methods and properties in relation to custom columns that mention &lt;tt&gt;FormattedValue&lt;/tt&gt; and to begin with I presumed the difference between this and &lt;tt&gt;Value&lt;/tt&gt; was that one was the display value and the other was the value stored in the bound data. After spending a long time trying to make this work, all of the error messages suggested that &lt;tt&gt;FormattedValue&lt;/tt&gt; and &lt;tt&gt;Value&lt;/tt&gt; should in fact be left containing same data.&lt;/li&gt;
&lt;li id="_note3"&gt;My first thought was that the best place to switch from the default &lt;tt&gt;Grid.DataGridTextColumn&lt;/tt&gt; to the custom column would be in the &lt;tt&gt;Grid.ColumnAdded&lt;/tt&gt; event as I presumed this would be fired before any rows were added and so save the grid doing things twice. &lt;a href="#_note4"&gt;[4]&lt;/a&gt;&lt;ul&gt;
  &lt;li&gt;No! If the columns are replaced in &lt;tt&gt;Grid.ColumnAdded&lt;/tt&gt; then they will later be re-added outside of the developer's control &lt;a href="#_note5"&gt;[5]&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;The next idea was to do it during &lt;tt&gt;Grid.DataBindingComplete&lt;/tt&gt; at which point I found that this event is called twice after setting &lt;tt&gt;Grid.DataSource&lt;/tt&gt; &lt;a href="#_note5"&gt;[5]&lt;/a&gt; and that the only safe way to switch columns was to do it on the second call to &lt;tt&gt;Grid.DataBindingComplete&lt;/tt&gt; (this event is fired for many different reasons so using it seemed rather hacky).&lt;/li&gt;
  &lt;li&gt;Finally I found the answer lay in the &lt;tt&gt;Grid.DataSourceChanged&lt;/tt&gt; event which fires only once after setting &lt;tt&gt;Grid.DataSource&lt;/tt&gt; and appears to work as expected.&lt;/li&gt;
  &lt;/ul&gt;&lt;/li&gt;
&lt;li id="_note4"&gt;This was the VB6 developer in me that had previously spent years using &lt;a href="http://www.vbaccelerator.com/home/VB/Code/Controls/S_Grid_2/" target="_blank"&gt;SGrid2&lt;/a&gt; and its predecessor and so presumed that the data would be fully parsed while being assigned to the grid costing cycles.&lt;/li&gt;
&lt;li id="_note5"&gt;This took a while to figure out! It appears that if the column is replaced in either the &lt;tt&gt;ColumnAdded&lt;/tt&gt; event or the first firing of the  &lt;tt&gt;DataBindingComplete&lt;/tt&gt; event, then on the second round of binding (no one seems to understand why this has to happen twice) the original version of the custom column that had custom properties assigned to it is dumped and replaced with a fresh one that only has standard &lt;tt&gt;DataGridViewColumn&lt;/tt&gt; properties assigned such as &lt;tt&gt;DataPropertyName&lt;/tt&gt;.&lt;/li&gt;
&lt;li id="_note6"&gt;It was the structure of the &lt;tt&gt;Paint&lt;/tt&gt; method in taking &lt;tt&gt;value&lt;/tt&gt; and &lt;tt&gt;formattedValue&lt;/tt&gt; parameters, and only displaying the contents of &lt;tt&gt;formattedValue&lt;/tt&gt; that led me to believe that &lt;tt&gt;FormattedValue&lt;/tt&gt; in the &lt;tt&gt;EditingControl&lt;/tt&gt; class could be different from &lt;tt&gt;Cell.Value&lt;/tt&gt;. &lt;a href="#_note2"&gt;[2]&lt;/a&gt;&lt;/li&gt;
&lt;li id="_note7"&gt;Although only one instance of the &lt;tt&gt;EditingControl&lt;/tt&gt; is created by default, I would imagine there are methods within the custom &lt;tt&gt;Cell&lt;/tt&gt; class that can be overridden to provide the developer with more flexibility.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Disclaimer: All sample code is provided for illustrative purposes only. These examples have not been thoroughly tested under all conditions. There is no guarantee or implied reliability, serviceability, or function of these programs.&lt;/em&gt;&lt;/p&gt;</description>
  <pubDate>Tue, 02 Jun 2009 08:33:20 GMT</pubDate>
  <category>VB</category>
  <category>Net</category>
  <category>Microsoft</category>
  <guid isPermaLink="true">http://www.theogray.com/blog/2009/06/custom-datagridviewcolumn-idatagridvieweditingcont</guid>
  <comments>http://www.theogray.com/blog/2009/06/custom-datagridviewcolumn-idatagridvieweditingcont#readercomments</comments>
</item>
<item>
  <title>Internet Explorer and the Unknown runtime error</title>
  <link>http://www.theogray.com/blog/2009/06/internet-explorer-unknown-runtime-error</link>
  <description>&lt;p&gt;As a developer I've come across my fair share of annoying Microsoft error messages, so I wasn't too suprised when I randomly hit the following Javascript error in IE8:&lt;/p&gt;
&lt;p align="center"&gt;&lt;tt&gt;Unknown runtime error&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;Even better, if I switched to IE7 compatibility mode I got the old:&lt;/p&gt;
&lt;p align="center"&gt;&lt;tt&gt;[object error]&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;Having tracked down the line that was causing the problem, it appears that the Javascript hook into the DOM is rather more strict (or maybe buggy!) when setting &lt;tt&gt;innerHTML&lt;/tt&gt; than when using &lt;tt&gt;document.write&lt;/tt&gt;.&lt;/p&gt;
&lt;h3&gt;document.write&lt;/h3&gt;
&lt;p&gt;The following line of code works and displays the expected output:&lt;/p&gt;
&lt;pre class="brush:js;light:true;"&gt;
document.write('&amp;lt;p id="extraNote"&amp;gt;&amp;lt;div class="somethingSpecial"&amp;gt;Hello&amp;lt;/div&amp;gt;&amp;lt;/p&amp;gt;');
&lt;/pre&gt;
&lt;h3&gt;innerHTML&lt;/h3&gt;
&lt;p&gt;And the following works as expected in all browsers except IE:&lt;/p&gt;
&lt;pre class="brush:js;light:true;"&gt;
// Done when the page is initially displayed
document.write('&amp;lt;p id="extraNote"&amp;gt;&amp;lt;/p&amp;gt;');

// Done in a seperate function that works out what should really go in extraNote
var note = document.getElementById("extraNote");
note.innerHTML='&amp;lt;div class="somethingSpecial"&amp;gt;Hello&amp;lt;/div&amp;gt;';
&lt;/pre&gt;
&lt;h3&gt;The fix&lt;/h3&gt;
&lt;p&gt;Having worked out why IE was being annoying, the fix was very simple...&lt;/p&gt;
&lt;p align="center"&gt;replace &lt;tt&gt;&amp;lt;p id="extraNote"&amp;gt;&lt;/tt&gt; with &lt;tt&gt;&amp;lt;div id="extraNote"&amp;gt;&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;... but it's obvious IE8 still has random IEisms, and proves that when it comes to supporting IE, that even now you have to fully test even the most minor of code changes (&lt;tt&gt;extraNote&lt;/tt&gt; used to be a table cell rather than a paragraph i.e. &lt;tt&gt;&amp;lt;td id="extraNote"&amp;gt;&lt;/tt&gt;).&lt;/p&gt;
&lt;hr class="required" /&gt;
&lt;p&gt;&lt;b&gt;Update:&lt;/b&gt; Just checked the &lt;a href="http://channel9.msdn.com/Wiki/InternetExplorerProgrammingBugs/" target="_blank"&gt;IE Programming Bugs Wiki&lt;/a&gt; and see that this is apparently "by design" - "&lt;em&gt;Can't put invalid HTML in the document: You cannot assign a string to innerHTML or outerHTML that contains invalid HTML. For example, trying to replace the content of the P element with another P will fail. A P element can only contain text and inline elements. However, replacing the entire P element with another P would work just fine.&lt;/em&gt;"&lt;/p&gt;
&lt;p&gt;This seems like a very wierd limitation, especially as it's possible to edit the DOM directly and create a &amp;lt;div&amp;gt; within a &amp;lt;p&amp;gt; tag in IE, but there we go. Case closed I guess.&lt;/p&gt;</description>
  <pubDate>Mon, 01 Jun 2009 18:10:46 GMT</pubDate>
  <category>VB</category>
  <category>Net</category>
  <category>Microsoft</category>
  <guid isPermaLink="true">http://www.theogray.com/blog/2009/06/internet-explorer-unknown-runtime-error</guid>
  <comments>http://www.theogray.com/blog/2009/06/internet-explorer-unknown-runtime-error#readercomments</comments>
</item>
<item>
  <title>All work and no play makes Jack a dull boy</title>
  <link>http://www.theogray.com/blog/2009/05/all-work-no-play-makes-jack-dull-boy</link>
  <description>&lt;p&gt;&lt;img src="http://www.theogray.com/blog/images/shining-lost.jpg" alt="Shining Lost" width="200" height="135" align="right" class="inline_right imgborder" /&gt;You can probably guess what I watched last night, but this &lt;a href="http://en.wikipedia.org/wiki/All_work_and_no_play_makes_Jack_a_dull_boy" target="_blank"&gt;Jack&lt;/a&gt; has also been working way too much recently. Unfortunately that doesn't look like it will slow down any time soon, but Friday night meant a few hours off, and I did manage to relax and catch up on the stories of a few other Jacks.&lt;/p&gt;
&lt;p&gt;Before another viewing of &lt;em&gt;The Shining&lt;/em&gt;, I had the fun of watching &lt;em&gt;Lost&lt;/em&gt; Series 5 come to an end in dramatic form; admittedly not as dramatic as Jack Torrance arriving on the island and chasing everyone with an axe, but still pretty dramatic! I am very much looking forward to everything (hopefully) being wrapped up in Series 6; only another nine or so months to wait for the final series to kick off!&lt;/p&gt;
&lt;p&gt;At least with that over and &lt;em&gt;24&lt;/em&gt; coming to an end my iTunes bill will be much lower each week now. And with many less Jack stories to catch up on, my Friday nights off could become even more interesting :-)&lt;/p&gt;</description>
  <pubDate>Sat, 16 May 2009 15:24:44 GMT</pubDate>
  <category>Lost</category>
  <category>Jack</category>
  <category>Film</category>
  <category>TV</category>
  <guid isPermaLink="true">http://www.theogray.com/blog/2009/05/all-work-no-play-makes-jack-dull-boy</guid>
  <comments>http://www.theogray.com/blog/2009/05/all-work-no-play-makes-jack-dull-boy#readercomments</comments>
</item>
<item>
  <title>Using Reserved Words as Identifiers in VB.Net</title>
  <link>http://www.theogray.com/blog/2009/03/using-reserved-words-as-identifiers-in-vbnet</link>
  <description>&lt;p&gt;Up until now, if I wanted to use a reserved keyword as a variable, function or property name (such as &lt;tt style="color:#00d;"&gt;Public Property &lt;tt class="squiggly"&gt;ReadOnly&lt;/tt&gt;() As Boolean&lt;/tt&gt;), the compiler would complain.&lt;/p&gt;
&lt;p&gt;Luckily I happened across a very simple answer yesterday; VB.Net works in a similar way to SQL - to use a reserved word as an identifier, just put square brackets around it!&lt;/p&gt;
&lt;p&gt;i.e. &lt;tt style="color:#00d;"&gt;Public Property&lt;/tt&gt; &lt;tt&gt;[ReadOnly]&lt;/tt&gt;&lt;tt style="color:#00d;"&gt;() As Boolean&lt;/tt&gt;&lt;/p&gt;
&lt;p style="color:#999;"&gt;File under: &lt;em&gt;things I can't believe I didn't know!&lt;/em&gt;&lt;/p&gt;</description>
  <pubDate>Fri, 20 Mar 2009 08:20:16 GMT</pubDate>
  <category>VB</category>
  <category>Net</category>
  <category>Microsoft</category>
  <guid isPermaLink="true">http://www.theogray.com/blog/2009/03/using-reserved-words-as-identifiers-in-vbnet</guid>
  <comments>http://www.theogray.com/blog/2009/03/using-reserved-words-as-identifiers-in-vbnet#readercomments</comments>
</item>
<item>
  <title>Passing an Empty Array in VB.Net</title>
  <link>http://www.theogray.com/blog/2009/03/passing-an-empty-array-in-vbnet</link>
  <description>&lt;p&gt;When needing to pass arrays around between methods, I had always initialised them as &lt;tt&gt;Nothing&lt;/tt&gt; so that I knew when they were completely empty. i.e.&lt;/p&gt;
&lt;pre class="brush:vb;light:true;"&gt;Dim arrayVar() As String = Nothing&lt;/pre&gt;
&lt;p&gt;This is fine, but does then mean doing an extra check before working with the array. i.e.&lt;/p&gt;
&lt;pre class="brush:vb;light:true;"&gt;
If arrayVar IsNot Nothing Then
    For i As Integer = 0 To arrayVar.GetUpperBound(0)
        'do other work with the array, etc
    Next
End If&lt;/pre&gt;
&lt;p&gt;The tip, is to initialise the array as size &lt;tt&gt;-1&lt;/tt&gt; instead of &lt;tt&gt;Nothing&lt;/tt&gt;, i.e.&lt;/p&gt;
&lt;pre class="brush:vb;light:true;"&gt;Dim arrayVar(-1) As String&lt;/pre&gt;
&lt;p&gt;This means that you then don't need the extra &lt;tt&gt;IsNot Nothing&lt;/tt&gt; check, saving two lines of code every time the array is used, and allowing you to have coffee a few seconds earlier than you otherwise would!&lt;/p&gt;</description>
  <pubDate>Wed, 04 Mar 2009 08:19:06 GMT</pubDate>
  <category>VB</category>
  <category>Net</category>
  <category>Microsoft</category>
  <guid isPermaLink="true">http://www.theogray.com/blog/2009/03/passing-an-empty-array-in-vbnet</guid>
  <comments>http://www.theogray.com/blog/2009/03/passing-an-empty-array-in-vbnet#readercomments</comments>
</item>
<item>
  <title>Do I Need Planning Permission</title>
  <link>http://www.theogray.com/blog/2009/02/do-i-need-planning-permission</link>
  <description>&lt;p&gt;Good evening all! It seems I haven't actually &lt;em&gt;written&lt;/em&gt; much of late so here's a little tidbit of the stuff that has been keeping me busy for the past few months.&lt;/p&gt;
&lt;p&gt;&lt;img class="inline_right" align="right" height="215" alt="Do I Need Planning Permission" src="http://www.theogray.com/blog/images/orchard-planning.gif" width="300"&gt;First of all there was the quick revamp of &lt;em&gt;Blackstar Search&lt;/em&gt;, but mainly I have been putting together a new planning website called simply &lt;a href="http://www.doineedplanningpermission.co.uk/" target="_blank"&gt;Do I Need Planning Permission?&lt;/a&gt; for &lt;em&gt;Orchard Planning Solutions&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The idea of &lt;em&gt;Do I Need Planning Permission?&lt;/em&gt; is to provide a comprehensive set of information about when you do and do not need planning permission and whether building regulations apply to your particular project on your home. In addition there is an interactve &lt;a href="http://www.doineedplanningpermission.co.uk/forums/" target="_blank"&gt;forum&lt;/a&gt; and &lt;a href="http://www.doineedplanningpermission.co.uk/blog/" target="_blank"&gt;blog&lt;/a&gt; to keep people joining in, plus a feature for calculating the expected cost of an extension based on its size, and another for calculating the number of roles of &lt;a href="http://www.doineedplanningpermission.co.uk/planning-information/wallpapering.aspx" target="_blank"&gt;wallpaper&lt;/a&gt; you need to paper a room.&lt;/p&gt;
&lt;p&gt;As I've been writing software to help large companies and local authorities manage the processes invoved with the &lt;a href="http://www.aisolutions.co.uk/solutions/cdm-management/regulations.asp" target="_blank"&gt;CDM regulations&lt;/a&gt; for larger projects for nearly 14 years now, it's been interesting to pick up the details of what is required for smaller home based projects too.&lt;/p&gt;
&lt;p&gt;This website has involved some fun javascript for the calculators, but it has also given me the excuse to finally build the online Forum software that I've been meaning to do for a couple of years. This has now been intergrated into both the &lt;em&gt;Do I Need Planning Permission?&lt;/em&gt; and &lt;a href="http://www.eatonbray.com/"&gt;Eaton Bray&lt;/a&gt; websites. On the blog side it has also forced me to convert the blog backend to ASP.Net with SQL stored procedures rather than the bulky ASP/ADO code that it was originally based on; at one point with a slowish internet connection the old code was taking minutes to publish a single post and as soon as the switch was made, that became no more than one second.... I knew there would be a big performance boost, but that was spectacular!&lt;/p&gt;</description>
  <pubDate>Thu, 26 Feb 2009 22:56:59 GMT</pubDate>
  <category>Planning</category>
  <category>Websites</category>
  <guid isPermaLink="true">http://www.theogray.com/blog/2009/02/do-i-need-planning-permission</guid>
  <comments>http://www.theogray.com/blog/2009/02/do-i-need-planning-permission#readercomments</comments>
</item>
</channel>
</rss>
