C# 将数组的所有元素添加到datagridview行中,只有一个除外

C# 将数组的所有元素添加到datagridview行中,只有一个除外,c#,winforms,datagridview,C#,Winforms,Datagridview,我正在逐行读取文本文件,并将其插入数组中 然后我有一个名为custIndex的列表,其中包含某些索引,我正在测试的items数组的索引,看看它们是否是有效代码。(例如,custIndex[0]=7,因此我在这里的两个字典中检查项目[7-1]中的值以查看其是否有效)。然后,如果有无效代码,我将该行(items数组)添加到dataGridView1 问题是,dataGridView1中的一些列是组合框列,因此用户可以选择正确的值。尝试添加items数组时,出现异常:“DataGridView中发生以

我正在逐行读取文本文件,并将其插入数组中

然后我有一个名为custIndex的列表,其中包含某些索引,我正在测试的items数组的索引,看看它们是否是有效代码。(例如,custIndex[0]=7,因此我在这里的两个字典中检查项目[7-1]中的值以查看其是否有效)。然后,如果有无效代码,我将该行(items数组)添加到dataGridView1

问题是,dataGridView1中的一些列是组合框列,因此用户可以选择正确的值。尝试添加items数组时,出现异常:“DataGridView中发生以下异常:System.ArgumentException:DataGridViewComboxCell值无效。”

我知道组合框是使用正确的数据源正确添加的,因为如果我只将items数组中的一些项添加到dataGridView1中,就像只添加items[0]一样,组合框会显示得很好,并且不会引发异常。我想问题是当我尝试将items数组中的错误值添加到dataGridView1行时

我不知道该怎么处理。是否有一种方法可以添加项目中除该值之外的所有项目?或者我可以添加来自项目的值,并将其与填充的下拉项目一起显示在组合框单元格中吗

if(choosenFile.Contains("Cust"))
{
    var lines = File.ReadAllLines(path+"\\"+ choosenFile);

    foreach (string line in lines)
    {
        errorCounter = 0;
        string[] items = line.Split('\t').ToArray();

        for (int i = 0; i <custIndex.Count; i++)
        {
            int index = custIndex[i];
            /*Get the state and country codes from the files using the correct indices*/
            Globals.Code = items[index - 1].ToUpper();

            if (!CountryList.ContainsKey(Globals.Code) && !StateList.ContainsKey(Globals.Code))
            {
                errorCounter++;

                dataGridView1.Rows.Add(items);
            }
        }//inner for

        if (errorCounter == 0)
            dataGridView2.Rows.Add(items);

    }//inner for each

}//if file is a customer file
if(选择file.Contains(“Cust”))
{
var lines=File.ReadAllLines(路径+“\\”+选择文件);
foreach(行中的字符串行)
{
errorCounter=0;
string[]items=line.Split('\t').ToArray();

对于(int i=0;i来说,您的文本文件包含:

澳大利亚巴布亚新几内亚、印度和非洲
奥地利-巴厘岛-印度尼西亚
法国、英格兰、苏格兰、爱尔兰、格陵兰
德国巴哈马夏威夷
希腊哥伦比亚、墨西哥、秘鲁和阿根廷
新西兰俄罗斯美国

假设DataGridView设置为3列,第2列是组合框

当您填充网格并错误地填充组合框列时,您将得到错误

解决方法是“显式处理/声明”DataError事件,更重要的是正确填充combobox列

private void dataGridView1_DataError(object sender, DataGridViewDataErrorEventArgs e)
{
    //Cancelling doesn't make a difference, specifying the event avoids the prompt 
    e.Cancel = true;
}

private void dataGridView2_DataError(object sender, DataGridViewDataErrorEventArgs e)
{
    e.Cancel = true;
}
因此,假设第2列包含国家的下拉列表,第1列和第3列包含文本字段

对于第1列和第3列,它们只是字符串,因此我创建了一个类来表示每一行:

public class CountryData
{
    public string FirstCountry { get; set; }
    public string ThirdCountry { get; set; }
}
对于第二列“国家”组合框单元格,我创建了一个单独的类,因为我将把它绑定到第二列数据源

public class MultiCountryData
{
    public string[] SeceondCountryOption { get; set; }
}
使用组合框列等填充网格(如图所示):不是一种好的做法。您希望将业务逻辑与演示文稿分离,以获得一种更为封装、多态和抽象的方法,从而简化单元测试和维护。因此,数据绑定

代码如下:

namespace BusLogic
{
public class ProcessFiles
{

internal List<CountryData> CountryDataList = new List<CountryData>();
internal List<MultiCountryData> MultiCountryDataList = new List<MultiCountryData>();

internal void foo(string path,string choosenFile)
{
    var custIndex = new List<int>();
    //if (choosenFile.Contains("Cust"))
    //{
        var lines = File.ReadAllLines(path + "\\" + choosenFile);
        foreach (string line in lines)
        {
            int errorCounter = 0;
            string[] items = line.Split('\t');

            //Put all your logic back here...

            if (errorCounter == 0)
            {
                var countryData = new CountryData()
                                      {
                                          FirstCountry = items[0],
                                          ThirdCountry = items[2]
                                      };
                countryDataList.Add(countryData);

                multiCountryDataList.Add( new MultiCountryData() { SeceondCountryOption = items[1].Split(',')});

            }
        //}
      }

}
}
我设置了
dataGridView2.AutoGenerateColumns=false;
,因为我在设计期间添加了3列:第一个文本列、第二个组合框列和第三个文本列

绑定第二个组合框列的技巧是
BindingSource
。在设计时>右键单击DataGridView>选择编辑列>选择第二列>选择数据源>单击添加项目数据源>选择对象>然后勾选multiCountry类并单击完成

还将第一列的DataPropertyName设置为FirstCountry,将第三列的DataPropertyName设置为ThirdCountry,以便在绑定数据时自动完成映射

最后,不要忘记将BindingSource的DataMember属性设置为multiCountry类的
SeceondCountryOption
成员


下面是一个代码演示

为什么不将记录放入列表,然后从列表中删除坏记录(或者使用LINQ仅将好记录选择到新数组/列表中)?是否有方法将项数组中的值添加到组合框单元格中?如果我将数组中有问题的值设置为string.empty,则该方法有效,但似乎我也应该能够在组合框中显示该值。我认为可以,但我已经尝试了一段时间。您也可以尝试创建一个新的列类型,并使用默认的组合框w如果启用了在文本框部分输入自定义值的功能,则只需将组合框的文本设置为您获得的值。是否有方法将文本文件中的第二列添加为默认值,在组合框中显示值?例如,PNG将是第一行-列框的默认值?或者仅为h将其显示在该单元格中?这很简单,如果希望PNG作为第一行组合框的默认值,只需在绑定数据源后在代码中设置
dataGridView2.rows[0].Cells[1].value=“PNG”
。哦,我只是举个例子:)硬编码很简单。谢谢,我会在有机会的时候看看这个!+1的所有详细截图-绝对是一个疯狂的细节水平。
 imports BusLogic;
 private void button1_Click(object sender, EventArgs e)
 {
     var pf = new ProcessFiles();
     pf.foo(@"C:\temp","countries.txt"); 
     dataGridView2.AutoGenerateColumns = false;
     dataGridView2.DataSource = pf.CountryDataList;
     multiCountryDataBindingSource.DataSource = pf.MultiCountryDataList;      
 }