Wednesday, May 03, 2006

The dreaded SHIFT+SPACE of Datagrids and how to fix it

Anyone familiar with the .NET Datagrid class has probably run across the so-called "feature" where using SHIFT+SPACE selects the entire row. This is especially annoying when typing something like "How do I fix this?" in a text column. The row gets selected and if you manage to keep tying past the "I", you erase everything prior and all you get is "fix this?" Which is something I've been hearing for months from my users.

Today I decided to search once again on the web for a solution and found one on a fellow programmer's blog. He calls it a "dodge", but I think it's an excellent solution.

The Solution

Basically, you're overriding the Datagrid class, and then overriding the ProcessCmdKey method such that you can filter out the SHIFT+SPACE combo. However, I suppose it would be better to actually be able to alter the method that creates this behavior in the first place! Since we can't do that, this is the next best thing.

Just create the class below in your project, and then replace Datagrid objects with DataGridFix objects. You shouldn't need to make any other changes to your project.


using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;


namespace MyProject
{
///
/// This class is derived from the DataGrid class so that I can disable the "feature" that selects
/// a row by using SHIFT+SPACE
///

public class DataGridFix:System.Windows.Forms.DataGrid
{
// a couple of setup bits
const int WM_KEYDOWN = 256;
[DllImport("user32.dll")]
public static extern int GetKeyboardState(ref Byte pbKeyState);
[DllImport("user32.dll")]
public static extern int SetKeyboardState(ref Byte bpKeyState);

// over-ride the 'ProcessCmdKey' method
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
Keys keyCode = ((Keys)msg.WParam.ToInt32()) & Keys.KeyCode;
if (msg.Msg == WM_KEYDOWN && keyCode == Keys.Space)
{
if (Control.ModifierKeys == Keys.Shift)
{
// if the keystate is SHIFT+SPACE, make it just a SPACE
byte[] keystates = new byte[255];
GetKeyboardState(ref keystates[0]);
keystates[16] = 0;
SetKeyboardState(ref keystates[0]);
SendKeys.Send(" ");
return true;
}
}
return base.ProcessCmdKey(ref msg, keyData); // let the base method handle everything else as-is
}
}
}


I also need to give credit for the CSS code which make the code above easy to read.

CSS article

1 comment:

cara said...

um yeah. so i thought for a second i was looking over henri's shoulder at his laptop when i logged onto your blog. how can you guys stand looking at all that gobbledygook. it makes my head hurt thinking that all those slashes and nonsense words like else if or whatever actually mean things and make things run. i just like the pretty colors. ok, diatribe over.

it was such a surprise to find a comment from you, dan...it's been a long time! probably at least 10 years or so. eek. hope things are well with and i look forward to reading more about your thoughts and life out on the east coast. of course i shall be skipping over the geek entries, i hope that doesn't hurt your feelings :)