【问题标题】:DataGridView selection change doesn't show until the SelectionChanged event handler has completed在 SelectionChanged 事件处理程序完成之前,不会显示 DataGridView 选择更改
【发布时间】:2012-05-23 00:54:02
【问题描述】:

我正在捕捉 DataGridView 控件的 SelectionChanged 事件,我的事件处理程序大约需要 1/2 秒来完成其任务(设置多个控件的值等)。在 UI 方面,这是永恒的。

问题在于 DataGridView 的用户界面不会立即更新选择。我想要的是让用户在单击后立即看到 DataGridView 中的选择更改,然后 完成了漫长的工作。完成整个任务仍然需要 1/2 秒,并且在此期间 UI 不会响应,这没关系 - 至少用户会得到即时反馈。

您可以通过将以下代码插入新的 Form1 类来查看此行为:

    private System.Windows.Forms.DataGridView dataGridView1;

    public Form1()
    {
        InitializeComponent();
        dataGridView1 = new DataGridView();
        dataGridView1.Dock = DockStyle.Fill;
        dataGridView1.Columns.Add("Column0", "Column 0");
        dataGridView1.Rows.Add("Row 0");
        dataGridView1.Rows.Add("Row 1");
        dataGridView1.Rows.Add("Row 2");
        dataGridView1.Rows.Add("Row 3");
        dataGridView1.SelectionChanged += 
            new EventHandler(dataGridView1_SelectionChanged);
        this.Controls.Add(dataGridView1);
    }
    private void dataGridView1_SelectionChanged(object sender, EventArgs e)
    {
        if (this.Handle != null)
        {
            this.DoSomethingForAWhile();
            // Even BeginInvoke doesn't help
            //this.BeginInvoke((MethodInvoker)this.DoSomethingForAWhile);
        }
    }
    private void DoSomethingForAWhile()
    {
        // Do anything that causes a noticable delay

        DateTime t0 = DateTime.Now;
        while ((DateTime.Now - t0).TotalSeconds < 2)
        {
            // Do nothing
        }
    }

我通常会使用 Control.BeginInvoke 以便在我的 1/2 秒任务开始之前处理绘制消息。这适用于 ListView 控件,但由于某种原因它不适用于 DataGridView。

可以在另一个线程上进行处理并使用 Invoke 来设置 UI 值,但这对于应该简单的任务来说似乎很复杂.

肯定有更好的方法。

【问题讨论】:

    标签: c# .net winforms datagridview


    【解决方案1】:

    虽然我认为将长时间运行的任务放入 BackgroundWorker 并回调到 UI 以更新它是合适的,但您可以通过调用 DataGridView.Refresh() 和使用 BeginInvoke 来获得所需的行为;

    private void dataGridView1_SelectionChanged(object sender, EventArgs e)
    {
        dataGridView1.Refresh();
        if (this.Handle != null)
        {
            this.BeginInvoke((MethodInvoker)this.DoSomethingForAWhile);
        }
    }
    

    这种方法会在您的长时间运行的任务之前在 UI 线程上粘贴一条 Paint 消息,这会阻塞 UI 线程。那时,我认为尚未指示 DataGridView 自行绘制,因此您没有看到它更新。

    【讨论】:

    • 谢谢。这很好用。现在我明白了。 DataGridView 直到 事件处理程序完成后才会发布 Paint 消息,因此除非我按照您的建议强制执行,否则我的长时间运行的任务仍会在 Paint 消息之前执行。
    猜你喜欢
    • 2021-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多