I want to display a message when items in DataGridViewComboBox has been changed. I am able to perform it partially by taking help of datagridview CellbeginEdit event and CellEndEdit event but that is not up to mark. I want it as it happen in combobox selection change event.
I had google it for solving but not get appropriate help.
Any help will be appriciated.
use EditingControlShowing event for it
private void grvList_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
if (grvList.Columns[grvList.CurrentCell.ColumnIndex].Name.Equals("routing_ID"))
{
ComboBox cmbprocess = e.Control as ComboBox;
cmbprocess.SelectedIndexChanged += new EventHandler(grvcmbProcess_SelectedIndexChanged);
}
}
private void grvcmbProcess_SelectedIndexChanged(object sender, EventArgs e)
{
ComboBox cmbprocess = (ComboBox)sender;
if (cmbprocess.SelectedValue != null)
{
/// Your Code goes here
}
}
this is only an example program to show how to do it
Related
I'd like to disable item in ComboBox that is in a DataGridview cell.
I already know how to disable(or seems disabled) items in a ComboBox, using the DrawItem event and SelectedIndexChanged event but there is no similar event in DataGridViewComboBoxCell or DataGridViewComboBoxColumn.
So my question is, how to disable any item in ComboBox that is in a DataGridView?
In ComboBox I can modify items display that need to be disabled like this:
But can't do the same functionality in DataGridView:
I think the simplest option for you would be to handle the EditControlShowing event, and then handle the ComboBoxes SelectedIndexChanged event and do what you already know how to do.
When you setup the DataGridview in code, you can do this:
dataGridView1.EditingControlShowing += dataGridView1_EditingControlShowing;
And then implement the handler like:
void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
ComboBox combo = e.Control as ComboBox;
if (combo != null)
{
// Both of these lines are essential, otherwise you will be handling the same event twice in some conditions
combo.SelectedIndexChanged -= combo_SelectedIndexChanged;
combo.SelectedIndexChanged += combo_SelectedIndexChanged;
}
}
Finally, the SelectedIndexChanged event is handled exactly the way you want to:
void combo_SelectedIndexChanged(object sender, EventArgs e)
{
ComboBox thisCombo = sender as ComboBox;
if (thisCombo != null)
{
Debug.Print(thisCombo.Text);
}
}
I'm pretty new to C# development, but here goes. I'm working on a plugin for Autodesk revit, which creates a windows form with a datagridview on it which gets populated with several checkbox columns when the form loads. What I would like to do is select multiple checkbox cells, and check one of the selected boxes in order to check all selected boxes.
I have tried using a SelectionChanged event handler to store the selected sells in another variable. Then I'm trying to use CellValueChanged in order to set all those cells to the new value
DataGridViewSelectedCellCollection selCells = null;
private void revDataGridView_SelectionChanged(object sender, EventArgs e)
{
selCells = revDataGridView.SelectedCells;
}
private void revDataGridView_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
foreach(DataGridViewCell cell in selCells)
{
cell.Value = revDataGridView[e.ColumnIndex, e.RowIndex].Value;
}
}
My problem is that as soon as I click on the one cell, it resets the DataGridView.SelectedCells to that one cell and I lose the previous selection. Any help would be greatly appreciated!
EDIT: I solved this by storing the selection in another variable (selCells) and using a combination of the CellMouseUp, CellMouseDown, and CellValueChanged event handlers:
private void revDataGridView_CellMouseUp(object sender, DataGridViewCellMouseEventArgs e)
{
if (selCells != null && selCells.Count>1)
{
revDataGridView.EndEdit();
selCells = revDataGridView.SelectedCells;
}
else if(selCells !=null && selCells.Count == 1)
{
selCells = revDataGridView.SelectedCells;
revDataGridView.EndEdit();
}
}
//when a value is changed, apply change to all selected cells
private void revDataGridView_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
foreach(DataGridViewCell cell in selCells)
{
if (cell.ReadOnly == false)
{
cell.Value = revDataGridView[e.ColumnIndex, e.RowIndex].Value;
cell.Selected = true;
}
}
}
//clear selection upon mouse button down
private void revDataGridView_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
{
revDataGridView.ClearSelection();
}
I want to create DataGridViewComboBoxColumn and attach to it's combo box Click event (i want to generate it's datasource on click only).
While I have no idea about why you need Click event of that ComboBox control,
you can access that combo box using EditingControlShowing event:
private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
//Check if the event is for your column, for example column 1
if (this.dataGridView1.CurrentCell.ColumnIndex == 1)
{
var comboBox = e.Control as DataGridViewComboBoxEditingControl;
comboBox.Click -= comboBox_Click;
comboBox.Click += comboBox_Click;
}
}
private void comboBox_Click(object sender, EventArgs e)
{
var comboBox = sender as DataGridViewComboBoxEditingControl;
//use comboBox here
}
But you should know, you can set the DataSource for you column in CellClick event of your datagridview too:
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
if(e.ColumnIndex==1 && e.RowIndex>-1)
{
//Check if the event is for your column, for example column 1
var column = (DataGridViewComboBoxColumn)this.dataGridView1.Columns[e.ColumnIndex];
//use column.DataSource
}
}
And another important thing you should know is if you set a datasource that not contains the value of one of cells of this column, you will receive errors while rendering the column.
I have a DataGridView with two columns (DataGridViewTextBoxColumn and DataGRidViewComboBoxColumn). If I click on a cell in the textbox column and scroll with the mousewheel, the grid scrolls. This is perfect.
If I click on a cell in the combobox column, the mousewheel will scroll the items in the combobox. I need to scroll the datagridview instead.
In my attempt to fix I can disable the scrolling in the combobox by handling the EditingControlShowing event :
private void SeismicDateGridView_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
if (e.Control is IDataGridViewEditingControl)
{
dgvCombo = (IDataGridViewEditingControl) e.Control;
((System.Windows.Forms.ComboBox)dgvCombo).MouseWheel -= new MouseEventHandler(DGVCombo_MouseWheel);
((System.Windows.Forms.ComboBox)dgvCombo).MouseWheel += new MouseEventHandler(DGVCombo_MouseWheel);
}
}
private void DGVCombo_MouseWheel(object sender, System.Windows.Forms.MouseEventArgs e)
{
HandledMouseEventArgs mwe = (HandledMouseEventArgs)e;
mwe.Handled = true;
}
Any ideas how to scroll the DataGridView when the DataGridViewComboBox column is active ?
Have you considered handling the ComboBox's DropDownClosed event and changing the focus to the parent?
void DateGridView_CellClick(object sender, DataGridViewCellEventArgs e)
{
System.Windows.Forms.ComboBox comboBox = dataGridView.EditingControl as System.Windows.Forms.ComboBox;
if (comboBox != null)
{
comboBox.DropDownClosed += comboBox_DropDownClosed;
}
}
void comboBox_DropDownClosed(object sender, EventArgs e)
{
(sender as System.Windows.Forms.ComboBox).DropDownClosed -= comboBox_DropDownClosed;
(sender as System.Windows.Forms.ComboBox).Parent.Focus();
}
If you want to scroll the DataGridView before you select a cell but while the ComboBox is still dropped down, that would be a different situation but judging by what you said here:
If I click on a cell in the combobox column, the mousewheel will
scroll the items in the combobox.
I am assuming that you simply want to change the focus once a selection has been made.
You could redirect the input using P/Invoke like here. Or you could subclass the DataGridView to add a Scroll Method to it which calls the base class's OnMouseWheel method, which you could then call from DGVCombo_MouseWheel. Example here.
I think the second option is probably the most elegant, no reason to use PInvoke.
Here it is done with inline functions. And handled case, when combo box is dropped down:
dgv.EditingControlShowing += (s, e) =>
{
DataGridViewComboBoxEditingControl editingControl = e.Control as DataGridViewComboBoxEditingControl;
if (editingControl != null)
editingControl.MouseWheel += (s2, e2) =>
{
if (!editingControl.DroppedDown)
{
((HandledMouseEventArgs)e2).Handled = true;
dgv.Focus();
}
};
};
I want to handle the event when a value is changed in a ComboBox in a DataGridView cell.
There's the CellValueChanged event, but that one doesn't fire until I click somewhere else inside the DataGridView.
A simple ComboBox SelectedValueChanged does fire immediately after a new value is selected.
How can I add a listener to the combobox that's inside the cell?
The above answer led me down the primrose path for awhile. It does not work as it causes multiple events to fire and just keeps adding events. The problem is that the above catches the DataGridViewEditingControlShowingEvent and it does not catch the value changed. So it will fire every time you focus then leave the combobox whether it has changed or not.
The last answer about CurrentCellDirtyStateChanged is the right way to go. I hope this helps someone avoid going down a rabbit hole.
Here is some code:
// Add the events to listen for
dataGridView1.CellValueChanged += new DataGridViewCellEventHandler(dataGridView1_CellValueChanged);
dataGridView1.CurrentCellDirtyStateChanged += new EventHandler(dataGridView1_CurrentCellDirtyStateChanged);
// This event handler manually raises the CellValueChanged event
// by calling the CommitEdit method.
void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
if (dataGridView1.IsCurrentCellDirty)
{
// This fires the cell value changed handler below
dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
}
private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
// My combobox column is the second one so I hard coded a 1, flavor to taste
DataGridViewComboBoxCell cb = (DataGridViewComboBoxCell)dataGridView1.Rows[e.RowIndex].Cells[1];
if (cb.Value != null)
{
// do stuff
dataGridView1.Invalidate();
}
}
You can also handle the CurrentCellDirtyStateChanged event which gets called whenever a value is changed, even if it's not commited. To get the selected value in the list, you would do something like:
var newValue = dataGridView.CurrentCell.EditedFormattedValue;
This is the code, which will fire the event of the selection in the comboBox in the dataGridView:
public Form1()
{
InitializeComponent();
DataGridViewComboBoxColumn cmbcolumn = new DataGridViewComboBoxColumn();
cmbcolumn.Name = "cmbColumn";
cmbcolumn.HeaderText = "combobox column";
cmbcolumn.Items.AddRange(new string[] { "aa", "ac", "aacc" });
dataGridView1.Columns.Add(cmbcolumn);
dataGridView1.EditingControlShowing += new DataGridViewEditingControlShowingEventHandler(dataGridView1_EditingControlShowing);
}
private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
ComboBox combo = e.Control as ComboBox;
if (combo != null)
{
combo.SelectedIndexChanged -= new EventHandler(ComboBox_SelectedIndexChanged);
combo.SelectedIndexChanged += new EventHandler(ComboBox_SelectedIndexChanged);
}
}
private void ComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
ComboBox cb = (ComboBox)sender;
string item = cb.Text;
if (item != null)
MessageBox.Show(item);
}
I have implemented another solution, that seems more responsive (e.g.. quicker and less clicks) than Mitja Bonca's above. Although sometimes the combobox closes to quickly. This uses the CurrentCellDirtyStateChanged and CellMouseDown callback
private void myGrid_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
if (myGrid.CurrentCell is DataGridViewComboBoxCell)
{
myGrid.CommitEdit(DataGridViewDataErrorContexts.Commit);
myGrid.EndEdit();
}
}
private void myGrid_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
{
if (myGrid.Rows[e.RowIndex].Cells[e.ColumnIndex] is DataGridViewComboBoxCell)
{
myGrid.CurrentCell = myGrid.Rows[e.RowIndex].Cells[e.ColumnIndex];
myGrid.BeginEdit(true);
((ComboBox)myGrid.EditingControl).DroppedDown = true; // Tell combobox to expand
}
}
ComboBox cmbBox = (ComboBox)sender;
MessageBox.Show(cmbBox.SelectedValue.ToString());