Richard T. Schaefer
2009-12-02 09:23:51 UTC
The attached specialized combo boxes allows the use of the keyboard to find
a selected entry in the combo box by matching any part of the text entries.
(Not just the beginning characters)
However I can't seem to get it to work in a DataGridView column. Using the
MSDN example of How to Host Controls in Windows Forms DataGridView Cells.
I get:
System.NullReferenceException
at System.Windows.Forms.DataGridViewComboBoxCell.ComboBox_DropDown(Object
sender, EventArgs e)
at System.Windows.Forms.ComboBox.OnDropDown(EventArgs e)
at System.Windows.Forms.ComboBox.WmReflectCommand(Message& m)
at System.Windows.Forms.ComboBox.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd,
Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.SendMessage(HandleRef hWnd,
Int32 msg, IntPtr wParam, IntPtr lParam)
at System.Windows.Forms.Control.SendMessage(Int32 msg, IntPtr wparam,
IntPtr lparam)
at System.Windows.Forms.Control.ReflectMessageInternal(IntPtr hWnd,
Message& m)
at System.Windows.Forms.Control.WmCommand(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd,
Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.CallWindowProc(IntPtr wndProc,
IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at System.Windows.Forms.NativeWindow.DefWndProc(Message& m)
at System.Windows.Forms.Control.DefWndProc(Message& m)
at System.Windows.Forms.Control.WmMouseDown(Message& m, MouseButtons
button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ComboBox.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd,
Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.
UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32
dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.
RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32
reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at DORReport.Program.Main(String[] args) in
C:\Aviation\FLF\DorSoftware\DORReport\Program.cs:line 22
Do not know how to debug this.
The particular classes are as follow:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
// This class allows for searching for any string in the items, not just the
first character.
// Uses the Arrow keys to move between matches for the current string
// Displays the selected characters between "<" and ">"
namespace DORReport
{
public class DORComboBox : ComboBox, IDataGridViewEditingControl
{
public DORComboBox() : base() {
SearchString = "";
SearchIndex = 0;
FormattingEnabled = true;
HaveFocus = false;
}
protected override bool IsInputKey(Keys KeyData) {
bool Result = true;
if (KeyData == Keys.Tab) return(false);
if (SearchString.Length == 0) {
Result = base.IsInputKey(KeyData);
}
return(Result);
}
protected override void OnKeyDown(KeyEventArgs e) {
bool ForwardSearch = true;
String OldSearchString = SearchString;
switch (e.KeyCode) {
case Keys.Right:
case Keys.Down:
SearchIndex++;
break;
case Keys.Left:
case Keys.Up:
ForwardSearch = false;
break;
case Keys.Delete:
case Keys.Back:
if (SearchString.Length > 0) {
SearchString = SearchString.Substring(0, SearchString.Length
-1);
if (SearchString.Length == 0) {
SelectedIndex = 0;
}
}
SearchIndex = 0;
break;
case Keys.Escape:
SearchString = "";
SearchIndex = 0;
SelectedIndex = 0;
break;
case Keys.Space:
if (SearchString.Length != 0) {
SearchString += " ";
}
break;
default:
if (((e.KeyCode >= Keys.D0) && (e.KeyCode <= Keys.D9)) ||
((e.KeyCode >= Keys.A) && (e.KeyCode <= Keys.Z))) {
SearchString += e.KeyCode;
}
break;
}
if (SearchString.Length > 0) {
int i;
String s;
// Start Search from last selected item
for (i = (ForwardSearch ? SearchIndex : SearchIndex - 1);
ForwardSearch ? i < Items.Count : i >= 0;
i += (ForwardSearch ? 1 : -1)) {
s = Items[i] as String;
if ((s != null) && s.IndexOf(SearchString, StringComparison.
OrdinalIgnoreCase) >= 0) {
// The following pattern is to force OnFormat to be fired
SelectedIndex = -1;
SelectedIndex = i;
break;
}
}
if ((i == (ForwardSearch ? Items.Count : -1)) && SearchIndex > 0)
{
// Wrap the search
for (i = ForwardSearch ? 0 : Items.Count - 1;
ForwardSearch ? i < Items.Count: i >= 0;
i += (ForwardSearch ? 1 : -1)) {
s = Items[i] as String;
if ((s != null) && s.IndexOf(SearchString, StringComparison.
OrdinalIgnoreCase) >= 0) {
// The following pattern is to force OnFormat to be fired
SelectedIndex = -1;
SelectedIndex = i;
break;
}
}
}
if (i == (ForwardSearch ? Items.Count : -1)) {
// Since we did not find anything restore the SearchString
SearchString = OldSearchString;
}
}
SearchIndex = SelectedIndex;
if (SearchString.Length > 0) {
e.SuppressKeyPress = true;
}
}
protected override void OnFormat(ListControlConvertEventArgs e) {
if (HaveFocus && (SearchString.Length > 0)) {
String Result = e.Value.ToString();
int i = Result.IndexOf(SearchString, StringComparison.
OrdinalIgnoreCase);
if (i >= 0) {
int j = SearchString.Length;
e.Value = Result.Substring(0, i) + "<" + Result.Substring(i, j)
+ ">" + Result.Substring(i+j);
}
}
}
protected override void OnGotFocus(EventArgs e) {
HaveFocus = true;
SearchString = "";
SearchIndex = 0;
}
protected override void OnLostFocus(EventArgs e) {
HaveFocus = false;
int i = SelectedIndex;
if (i >= 0) {
SelectedIndex = -1;
SelectedIndex = i;
}
}
private String SearchString;
private int SearchIndex;
private bool HaveFocus;
// The following are for IDataGridViewEditingControl
// Implements the IDataGridViewEditingControl.
EditingControlFormattedValue
// property.
public object EditingControlFormattedValue {
get { return this.Text; }
set {
if (value is String) {
this.Text = value as String;
}
}
}
// Implements the
// IDataGridViewEditingControl.GetEditingControlFormattedValue
method.
public object
GetEditingControlFormattedValue(DataGridViewDataErrorContexts context) {
return EditingControlFormattedValue;
}
// Implements the
// IDataGridViewEditingControl.ApplyCellStyleToEditingControl method.
public void ApplyCellStyleToEditingControl(DataGridViewCellStyle
dataGridViewCellStyle) {
this.Font = dataGridViewCellStyle.Font;
this.ForeColor = dataGridViewCellStyle.ForeColor;
this.BackColor = dataGridViewCellStyle.BackColor;
}
// Implements the IDataGridViewEditingControl.EditingControlRowIndex
// property.
public int EditingControlRowIndex {
get {return rowIndex;}
set {
rowIndex = value;
}
}
// Implements the IDataGridViewEditingControl.
EditingControlWantsInputKey
// method.
public bool EditingControlWantsInputKey(Keys key, bool
dataGridViewWantsInputKey) {
switch (key & Keys.KeyCode) {
case Keys.Left:
case Keys.Up:
case Keys.Down:
case Keys.Right:
case Keys.Home:
case Keys.End:
case Keys.PageDown:
case Keys.PageUp:
return true;
default:
return !dataGridViewWantsInputKey;
}
}
// Implements the IDataGridViewEditingControl.
PrepareEditingControlForEdit
// method.
public void PrepareEditingControlForEdit(bool selectAll) {
// No preparation needs to be done.
}
// Implements the IDataGridViewEditingControl
// .RepositionEditingControlOnValueChange property.
public bool RepositionEditingControlOnValueChange {
get {return false;}
}
// Implements the IDataGridViewEditingControl
// .EditingControlDataGridView property.
public DataGridView EditingControlDataGridView {
get { return dataGridView; }
set {
dataGridView = value;
}
}
// Implements the IDataGridViewEditingControl
// .EditingControlValueChanged property.
public bool EditingControlValueChanged {
get {return valueChanged; }
set {
valueChanged = value;
}
}
// Implements the IDataGridViewEditingControl
// .EditingPanelCursor property.
public Cursor EditingPanelCursor {
get {
return base.Cursor;
}
}
private DataGridView dataGridView;
private bool valueChanged = false;
private int rowIndex;
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace DORReport
{
public class DORDataGridViewComboBoxColumn : DataGridViewComboBoxColumn
{
public DORDataGridViewComboBoxColumn() : base() {
base.CellTemplate = new DorComboBoxCell();
}
public override DataGridViewCell CellTemplate
{
get { return base.CellTemplate; }
set {
if ((value != null) && (!value.GetType().
IsAssignableFrom(typeof(DorComboBoxCell)))) {
throw new InvalidCastException("Must be a DORComboBoxCell");
}
base.CellTemplate = value;
}
}
}
public class DorComboBoxCell : DataGridViewComboBoxCell
{
public DorComboBoxCell() : base() {
}
public override
void InitializeEditingControl(int rowIndex, object
initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle) {
base.InitializeEditingControl(rowIndex, initialFormattedValue,
dataGridViewCellStyle);
DORComboBox cb = DataGridView.EditingControl as DORComboBox;
cb.SelectedText = (String) this.Value;
}
public override Type EditType
{
get { return(typeof(DORComboBox));}
}
}
}
url:http://www.ureader.com/gp/1440-1.aspx
a selected entry in the combo box by matching any part of the text entries.
(Not just the beginning characters)
However I can't seem to get it to work in a DataGridView column. Using the
MSDN example of How to Host Controls in Windows Forms DataGridView Cells.
I get:
System.NullReferenceException
at System.Windows.Forms.DataGridViewComboBoxCell.ComboBox_DropDown(Object
sender, EventArgs e)
at System.Windows.Forms.ComboBox.OnDropDown(EventArgs e)
at System.Windows.Forms.ComboBox.WmReflectCommand(Message& m)
at System.Windows.Forms.ComboBox.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd,
Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.SendMessage(HandleRef hWnd,
Int32 msg, IntPtr wParam, IntPtr lParam)
at System.Windows.Forms.Control.SendMessage(Int32 msg, IntPtr wparam,
IntPtr lparam)
at System.Windows.Forms.Control.ReflectMessageInternal(IntPtr hWnd,
Message& m)
at System.Windows.Forms.Control.WmCommand(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd,
Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.CallWindowProc(IntPtr wndProc,
IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at System.Windows.Forms.NativeWindow.DefWndProc(Message& m)
at System.Windows.Forms.Control.DefWndProc(Message& m)
at System.Windows.Forms.Control.WmMouseDown(Message& m, MouseButtons
button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ComboBox.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd,
Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.
UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32
dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.
RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32
reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at DORReport.Program.Main(String[] args) in
C:\Aviation\FLF\DorSoftware\DORReport\Program.cs:line 22
Do not know how to debug this.
The particular classes are as follow:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
// This class allows for searching for any string in the items, not just the
first character.
// Uses the Arrow keys to move between matches for the current string
// Displays the selected characters between "<" and ">"
namespace DORReport
{
public class DORComboBox : ComboBox, IDataGridViewEditingControl
{
public DORComboBox() : base() {
SearchString = "";
SearchIndex = 0;
FormattingEnabled = true;
HaveFocus = false;
}
protected override bool IsInputKey(Keys KeyData) {
bool Result = true;
if (KeyData == Keys.Tab) return(false);
if (SearchString.Length == 0) {
Result = base.IsInputKey(KeyData);
}
return(Result);
}
protected override void OnKeyDown(KeyEventArgs e) {
bool ForwardSearch = true;
String OldSearchString = SearchString;
switch (e.KeyCode) {
case Keys.Right:
case Keys.Down:
SearchIndex++;
break;
case Keys.Left:
case Keys.Up:
ForwardSearch = false;
break;
case Keys.Delete:
case Keys.Back:
if (SearchString.Length > 0) {
SearchString = SearchString.Substring(0, SearchString.Length
-1);
if (SearchString.Length == 0) {
SelectedIndex = 0;
}
}
SearchIndex = 0;
break;
case Keys.Escape:
SearchString = "";
SearchIndex = 0;
SelectedIndex = 0;
break;
case Keys.Space:
if (SearchString.Length != 0) {
SearchString += " ";
}
break;
default:
if (((e.KeyCode >= Keys.D0) && (e.KeyCode <= Keys.D9)) ||
((e.KeyCode >= Keys.A) && (e.KeyCode <= Keys.Z))) {
SearchString += e.KeyCode;
}
break;
}
if (SearchString.Length > 0) {
int i;
String s;
// Start Search from last selected item
for (i = (ForwardSearch ? SearchIndex : SearchIndex - 1);
ForwardSearch ? i < Items.Count : i >= 0;
i += (ForwardSearch ? 1 : -1)) {
s = Items[i] as String;
if ((s != null) && s.IndexOf(SearchString, StringComparison.
OrdinalIgnoreCase) >= 0) {
// The following pattern is to force OnFormat to be fired
SelectedIndex = -1;
SelectedIndex = i;
break;
}
}
if ((i == (ForwardSearch ? Items.Count : -1)) && SearchIndex > 0)
{
// Wrap the search
for (i = ForwardSearch ? 0 : Items.Count - 1;
ForwardSearch ? i < Items.Count: i >= 0;
i += (ForwardSearch ? 1 : -1)) {
s = Items[i] as String;
if ((s != null) && s.IndexOf(SearchString, StringComparison.
OrdinalIgnoreCase) >= 0) {
// The following pattern is to force OnFormat to be fired
SelectedIndex = -1;
SelectedIndex = i;
break;
}
}
}
if (i == (ForwardSearch ? Items.Count : -1)) {
// Since we did not find anything restore the SearchString
SearchString = OldSearchString;
}
}
SearchIndex = SelectedIndex;
if (SearchString.Length > 0) {
e.SuppressKeyPress = true;
}
}
protected override void OnFormat(ListControlConvertEventArgs e) {
if (HaveFocus && (SearchString.Length > 0)) {
String Result = e.Value.ToString();
int i = Result.IndexOf(SearchString, StringComparison.
OrdinalIgnoreCase);
if (i >= 0) {
int j = SearchString.Length;
e.Value = Result.Substring(0, i) + "<" + Result.Substring(i, j)
+ ">" + Result.Substring(i+j);
}
}
}
protected override void OnGotFocus(EventArgs e) {
HaveFocus = true;
SearchString = "";
SearchIndex = 0;
}
protected override void OnLostFocus(EventArgs e) {
HaveFocus = false;
int i = SelectedIndex;
if (i >= 0) {
SelectedIndex = -1;
SelectedIndex = i;
}
}
private String SearchString;
private int SearchIndex;
private bool HaveFocus;
// The following are for IDataGridViewEditingControl
// Implements the IDataGridViewEditingControl.
EditingControlFormattedValue
// property.
public object EditingControlFormattedValue {
get { return this.Text; }
set {
if (value is String) {
this.Text = value as String;
}
}
}
// Implements the
// IDataGridViewEditingControl.GetEditingControlFormattedValue
method.
public object
GetEditingControlFormattedValue(DataGridViewDataErrorContexts context) {
return EditingControlFormattedValue;
}
// Implements the
// IDataGridViewEditingControl.ApplyCellStyleToEditingControl method.
public void ApplyCellStyleToEditingControl(DataGridViewCellStyle
dataGridViewCellStyle) {
this.Font = dataGridViewCellStyle.Font;
this.ForeColor = dataGridViewCellStyle.ForeColor;
this.BackColor = dataGridViewCellStyle.BackColor;
}
// Implements the IDataGridViewEditingControl.EditingControlRowIndex
// property.
public int EditingControlRowIndex {
get {return rowIndex;}
set {
rowIndex = value;
}
}
// Implements the IDataGridViewEditingControl.
EditingControlWantsInputKey
// method.
public bool EditingControlWantsInputKey(Keys key, bool
dataGridViewWantsInputKey) {
switch (key & Keys.KeyCode) {
case Keys.Left:
case Keys.Up:
case Keys.Down:
case Keys.Right:
case Keys.Home:
case Keys.End:
case Keys.PageDown:
case Keys.PageUp:
return true;
default:
return !dataGridViewWantsInputKey;
}
}
// Implements the IDataGridViewEditingControl.
PrepareEditingControlForEdit
// method.
public void PrepareEditingControlForEdit(bool selectAll) {
// No preparation needs to be done.
}
// Implements the IDataGridViewEditingControl
// .RepositionEditingControlOnValueChange property.
public bool RepositionEditingControlOnValueChange {
get {return false;}
}
// Implements the IDataGridViewEditingControl
// .EditingControlDataGridView property.
public DataGridView EditingControlDataGridView {
get { return dataGridView; }
set {
dataGridView = value;
}
}
// Implements the IDataGridViewEditingControl
// .EditingControlValueChanged property.
public bool EditingControlValueChanged {
get {return valueChanged; }
set {
valueChanged = value;
}
}
// Implements the IDataGridViewEditingControl
// .EditingPanelCursor property.
public Cursor EditingPanelCursor {
get {
return base.Cursor;
}
}
private DataGridView dataGridView;
private bool valueChanged = false;
private int rowIndex;
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace DORReport
{
public class DORDataGridViewComboBoxColumn : DataGridViewComboBoxColumn
{
public DORDataGridViewComboBoxColumn() : base() {
base.CellTemplate = new DorComboBoxCell();
}
public override DataGridViewCell CellTemplate
{
get { return base.CellTemplate; }
set {
if ((value != null) && (!value.GetType().
IsAssignableFrom(typeof(DorComboBoxCell)))) {
throw new InvalidCastException("Must be a DORComboBoxCell");
}
base.CellTemplate = value;
}
}
}
public class DorComboBoxCell : DataGridViewComboBoxCell
{
public DorComboBoxCell() : base() {
}
public override
void InitializeEditingControl(int rowIndex, object
initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle) {
base.InitializeEditingControl(rowIndex, initialFormattedValue,
dataGridViewCellStyle);
DORComboBox cb = DataGridView.EditingControl as DORComboBox;
cb.SelectedText = (String) this.Value;
}
public override Type EditType
{
get { return(typeof(DORComboBox));}
}
}
}
url:http://www.ureader.com/gp/1440-1.aspx