本文介绍了阵列中的所有元素添加到datagridview的行除了一的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我逐行读取文本文件行,并将其插入到一个数组。



然后,我有这个名单称为custIndex,其中包含一定的指数,指数的项目数组,我测试,看看他们是否是有效的代码。 (例如,custIndex [0] = 7,所以我检查项目[7-1]的值,看其是否有效,在两本词典我这里)。然后,如果有一个无效的代码,我添加行(项目数组)dataGridView1。



事情是,一些dataGridView1列是组合框列,这样,用户可以选择一个正确的值。当我尝试添加的项目数组,我得到一个异常:发生在DataGridView以下异常信息:System.ArgumentException:值的DataGridViewComboBoxCell无效



我知道用正确的数据源正确地添加组合框,因为如果我只是项目阵列中添加一些项目到dataGridView1,像刚才项[0],组合框中显示了罚款,并没有抛出异常。我想这个问题是,当我尝试添加的项目阵列的dataGridView1行中的不正确的值。



我不知道该如何处理这个问题。有没有一种方法,我可以添加所有项目中的项目除外价值?或者,我可以从项目的附加价值并使其在组合框中细胞显示,随着人口下拉项目一起?



 如果(choosenFile.Contains(卡斯特))
{
VAR线= File.ReadAllLines(路径+\\+ choosenFile);

的foreach(以线串线)
{
errorCounter = 0;
的String []项目= line.Split('\t')ToArray的()。

的for(int i = 0; I< custIndex.Count;我++)
{
INT指数= custIndex [I]
/ *获取从文件中使用正确的指数* /
Globals.Code =项国家和国家代码[指数 - 1] .ToUpper();

如果(CountryList.ContainsKey(Globals.Code)及!&安培;!StateList.ContainsKey(Globals.Code))
{
errorCounter ++;

dataGridView1.Rows.Add(项目);
}
} //内为

如果(errorCounter == 0)
dataGridView2.Rows.Add(项目);

} //内每个

} //如果文件是客户文件


解决方案

说你的文本文件包含:



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



和让说你的DataGridView是设置有3列,第二个是一个组合框。





在填充网格,并错误地填充组合框列中,您将得到错误。



要解决它是由处理/宣称明确的DataError事件,更重要的是正确地填充组合框列的方式。

 私人无效dataGridView1_DataError(对象发件人,DataGridViewDataErrorEventArgs E)
{
//消不有所作为,指定事件避免了提示
e.Cancel = TRUE;
}

私人无效dataGridView2_DataError(对象发件人,DataGridViewDataErrorEventArgs E)
{
e.Cancel = TRUE;
}



所以,想象中的第2列载的国家的一个DropDownList和第一和放大器; 。第3列包含文本字段



有关第一和第三列,他们仅仅是字符串,所以我创建一个类来表示每一行:

 公共类CountryData 
{
公共字符串FirstCountry {搞定;组; }
公共字符串ThirdCountry {搞定;组; }
}

有关的第2列国家组合框细胞的我创建了一个单独的类因为我将它绑定到第二列的数据源。

 公共类MultiCountryData 
{
公共字符串[] {SeceondCountryOption获得;组; }
}

填充用组合框列的网格,这里显示等作为:是不是好的做法。你想你的业务逻辑从演示分开的多个封装,多态和抽象的方法,将缓解单元测试和维护。因此,数据绑定



