winforms 比较DataGridView中所选复选框的单元格值

flvtvl50  于 2022-12-19  发布在  其他
关注(0)|答案(3)|浏览(134)

我有一个DataGridView和复选框列附加到它。我想实现这样的东西,当几个复选框被选中,它会比较列的单元格值命名为Description之间的那些选定的行。如果值不相同,将显示一个消息框,否则值将被解析到一个文本框。

如上例所示,当这些行被选中时,应该会显示一个消息框。
这就是我目前所做的,我不知道如何继续下去。

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
                    }
                }
            }
        }

谢谢你的帮助!

wpx232ag

wpx232ag1#

从您所编写的内容来看,我认为您的代码应该类似沿着以下内容:

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"
        }
    }

注意我从你的代码中删除了if (e.RowIndex >= 0 && e.ColumnIndex == 0),它看起来是多余的(但也许我遗漏了什么)。同样在ckboxselected = !Convert.ToBoolean(r.Cells[0].Value);中,“not”操作符看起来不正确(自己决定你的原始版本是否正确)。
当需求变得稍微复杂一些时,我建议分几步来处理:首先,用你感兴趣的行的内容填充一些集合,如列表、散列集或字典。2然后,在第二步中,评估内容以根据它做出决策。3在本例中,这也可以完成。

fzsnzjdm

fzsnzjdm2#

另一种方法是使用类加载DataGridView,这意味着在执行Assert时,在本例中,将调用提交DataGridViewCheckBoxColumn的更改。

示例模型/类,其中INotifyPropertyChanged通知客户端属性值已更改。

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));
    }
}

表单代码

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
            }
        }
    }
}
cu6pst1q

cu6pst1q3#

当您用鼠标单击单元格边界内的任意位置(包括DataGridViewCheckBoxCell的CheckBox区域)时,将引发CellClick事件。此外,当您在内容单元格具有焦点的情况下按Space键时,也将引发CellClick事件。另一方面,当鼠标或按键点击内容区域(即CheckBox)并且单元格的Value即将更改时,将引发CellContentClick事件。
根据我对您问题的理解,您需要实现后者,以便在您得到选中行的不同描述(第2列)时采取行动。

private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
    if (e.RowIndex >= 0 && e.ColumnIndex == 0)
    {
        // To get the new value...
        dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);

        var row = dataGridView1.Rows[e.RowIndex];
        var any = dataGridView1.Rows.OfType<DataGridViewRow>().Where(
            r => r.Index != row.Index && (bool)r.Cells[0].FormattedValue).Any(
            r => r.Cells[2].Value?.ToString().ToLower() != row.Cells[2].Value?.ToString().ToLower());

        if (any)
        {
            // Uncomment if you need to cancel the check...
            //row.Cells[0].Value = false;
            //dataGridView1.EndEdit();
            MessageBox.Show("Not same descriptions...");
        }
        else
        {
            // ...
        }
    }
}

如果您需要跳过null说明。

private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
    if (e.RowIndex >= 0 && e.ColumnIndex == 0)
    {
        dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);

        var row = dataGridView1.Rows[e.RowIndex];

        if (row.Cells[2].Value == null) return;

        var any = dataGridView1.Rows.OfType<DataGridViewRow>().Where(
            r => r.Index != row.Index && (bool)r.Cells[0].FormattedValue && r.Cells[2].Value != null).Any(
            r => r.Cells[2].Value.ToString().ToLower() != row.Cells[2].Value.ToString().ToLower());

        if (any)
        {
            // Uncomment if you need to uncheck...
            //row.Cells[0].Value = false;
            //dataGridView1.EndEdit();
            MessageBox.Show("Not same descriptions...");
        }
        else
        {
            // ...
        }
    }
}

Trim .ToLower()调用区分大小写的比较。

相关问题