Here is my code that i used to create my own custom combobox column, my combobox is kind of special that shows treeview inside (here is code page http://www.brad-smith.info/blog/projects/dropdown-controls). the new combobox column works well except in one thing, if i select for example from the combobox and navigate to the cell beside (which is textbox cell) and then navigate to the same combobox column in the second row and select another item from the second combobox then all is fine, but if i navigate from one combobox to the one under it directly and select an item then the first combobox will select same value of the second combobox.
any help please?
public class DataGridViewTreeComboBoxColumn : DataGridViewComboBoxColumn
{
public DataGridViewTreeComboBoxColumn() : base()
{
base.CellTemplate = new TreeComboBoxCell();
}
public override DataGridViewCell CellTemplate
{
get
{
return base.CellTemplate;
}
set
{
if (value != null &&
!value.GetType().IsAssignableFrom(typeof(TreeComboBoxCell)))
{
throw new InvalidCastException("Must be a CalendarCell");
}
base.CellTemplate = value;
}
}
}
public class TreeComboBoxCell : DataGridViewComboBoxCell
{
public TreeComboBoxCell()
: base()
{
}
public override void InitializeEditingControl(int rowIndex, object
initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
{
base.InitializeEditingControl(rowIndex, initialFormattedValue,
dataGridViewCellStyle);
TreeComboBoxEditingControl ctl = DataGridView.EditingControl as TreeComboBoxEditingControl;
ctl.SetItems(Items);
if (Value != null)
ctl.SelectedNode = ctl.AllNodes.ToList().First(x => x.Tag != null && x.Tag.Equals(Value));
ctl.SelectedNodeChanged += Ctl_SelectedNodeChanged;
}
public override object Clone()
{
TreeComboBoxCell dataGridViewCell = base.Clone() as TreeComboBoxCell;
if (dataGridViewCell != null)
{
}
return dataGridViewCell;
}
private void Ctl_SelectedNodeChanged(object sender, EventArgs e)
{
if (((TreeComboBoxEditingControl)sender).SelectedNode != null)
Value = ((TreeComboBoxEditingControl)sender).SelectedNode.Tag;
}
public override Type EditType
{
get
{
// Return the type of the editing control that CalendarCell uses.
return typeof(TreeComboBoxEditingControl);
}
}
public override Type ValueType
{
get
{
// Return the type of the value that CalendarCell contains.
return typeof(Object);
}
}
public override object DefaultNewRowValue
{
get
{
// Use the current date and time as the default value.
return 0;
}
}
}
public class TreeComboBoxEditingControl : ComboTreeBox, IDataGridViewEditingControl
{
DataGridView dataGridView;
private bool valueChanged = false;
int rowIndex;
public TreeComboBoxEditingControl()
{
this.TabStop = false;
}
public void SetItems(DataGridViewComboBoxCell.ObjectCollection items)
{
if (Nodes != null && Nodes.Count > 0)
return;
Action<ComboTreeNodeCollection> addNodesHelper = nodes => {
foreach (IGrouping<object, TreeComboBoxItem> group in items.Cast<TreeComboBoxItem>().GroupBy(x => x.Group).ToList())
{
ComboTreeNode parent = nodes.Add(group.Key.ToString());
foreach (TreeComboBoxItem item in group)
{
parent.Nodes.Add(item.Display).Tag = item.Value;
}
}
};
Action<ComboTreeBox> addNodes = ctb => {
addNodesHelper(ctb.Nodes);
ctb.Sort();
};
addNodes(this);
}
// Implements the IDataGridViewEditingControl.EditingControlFormattedValue
// property.
public object EditingControlFormattedValue
{
get
{
return GetEditingControlFormattedValue(DataGridViewDataErrorContexts.Formatting);
}
set
{
}
}
// Implements the
// IDataGridViewEditingControl.GetEditingControlFormattedValue method.
public object GetEditingControlFormattedValue(
DataGridViewDataErrorContexts context)
{
if (this.SelectedNode == null)
return null;
return this.SelectedNode.Tag;
}
// Implements the
// IDataGridViewEditingControl.ApplyCellStyleToEditingControl method.
public void ApplyCellStyleToEditingControl(
DataGridViewCellStyle dataGridViewCellStyle)
{
}
// 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)
{
// Let the DateTimePicker handle the keys listed.
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;
}
}
protected override void OnSelectedNodeChanged(EventArgs e)
{
valueChanged = true;
this.EditingControlDataGridView.NotifyCurrentCellDirty(true);
base.OnSelectedNodeChanged(e);
}
}