I have a DataGridView and Checkbox column attached to it. I would like to achieve something like this, when a few checkboxes are selected, it will compare the cells value of column named Description between those selected row. If the values are not same, a message box will be show up, else the value will be parse into a textbox.
As in example above, a messagebox should be show up when those rows are selected.
This is what i have done so far and i don't know how to continue from here.
private void datagridview1_CellClick(object sender, DataGridViewCellEventArgs e)
{
foreach (DataGridViewRow r in datagridview1.Rows)
{
bool ckboxselected = !Convert.ToBoolean(r.Cells[0].Value);
if (e.RowIndex >= 0 && e.ColumnIndex == 0)
{
if (ckboxselected)
{
//compare
}
else
{
//another action
}
}
}
}
I appreciate you help!
CodePudding user response:
From what you write, I think your code should look like something along the lines of this:
private void datagridview1_CellClick(object sender, DataGridViewCellEventArgs e)
{
string description =null;
bool differentDescriptionsChecked=false;
foreach (DataGridViewRow r in datagridview1.Rows)
{
bool ckboxselected = Convert.ToBoolean(r.Cells[0].Value);
if (ckboxselected)
{
string description2 = Convert.ToString(r.Cells[2].Value);
if(description==null)
{
description=description2;
}
else if(description!=description2)
{
differentDescriptionsChecked=true;
break;
}
}
}
if(description==null)
{
// show message "no row checked"
}
else if(differentDescriptionsChecked)
{
// show message "different descriptions checked"
}
else
{
// do something with "description"
}
}
Note I removed the if (e.RowIndex >= 0 && e.ColumnIndex == 0)
from your code, it looked superfluous for me (but maybe I am missing something). Also in ckboxselected = !Convert.ToBoolean(r.Cells[0].Value);
the "not" operator did not look right (decide by yourself if your original version was correct).
When the requirements become slightly more complicated, I would recommend to approach this in more than step: first, fill some collection like a list, hashset or dictionary with the content from the rows which you are interested in. Then, in a second step evaluate the content to make decisions from it. That could have been done here in this case, too.
CodePudding user response:
Another approach is to load the DataGridView using a class which means when performing assertions there is, in this case a call to commit changes of the DataGridViewCheckBoxColumn.
Sample model/class, where INotifyPropertyChanged notifies clients that a property value has changed.
public class Item : INotifyPropertyChanged
{
private bool _selected;
private string _description;
public bool Selected
{
get => _selected;
set
{
_selected = value;
OnPropertyChanged();
}
}
public int Id { get; set; }
public string Description
{
get => _description;
set
{
_description = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Form code
public partial class Form1 : Form
{
private readonly BindingSource _bindingSource = new BindingSource();
private BindingList<Item> _bindingList;
public Form1()
{
InitializeComponent();
Shown = OnShown;
}
private void OnShown(object sender, EventArgs e)
{
_bindingList = new BindingList<Item>(new List<Item>()
{
new Item() {Selected = false,Id = 1,Description = "A"},
new Item() {Selected = false,Id = 2,Description = "B"},
new Item() {Selected = false,Id = 3,Description = "B"},
new Item() {Selected = false,Id = 4,Description = "A"},
});
_bindingSource.DataSource = _bindingList;
dataGridView1.DataSource = _bindingSource;
dataGridView1.Columns["Id"]!.ReadOnly = true;
dataGridView1.CellContentClick = DataGridView1OnCellContentClick;
}
private void DataGridView1OnCellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex < 0 || e.ColumnIndex != 0) return;
dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
for (int index = 0; index < _bindingList.Count; index )
{
if (_bindingList[index].Selected)
{
// TODO
}
else
{
// TODO
}
}
}
}