c# - List<T> Add 方法在 Button.Click 事件中不起作用,但在 Form.Load 中起作用

标签 c# winforms arraylist datagridview

我正在尝试制作一个充当 parking 场的程序。

到目前为止,我使用了一些功能,一切都工作正常,直到我尝试在 parking 场添加一辆新车。

在这种情况下我尝试使用 add 方法,但找不到问题所在。虽然当我在 Form_Load 事件中使用该方法时它可以正常工作,但它在 Button_Click 事件处理程序中不起作用。

我的类(class)是这样的:

class Parking
{
    public int Spot { get; set; }
    public string Plate { get; set; }
    public DateTime EnterTime { get; set; }
    public DateTime? ExitTime { get; set; }

    public Parking(int spot, string plate, DateTime enterTime)
    {
        Spot = spot;
        Plate = plate;
        EnterTime = enterTime;
        ExitTime = null;
    }
}

到目前为止我的代码:

public partial class Form1 : Form
{
    Timer clock = new Timer();

    List<Parking> parking = new List<Parking>();

    public Form1()
    {
        InitializeComponent();
        GetLoadDataBase();
    }
    
    private void GetLoadDataBase()
    {
        parking.AddRange(new List<Parking>
        {
            new Parking(1, "TKN1893", DateTime.Now),            
            new Parking(2, "TKN1951", DateTime.Now),
            new Parking(3, "TNA725", DateTime.Now),
            new Parking(4, "TNA725", DateTime.Now),
            new Parking(5, "TNA725", DateTime.Now),
            new Parking(6, "TNA725", DateTime.Now),
            new Parking(7, "TNA725", DateTime.Now),
            new Parking(8, "TNA725", DateTime.Now)
        });                     
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        clock.Interval = 1000;
        clock.Tick += new EventHandler(this.clock_Tick);
        clock.Start();

        *parking.Add(new Parking(10, "IP3147", DateTime.Now));
        dataGridView1.DataSource = parking;            
    }              

    private void DataGridView1_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
    {
        try
        {
            string spot = dataGridView1.Rows[e.RowIndex].Cells[0].Value.ToString();
            string plate = dataGridView1.Rows[e.RowIndex].Cells[1].Value.ToString();
            string enterTime = dataGridView1.Rows[e.RowIndex].Cells[2].Value.ToString();
            ExitTimeInsert(e.RowIndex, parking);
            string exitTime = dataGridView1.Rows[e.RowIndex].Cells[3].Value.ToString();

            string BoxText = spot + " " + plate + " " + enterTime + " " + exitTime;

            DialogResult charge = MessageBox.Show(BoxText, "Test", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            if (charge == DialogResult.Yes)
            {
                parking[e.RowIndex] = null;
                dataGridView1.Refresh();
            }
            else
            {
                parking[e.RowIndex].ExitTime = null;                    
            }
        }
        catch(NullReferenceException)
        {
            MessageBox.Show("The Spot is Empty!");
        }
    }

    private void ExitTimeInsert(int index, List<Parking> parking)
    {
        parking[index].ExitTime = DateTime.Now;
    }

    private void clock_Tick(object sender, EventArgs e)
    {
        //get current time
        int hh = DateTime.Now.Hour;
        int mm = DateTime.Now.Minute;
        int ss = DateTime.Now.Second;

        //time
        string date = DateTime.Now.Date.ToLongDateString();
        string time = "";

        //padding leading zero
        if (hh < 10)
        {
            time += "0" + hh;
        }
        else
        {
            time += hh;
        }
        time += ":";

        if (mm < 10)
        {
            time += "0" + mm;
        }
        else
        {
            time += mm;
        }
        time += ":";

        if (ss < 10)
        {
            time += "0" + ss;
        }
        else
        {
            time += ss;
        }

        //update label
        label1.Text = time;
        label2.Text = date;
    }

    private void Exit_Click(object sender, EventArgs e)
    {
        System.Windows.Forms.Application.Exit();
    }

    private void Input_Button_Click(object sender, EventArgs e)
    {
        **Parking Adition = new Parking(10, "IP3147", DateTime.Now);
        **parking.Add(Adition);
        **parking.Add(new Parking(10, "IP3147", DateTime.Now));
        **Add_Record(textBox1.Text);
        **dataGridView1.DataSource = parking;
        dataGridView1.Refresh();
    }

    private void Add_Record(string value)
    {
        **parking.Add(new Parking(10, value, DateTime.Now));
        **dataGridView1.DataSource = parking;
    }
}

我希望这是有道理的:

“*”“有效的实现” “**”“单独尝试的实现并非全部一起尝试,但不起作用”

其他一切正常。

最佳答案

当DataGridView的DataSource为标准时List<T>List<T> 上的更改内容不会自动反射(reflect)在 DataGridView 中:List<T>不会发送更新通知。
将 DataGridView 的 DataSource 属性重新设置为相同的 List<T>也不会刷新数据,因为 DataSource 对象引用实际上是相同的。

在.Net源码中可以看到:DataGridView.DataSource property setter

set
{
    if (value != this.DataSource) { ...  } 

value=this.DataSource :数据源相同,因此不执行任何操作。

将 DataSource 属性设置为 null然后再回到之前的List<T>将重置数据源。

另一个选项(可能更可取)是使用 BindingList而不是List<T>

The BindingList<T> class can be used as a base class to create a two-way data-binding mechanism. BindingList<T> provides a concrete, generic implementation of the IBindingList interface.

让我们使用当前设置让它工作:

  1. 添加 Parking 元素添加到 BindingList(表单构造函数或 Form.Load )
  2. 设置DataGridView.DataSource BindingList 对象的属性。

使用 BindingList与使用标准 List<T> 几乎相同.
请注意,当您从 BindingList 添加或删除元素时,DataGridView 会立即更新,无需任何进一步操作:

DataGridView BindingList

private BindingList<Parking> parking = null;

public Form1()
{
    InitializeComponent();

    var tmpList = new List<Parking>
    {
        new Parking(1, "TKN1893", DateTime.Now),
        new Parking(2, "TKN1951", DateTime.Now),
        new Parking(3, "TNA725", DateTime.Now),
    };
    this.parking = new BindingList<Parking>();
    tmpList.ForEach(elm => parking.Add(elm));
}

private void Form1_Load(object sender, EventArgs e)
{
    //(...)
    this.dataGridView1.DataSource = this.parking;            
}              

private void btnAddRecord_Click(object sender, EventArgs e)
{
    this.parking.Add(new Parking(10, "IP3147", DateTime.Now));
}

private void btnRemoveRecord(string value)
{
    this.parking.RemoveAt(0);
}

关于c# - List<T> Add 方法在 Button.Click 事件中不起作用,但在 Form.Load 中起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54762091/

相关文章:

java ArrayList只添加一个元素

c# - 如何使用 LINQ 按深度级别对对象层次结构进行排序?

c# - Monitor.Wait() 和 Monitor.Pulse() 的线程问题

c# - 返回时导致 SEGFAULT 的非托管函数指针

c# - 如何同时更好地控制多个控件的行为?

c# - C#获取窗口句柄

c# - WinForms 列表框中的图像缩略图

c# - 无法从 RestSharp OAuth 请求 Windows Phone 8.1 中保存 token

java - 如何从另一个类访问 arrayList (存储在主类中)?

java - ArrayList 和 Formatter 的行为不符合预期