下面是代码:

 命名空间的BusLogic 
{
公共类ProcessFiles
{

内部列表< CountryData> CountryDataList =新的List< CountryData>();
内部列表< MultiCountryData> MultiCountryDataList =新的List< MultiCountryData>();

内部无效美孚(路径字符串,字符串choosenFile)
{
变种custIndex =新的List< INT>();
//如果(choosenFile.Contains(卡斯特))
// {
VAR线= File.ReadAllLines(路径+\\+ choosenFile);
的foreach(以线串线)
{
INT errorCounter = 0;
的String []项目= line.Split('\t');

//把所有的逻辑,回到这里...

如果(errorCounter == 0)
{
变种countryData =新CountryData()
{
FirstCountry =项目[0],
ThirdCountry =项目[2]
};
countryDataList.Add(countryData);

multiCountryDataList.Add(新MultiCountryData(){SeceondCountryOption =项[1] .Split(,)});

}
//}
}

}
}

在这里演示的项目是按钮单击代码:

 进口在BusLogic; 
私人无效的button1_Click(对象发件人,EventArgs五)
{
变种PF =新ProcessFiles();
pf.foo(@C:\temp,countries.txt);
dataGridView2.AutoGenerateColumns = FALSE;
dataGridView2.DataSource = pf.CountryDataList;
multiCountryDataBindingSource.DataSource = pf.MultiCountryDataList;
}



我设置 dataGridView2.AutoGenerateColumns = FALSE; ,因为我已经添加在设计时的3列; 1文本列,第二个组合框列和第3文本列。



与结合第二组合​​框列诀窍是的BindingSource 。在设计时>右键单击在DataGridView>选择编辑列>选择第二列>选择数据源>单击添加项目数据源>选择对象>再勾选多国类,然后单击Finish(完成)。







还设置第一列的DataPropertyName到FirstCountry 3列的DataPropertyName到ThirdCountry,所以当你绑定映射是自动完成的数据。





最后,不要忘记设置。BindingSource的的成员属性的多国类的 SeceondCountryOption 成员





下面是一个代码演示的


I'm reading a text file line by line, and inserting it into an array.

I then have this list called custIndex, which contains certain indices, indices of the items array that I'm testing to see if they are valid codes. (for example, custIndex[0]=7, so I check the value in items[7-1] to see if its valid, in the two dictionaries I have here). Then, if there's an invalid code, I add the line (the items array) to dataGridView1.

The thing is, some of the columns in dataGridView1 are Combo Box Columns, so the user can select a correct value. When I try adding the items array, I get an exception: "The following exception occurred in the DataGridView: System.ArgumentException: DataGridViewComboBoxCell value is not valid."

I know the combo box was added correctly with the correct data source, since if I just add a few items in the items array to the dataGridView1, like just items[0], the combo box shows up fine and there's no exception thrown. I guess the problem is when I try adding the incorrect value in the items array to the dataGridView1 row.

I'm not sure how to deal with this. Is there a way I can add all of the items in items except for that value? Or can I add the value from items and have it show up in the combo box cell, along with the populated drop down items?

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
解决方案

Say your text file contains:

Australia PNG, India Africa
Austria Bali Indonisia
France England,Scotland,Ireland Greenland
Germany Bahama Hawaii
Greece Columbia,Mexico,Peru Argentina
New Zealand Russia USA

And lets say your DataGridView is setup with 3 columns, the 2nd being a combobox.

When you populate the grid and incorrectly populate the combobox column you will get the error.

The way to solve it is by "handling/declaring explicitly" the DataError event and more importantly populating the combobox column correctly.

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

So imagine the 2nd column contained a dropdownlist of countries and the 1st & 3rd column contained text fields.

For the 1st and 3rd columns they are just strings so I create a class to represent each row:

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

For the 2nd column "Countries" combobox cell's I have created a separate class because I will bind it to the 2nd columns datasource.

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

Populating the grid with combobox columns and the like as shown here: http://stackoverflow.com/a/1292847/495455 is not good practice. You want to separate your business logic from your presentation for a more encapsulated, polymorphic and abstract approach that will ease unit testing and maintenance. Hence the DataBinding.

Here is the code:

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

            }
        //}
      }

}
}

In your presentation project here is the button click code:

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

I set dataGridView2.AutoGenerateColumns = false; because I have added the 3 columns during design time; 1st text column, 2nd combobox column and 3rd text column.

The trick with binding the 2nd combobox column is a BindingSource. In design time > right click on the DataGridView > choose Edit Columns > select the second column > choose DataSource > click Add Project DataSource > choose Object > then tick the multiCountry class and click Finish.

Also set the 1st column's DataPropertyName to FirstCountry and the 3rd column's DataPropertyName to ThirdCountry, so when you bind the data the mapping is done automatically.

Finally, dont forget to set the BindingSource's DataMember property to the multiCountry class's SeceondCountryOption member.

Here is a code demo http://temp-share.com/show/HKdPSzU1A

这篇关于阵列中的所有元素添加到datagridview的行除了一的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-29 07:18