Visual Studio 访问dataGridView值

0s7z1bwu  于 2023-03-31  发布在  其他
关注(0)|答案(2)|浏览(159)

我在一个窗口窗体上工作。我从数据库中得到这样的表:

M_TABLE

a  |b  |c
---------
1  |xy |z
---------
2  |ab |c

我有一个dataGridView 1,我将上面的表作为数据源传递。这很好,所以我不显示代码细节。但简化后看起来像这样:

DataSet dsData = new DataSet();
dataGridView1.DataSource = dsData.Tables[0];

我希望在datagriedview 1中添加一个复选框为空的列,具体操作如下:

DataGridViewCheckBoxColumn col = new DataGridViewCheckBoxColumn();
 dataGridView1.Columns.Add(col);

这也很好,我可以看到表与chcekbox列.我有一个提交按钮在这个表单.我希望选中2复选框,并提交表单.这也很好.但提交后,我期待一个问题.我试图通过行循环,并希望得到选中的值.

String[] files = new String[5];
int i = 0;
foreach (DataGridViewRow item in dataGridView1.Rows)
{
    if (item.Cells[3].Value is true)
        files[i] = (String)item.Cells[2].Value;
    i++;
}

在尝试访问item.Cells[3].Value时,我正在获取indexofboundException。我可以访问其他值(例如第1行:1|xy|z).但是添加的chceckbox-columum是不可访问的。我如何访问复选框列?

hwamh0ep

hwamh0ep1#

在没有看到更多代码的情况下,这只是一个猜测,但听起来您的网格没有您想象的那么多列。
在中断的那一行前面放一个断点,然后查看item.Cells,看看有多少个元素,它们包含什么。我怀疑你会发现只有3个元素,这可以解释你的错误。
如果是这样,检查你的网格,确保你有你期望的列。如果你有,发布更多的代码。

p1tboqfb

p1tboqfb2#

这里有一个建议,将数据库中的数据加载到DataTable中,添加一个类型为bool的新列,并将默认值设置为false,以允许用户进行选择,并将本例中的序号位置设置为第一列。
这里我们包含了一个可选的主键,并将ColumnMapping设置为hidden,这样它就不会出现在DataGridView中,但是我们可以在稍后的按钮Click事件中访问它。注意我没有使用DataSet,但是这并不重要,因为我们最终仍然使用DataTable。

public class DataOperations
{
    private static readonly string ConnectionString =
        "Data Source=.\\SQLEXPRESS;" +
        "Initial Catalog=NorthWind2022;" +
        "Integrated Security=True;" +
        "Encrypt=False";

    public static DataTable LoadData()
    {
        var dt = new DataTable();

        using var cn = new SqlConnection { ConnectionString = ConnectionString };
        using var cmd = new SqlCommand { Connection = cn };

        cn.Open();

        cmd.CommandText = "SELECT CountryIdentifier ,[Name] FROM dbo.Countries";

        dt.Load(cmd.ExecuteReader());

        dt.Columns["CountryIdentifier"].ColumnMapping = MappingType.Hidden;
        dt.Columns.Add(new DataColumn()
        {
            ColumnName = "Checked", 
            DefaultValue = false, 
            DataType = typeof(bool)
        });

        dt.Columns["Checked"].SetOrdinal(0);

        return dt;

    }
}

为了保持表单中的代码整洁,使用了这两种语言扩展。第一种是获取DataTable,第二种是获取选中的行。

internal static class DataGridViewExtensions
{
    public static DataTable DataTable(this DataGridView pDataGridView) 
        => (DataTable)pDataGridView.DataSource;

    public static List<DataRow> Checked(this DataTable pDataTable, string pColumnName) 
        => pDataTable.AsEnumerable().Where(row => row.Field<bool>(pColumnName)).ToList();
}

表单代码,我们从原始SQL SELECT语句中知道列名。

public partial class DataGridViewForm : Form
{
    public DataGridViewForm()
    {
        InitializeComponent();

        dataGridView1.DataSource = DataOperations.LoadData();
        dataGridView1.Columns["Checked"].HeaderText = "";
        dataGridView1.Columns["Checked"].Width = 25;
    }

    private void GetCheckedButton_Click(object sender, EventArgs e)
    {
        var checkedRows = dataGridView1
            .DataTable()
            .Checked("Checked");

        if (checkedRows.Any())
        {
            foreach (var row in checkedRows)
            {
                // logic to do your work, here I simple show how to access 
                // properties
                Debug.WriteLine($"" +
                                $"{row.Field<int>("CountryIdentifier"),-5}" +
                                $"{row.Field<string>("name")}");
            } 
        }
    }
}

因此,在结束时,必须知道SELECT语句中的列的名称以便稍后使用,并且还注意,当DataGridView有DataSource时,我们迭代DataRow对象而不是迭代DataGridView中的行,这总是比迭代DataGridView中的单元格更好。

相关问题