2

我正在制作一个程序来检查我在大学里还剩下多少门课程。我将信息从csv放置它的数据加载到数据集并使用数据网格显示它。

我希望某些列(实验室和理论)具有复选框单元格,以便我可以检查我通过的课程,然后将它们保存回以csv稍后再次加载它们(当我通过某些东西时:P)。但是我在将这些(字符串)列转换为复选框时遇到问题,因为我在 c# 中没有那么丰富的经验

那是我的代码:

string delimiter = ";";
string tablename = "paTable";
filename = "aname";
DataSet dataset = new DataSet();
StreamReader sr = new StreamReader(filename);
DataGridViewColumn column = new DataGridViewColumn();
dataset.Tables.Add(tablename);

dataset.Tables[tablename].Columns.Add("A/A");
dataset.Tables[tablename].Columns.Add("Course");
dataset.Tables[tablename].Columns.Add("Semester");
dataset.Tables[tablename].Columns.Add("Theory");
dataset.Tables[tablename].Columns.Add("Lab");
dataset.Tables[tablename].Columns.Add("Passed");

string alldata = sr.ReadLine();
while (sr.Peek() != -1)
{
alldata = sr.ReadLine();
string[] rows;
rows = alldata.Split("\r".ToCharArray());

foreach (string r in rows)
{
string[] items = r.Split(delimiter.ToCharArray());
dataset.Tables[tablename].Rows.Add(items);
}

this.dataGridView1.DataSource = dataset.Tables[0].DefaultView;
}

任何帮助,将不胜感激 !

4

3 回答 3

1

如果您手动创建列并将其添加到您的DataGridView中,我认为您可以保持DataSet-loading 过程不变。

关闭AutoGenerateColumns并手动添加它们:

dataGridView1.AutoGenerateColumns = false;
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn { Name="Course", ... } );
dataGridView1.Columns.Add(new DataGridViewCheckBoxColumn { Name="Passed", ... } );
...

DataView将网格视图与您正在执行的操作绑定后,应该会填充网格视图:

dataGridView1.DataSource = dataset.Tables[0].DefaultView;

编辑

因为它依赖于强类型和适当的绑定,可能更好的选择是创建一个类来表示 CSV 记录(假定类型)。如果该类实现了INotifyPropertyChanged接口,则可以在 中编辑值DataGridView并在该类中以最小的努力反映出来。

public class CsvDataRow : INotifyPropertyChanged
{
    private bool _aa;
    private string _course;
    private int _semester;
    private double _theory;
    private double _lab;
    private bool _passed;

    public bool AA { get { return _aa; } set { if (value == _aa) return; _aa = value; NotifyPropertyChanged("AA"); } }
    public string Course { get { return _course; } set { if (value == _course) return; _course = value; NotifyPropertyChanged("Course"); } }
    public int Semester { get { return _semester; } set { if (value == _semester) return; _semester = value; NotifyPropertyChanged("Semester"); } }
    public double Theory { get { return _theory; } set { if (value == _theory) return; _theory = value; NotifyPropertyChanged("Theory"); } }
    public double Lab { get { return _lab; } set { if (value == _lab) return; _lab = value; NotifyPropertyChanged("Lab"); } }
    public bool Passed { get { return _passed; } set { if (value == _passed) return; _passed = value; NotifyPropertyChanged("Passed"); } }

    char _delimiter;

    // static factory method creates object from CSV row
    public static CsvDataRow Create(string row, char delimiter)
    {
        return new CsvDataRow(row, delimiter);
    }

    // private constructor initializes property values
    private CsvDataRow(string row, char delimiter)
    {
        _delimiter = delimiter;

        var values = row.Split(_delimiter);
        AA = (values[0].ToString().Equals("1"));
        Course = Convert.ToString(values[1]);
        Semester = Convert.ToInt32(values[2]);
        Theory = Convert.ToDouble(values[3]);
        Lab = Convert.ToDouble(values[4]);
        Passed = (values[5].ToString().Equals("1"));
    }

    // a method to convert back into a CSV row
    public string ToCsvString()
    {
        var values = new string[] { (AA ? 1 : 0).ToString(), Course, Semester.ToString(), Theory.ToString(), Lab.ToString(), (Passed ? 1: 0).ToString() };
        return string.Join(_delimiter.ToString(), values);
    }

    // INotifyPropertyChanged interface requires this event
    public event PropertyChangedEventHandler PropertyChanged;

    // helper method to raise PropertyChanged event
    private void NotifyPropertyChanged(string name)
    {
        if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(name));
    }
}

CSV 文件本身可以由一个类表示:

public class CsvDataSource
{
    public char Delimiter { get; private set; }
    public CsvDataSource()
        : this(',')
    { }

    public string[] Columns { get; private set; }

    public ObservableCollection<CsvDataRow> Rows { get; private set; }

    public CsvDataSource(char delimiter)
    {
        Delimiter = delimiter;
    }

    public void LoadCsv(string csvFileName)
    {
        string header;
        string data;

        using (var reader = new StreamReader(csvFileName))
        {
            header = reader.ReadLine(); // assumes 1st row is column headers
            data = reader.ReadToEnd();
        }

        Columns = header.Split(Delimiter);
        var rows = Regex.Split(data, Environment.NewLine);

        if (!rows.Select(row => row.Split(Delimiter)).All(row => row.Length == Columns.Length)) throw new FormatException("Inconsistent data format.");
        Rows = new ObservableCollection<CsvDataRow>(rows.Select(row => CsvDataRow.Create(row, Delimiter)));
    }
}

然后可以将 DataGridView 绑定到实例的Rows属性CsvDataSource,因此表单的代码如下所示:

public partial class Form1 : Form
{
    private CsvDataSource _data;
    private ObservableCollection<CsvDataRow> _rows;

    public Form1()
    {
        InitializeComponent();
    }

    public void LoadCsv(CsvDataSource data)
    {
        _data = data;
        _rows = _data.Rows;
        dataGridView1.DataSource = _rows;
    }

    public void SaveCsv(string path)
    {
        using (var writer = new StreamWriter(path))
        {
            writer.WriteLine(string.Join(_data.Delimiter.ToString(), _data.Columns));
            foreach (var row in _rows)
            {
                writer.WriteLine(row.ToCsvString());
            }
        }
    }
}

当然,您会有一个按钮调用该SaveCsv方法,并且您需要另一个按钮来向/从您的 DataGridView 添加/删除行。此外,您还需要将文件 I/O 操作包装在 try/cath 块中。

这是一个快速总结的实现,确实需要一些额外的工作才能完全发挥作用,但它提供了一个想法,并且开箱即用。

这样,“定义列”部分在CsvDataRow为每个记录提供强类型的类中完全得到处理。不DataSet,不DataColumn,也不DataGridViewColumn。只是数据,还有一些数据绑定。

于 2013-05-28T16:54:25.610 回答
1

您可以像这样将文本框列“转换”为复选框:

        dgv.Columns.RemoveAt(<NumberColumn2Remove>);

        DataGridViewCheckBoxColumn chk = new DataGridViewCheckBoxColumn;
        chk.HeaderText = "<HeaderText>";
        chk.Name = "<WhatEver>";
        chk.DataPropertyName = "<DataField2Bind2>";

        dgv.Columns.Insert(<NumberColumn2Insert>, chk);
于 2017-08-17T09:04:30.867 回答
0

您需要一个 DataGridViewCheckBoxColumn:

所以你需要更换

DataGridViewColumn column = new DataGridViewColumn();

DataGridViewCheckBoxColumn. 读一读。_

于 2013-05-28T16:27:52.880 回答