【问题标题】:Add all elements of array to datagridview rows except one将数组的所有元素添加到 datagridview 行,除了一个
【发布时间】:2012-11-23 20:41:29
【问题描述】:

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

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

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

我知道组合框是用正确的数据源正确添加的,因为如果我只是将 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

【问题讨论】:

  • 为什么不将记录放入List,然后从列表中删除不良记录(或使用LINQ仅选择好的记录放入新的Array/List)?
  • 有没有办法将项目数组中的值添加到组合框单元格中?如果我将数组中的违规值设置为 string.empty,它会起作用,但似乎我也应该能够在组合框中显示该值。
  • 我想是的,但我已经有一段时间没有尝试过了。您也可以尝试创建一个新的列类型,并使用默认的 ComboBox 来将自定义值输入到打开的文本框部分。然后只需将 ComboBox 的文本设置为您获得的值。

标签: c# winforms datagridview


【解决方案1】:

假设您的文本文件包含:

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

假设您的 DataGridView 设置为 3 列,第二列是组合框。

当您填充网格并错误地填充组合框列时,您将收到错误消息。

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

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

因此,假设第二列包含国家/地区的下拉列表,第一列和第三列包含文本字段。

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

public class CountryData
{
    public string FirstCountry { get; set; }
    public string ThirdCountry { get; set; }
}

对于第二列“Countries”组合框单元格,我创建了一个单独的类,因为我会将它绑定到第二列数据源。

public class MultiCountryData
{
    public string[] SeceondCountryOption { get; set; }
}

使用组合框列等填充网格,如下所示:https://stackoverflow.com/a/1292847/495455 不是好的做法。您希望将您的业务逻辑与您的演示文稿分开,以获得一种更加封装、多态和抽象的方法,从而简化单元测试和维护。因此是 DataBinding。

代码如下:

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(',')});

            }
        //}
      }

}
}

在您的演示项目中,这里是按钮点击代码:

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

我设置了dataGridView2.AutoGenerateColumns = false;,因为我在设计时添加了 3 列;第 1 个文本列、第 2 个组合框列和第 3 个文本列。

绑定第二个组合框列的技巧是BindingSource。在设计时 > 右键单击​​ DataGridView > 选择 Edit Columns > 选择第二列 > 选择 DataSource > 单击 Add Project DataSource > 选择 Object > 然后勾选 multiCountry 类并单击 Finish。

还将第一列的 DataPropertyName 设置为 FirstCountry,将第三列的 DataPropertyName 设置为 ThirdCountry,因此当您绑定数据时,映射会自动完成。

最后,别忘了将 BindingSource 的 DataMember 属性设置为 multiCountry 类的 SeceondCountryOption 成员。

这是一个代码演示http://temp-share.com/show/HKdPSzU1A

【讨论】:

  • 有没有办法将文本文件中的第二列添加为默认值,在组合框中显示值?
  • 那么,例如,PNG 将是第一行列框显示的默认值?或者只是让它显示在那个单元格中?
  • 很简单,如果您希望 PNG 成为第一行组合框的默认值,只需在绑定数据源后在代码中设置 dataGridView2.Rows[0].Cells[1].Value = "PNG";
  • 哦,我只是举个例子 :) 硬编码很容易。谢谢,有机会我会看看这个!
  • +1 获取所有详细的屏幕截图 - 绝对是一个疯狂的细节水平。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-10
  • 1970-01-01
  • 1970-01-01
  • 2022-11-21
  • 1970-01-01
  • 2018-05-13
相关资源
最近更新 更多