I'm currently using DataGridView with three cells, and the first cell is
DataGridViewComboBoxColumn object, and I want to ensure whenever I select any new item in DataGridViewComboBoxColumn object other cells of dataGridview get empty. It doesn't matter if I reselect the same item again.
Could anyone please tell me how should I ensure that I've selected new item in DataGridViewComboBoxColumn object? Which property or method should I use for this approach?
You can declare a global List<int> gridComboSelections and when you bind your DataSource to your grid, you can fill this list with the SelectedValues of the comboboxes. When any of the combobox' value is changed, find the position of the combobox and check if it is same with gridComboSelections[i]. If it is same end operation, if not do what you want with it. If the value is changed, remember to change the corresponding value on your List.
You can refer following code which does same thing.
private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
ComboBox combo = e.Control as ComboBox;
if (combo != null)
{
combo.SelectionChangeCommitted += new EventHandler(combo_SelectionChangeCommitted);
}
}
void combo_SelectionChangeCommitted(object sender, EventArgs e)
{
DataGridViewComboBoxEditingControl combo = sender as DataGridViewComboBoxEditingControl;
if (combo != null)
{
for (int columnIndex = 0; columnIndex < dataGridView1.ColumnCount; columnIndex++)
{
if (columnIndex != combo.EditingControlDataGridView.CurrentCell.ColumnIndex)
{
dataGridView1[columnIndex, combo.EditingControlRowIndex].Value = null;
}
}
}
}
Related
I have a data grid view which is used to bind values.
I have a ComboBox inside this DatagridView; I want to implement an auto complete property in this ComboBox. It should not only search for the first letter but the whole item...
This can be done by
Grabbing the ComboBox
Manipulating its Items
Let's assume you have only one ComboBoxColumn; then you can grab an instance of the current one like this:
ComboBox editCombo = null; // class level variable
private void dataGridView1_EditingControlShowing(object sender,
DataGridViewEditingControlShowingEventArgs e)
{
editCombo = e.Control as ComboBox;
if (editCombo != null)
{
// here we can set its style..
editCombo.DropDownStyle = ComboBoxStyle.DropDown;
editCombo.AutoCompleteMode = AutoCompleteMode.Suggest;
// sigh..:
editCombo.TextChanged -= editCombo_TextChanged;
editCombo.TextChanged += editCombo_TextChanged;
}
}
Let's assume you have the valid list of values in a List<string>
List<string>() allChoices = new List<string>();
Then we can adapt the Items to be shown in the TextChanged event:
void editCombo_TextChanged(object sender, EventArgs e)
{
List<String> items = allChoices.Select(x=>x)
.Where(x=>x.Contains(editCombo.Text)).ToList();
if (items.Count > 0)
{
editCombo.Items.Clear();
editCombo.Items.AddRange(items.ToArray());
}
editCombo.Select(editCombo.Text.Length, 0); //clear the selection
}
Note that this x=>x.Contains(editCombo.Text) searches for items that contain the full text entered. I hope that is what you mean; searching for items that are identical to the entered text makes no sense, as then you do not need to AutoComplete them anyway..
In my application I have 2 ComboBox. When I select a ComboBoxItem in the first ComboBox the second one generates the relative ComboBoxItem. But if I create a SelectionChanged event on the second ComboBox I get this error. Why? Thanks!
private void scarpeBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ComboBox combo = (ComboBox)sender;
ComboBoxItem item = (ComboBoxItem)combo.SelectedItem;
for (int i = 0; i < 16; i++)
if (combo.Items[i] == item) id = i;
}
Your SelectedItem is of value String, it's not a control like you thought it would be. You're trying to convert your String to a ComboboxItem, which throws your exception.
In your example, I would use the SelectedIndex property:
private void scarpeBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ComboBox combo = (ComboBox)sender;
id = combo.SelectedIndex;
}
Your loop seems to look for the position of your SelectedItem, so replace your code with above, and it will return the position of the item in the ComboBox.
I have implemented a DataGridViewComboBox that allows editing using the code from this thread.
My problem right now is that when I focus the cell, the value is cleared. Based on the posts I've read, the item must be added to the combobox first. So here's what I have tried. Can you possibly tell me what's going wrong?
private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
if (e.Control.GetType() == typeof(DataGridViewComboBoxEditingControl))
{
DataGridViewRow row = dataGridView1.CurrentRow;
DataGridViewCell cell = dataGridView1.CurrentCell;
if (cell == row.Cells[colComboBox.Name])
{
DataGridViewComboBoxEditingControl control = e.Control as DataGridViewComboBoxEditingControl;
control.DropDownStyle = ComboBoxStyle.DropDown;
//For testing purposes
colComboBox.Items.Add("Test");//I'm adding the item to the combobox control
row.Cells[colComboBox.Name].Value = "Test";//Then set the value of the cell based on the item I added
}
}
}
private void dataGridView1_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
{
if (e.ColumnIndex == colComboBox.Index)
{
colComboBox.Items.Clear();
object eFV = e.FormattedValue;
if (!colComboBox.Items.Contains(eFV))
{
colComboBox.Items.Add(eFV);
dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = eFV;
}
}
}
In the example you linked, the Validating event used is the editing combo box one and not the DataGridView's CellValidating one.
By the way, using the EditingControlShowing event to access the editing control is generally a bad idea. I would suggest you to use a cell template by adding this code before populating your datagridview :
DataGridViewComboBoxCell templateCell = new DataGridViewComboBoxCell();
templateCell.Items.Add("Test");
templateCell.Items.Add("Test2");
colComboBox.CellTemplate = templateCell;
I'm not entirely sure why the DataGridViewComboBox behaves this way. But experimenting on to the ComboBox control with default properties, it does not clear the value when focused and behaves just like a TextBox control. The solution is just to actually set the Text property of the control to a e.g. global variable of some sort that can be accessed by other events bound to the control. As for now this is the behaviour that I'm trying to achieve.
DataGridViewComboBoxEditingControl control = e.Control as DataGridViewComboBoxEditingControl;
control.DropDownStyle = ComboBoxStyle.DropDown;
control.Text = SomeGlobalVariable;
I have a DataGridView with a DataGridViewComboBoxColumn which is bound to a List<IBrand>. In this combo box column, I allow the user to either select an existing value or type in a new one. When a user selects an existing value, IsCurrentRowDirty() correctly returns true. When the user types in a value, the IsCurrentRowDirty() always returns false when it obviously should return true.
I've tried calling DataGridView.CommitEdit() in the CurrentCellDirtyStateChanged event but that does not work
How do I get a user entered value in a DataGridViewComboBoxColumn to set the row to dirty?
Relevant code follows.
Thanks,
Kyle
public void BindBrands()
{
DataGridViewComboBoxColumn comboBox = (DataGridViewComboBoxColumn)dgvReference.Columns[(int)ReferenceColumnsIndex.Brand];
comboBox.DisplayMember = "Name";
comboBox.ValueMember = "Self"; //"Self" returns "this"
comboBox.DataSource = brands;
}
//This enables the DataGridViewComboBoxColumn to be editable by the user
private void dgvReference_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
DataGridViewComboBoxColumn column = GetColumn<DataGridViewComboBoxColumn>(dgvReference,
(int) ReferenceColumnsIndex.Brand);
if (column != null)
{
ComboBox comboBox = e.Control as ComboBox;
if (comboBox != null)
{
comboBox.DropDownStyle = ComboBoxStyle.DropDown;
}
}
}
private void dgvReference_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
{
switch (e.ColumnIndex)
{
case (int)ReferenceColumnsIndex.Brand:
DataGridViewComboBoxColumn comboBox = dgvReference.Columns[(int)ReferenceColumnsIndex.Brand] as DataGridViewComboBoxColumn;
if (e.ColumnIndex == comboBox.DisplayIndex)
{
IBrand brand = new Brand(e.FormattedValue.ToString());
if (!brands.Contains(brand))
{
//If the brand does not exist, add it to the datasource of the combobox
brands.Add(brand);
dgvReference.NotifyCurrentCellDirty(true); //<== THIS LINE FIXES THE ISSUE
}
//When setting the .Value to brand here, IsCurrentRowDirty() does not return true
dgvReference.Rows[e.RowIndex].Cells[(int)ReferenceColumnsIndex.Brand].Value = brand;
}
break;
}
}
Okay, I figured out how to force the IsCurrentRowDirty() method to return true. I needed to add the following line of code as illustrated in my example:
dgvReference.NotifyCurrentCellDirty(true);
Calling this on a newly entered brand will force the row to return true for IsCurrentRowDirty() method.
I have a Datagridview in Winform. One of the column is a Combobox. Is it possible to set the property such that user can enter apart from being able to select the entries from the dropdown list.
I was able to do it on a Combobox item with a following changes from the properties window:
AutoCompleteMode.SuggestAppend;
AutoCompleteSource.CustomSource;
DropDownStyle : Dropdown;
Thanks
Something like this may Help :-
private void DataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
if (DataGridView1.CurrentCell.ColumnIndex == yourComboBoxColum)
{
ComboBox combo = e.Control as ComboBox;
if (combo == null)
return;
combo.DropDownStyle = ComboBoxStyle.DropDown;
}
}