You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Windows Forms:点击Timer窗体按钮后更新主窗体DataGridView指定单元格值

Hey there! Let's work through this together—since you're dealing with WinForms (given the Forms and DataGridView references), here are a couple of solid approaches to get that value from your Timer form into your main form's DataGridView and make sure it displays correctly:

推荐方案:使用事件委托(解耦设计)

This is the cleanest way because it avoids tight coupling between your Timer form and main form—great for maintainability.

Step 1: Define an event in your Timer form

First, create a custom event to broadcast when a new value is ready, plus an event args class to pass the value and target cell coordinates:

// Inside your TimerForm class
public event EventHandler<ValueUpdatedEventArgs> ValueUpdated;

// Custom event args to carry your data
public class ValueUpdatedEventArgs : EventArgs
{
    public object NewValue { get; }
    public int TargetRow { get; }
    public int TargetColumn { get; }

    public ValueUpdatedEventArgs(object newValue, int targetRow, int targetColumn)
    {
        NewValue = newValue;
        TargetRow = targetRow;
        TargetColumn = targetColumn;
    }
}

Step 2: Trigger the event when you get the value

When your Timer form captures the value you want to send, fire the event:

// Example: In your Timer's Tick event or value-retrieval method
private void Timer1_Tick(object sender, EventArgs e)
{
    // Replace this with your actual value and target cell indices
    object newValue = 42; // Your fetched value
    int targetRow = 0;    // Specific row index
    int targetCol = 2;    // Specific column index

    // Fire the event (safe even if no subscribers)
    ValueUpdated?.Invoke(this, new ValueUpdatedEventArgs(newValue, targetRow, targetCol));
}

Step 3: Subscribe to the event in your main form

When you open the Timer form from your main form, hook up the event handler:

// Inside your MainForm's code (e.g., a button click that opens TimerForm)
private void OpenTimerFormBtn_Click(object sender, EventArgs e)
{
    var timerForm = new TimerForm();
    // Subscribe to the value update event
    timerForm.ValueUpdated += TimerForm_OnValueUpdated;
    timerForm.Show(); // Use ShowDialog() if you want a modal form
}

Step 4: Update the DataGridView from the main form

Handle the event, making sure you're on the UI thread (critical to avoid cross-thread exceptions):

private void TimerForm_OnValueUpdated(object sender, ValueUpdatedEventArgs e)
{
    // Check if we need to switch to the UI thread
    if (dataGridView1.InvokeRequired)
    {
        // Invoke the update on the UI thread
        dataGridView1.Invoke(new Action(() => UpdateDataGridViewCell(e)));
        return;
    }

    UpdateDataGridViewCell(e);
}

private void UpdateDataGridViewCell(ValueUpdatedEventArgs e)
{
    // Validate indices to avoid out-of-bounds errors
    if (e.TargetRow >= 0 && e.TargetRow < dataGridView1.RowCount &&
        e.TargetColumn >= 0 && e.TargetColumn < dataGridView1.ColumnCount)
    {
        // Set the cell value
        dataGridView1.Rows[e.TargetRow].Cells[e.TargetColumn].Value = e.NewValue;
        
        // Force immediate refresh of the cell (usually optional, but fixes edge cases)
        dataGridView1.RefreshEdit();
    }
}
简单方案:直接引用主窗体(适合小型项目)

If you're working on a small app and don't mind tight coupling, you can pass a reference to the main form to the Timer form:

Step 1: Modify TimerForm's constructor

private readonly MainForm _mainForm;

public TimerForm(MainForm mainForm)
{
    InitializeComponent();
    _mainForm = mainForm;
}

Step 2: Add a public update method to MainForm

// Inside MainForm
public void UpdateDataGridViewCell(object newValue, int rowIndex, int colIndex)
{
    if (dataGridView1.InvokeRequired)
    {
        dataGridView1.Invoke(new Action(() => UpdateCellInternal(newValue, rowIndex, colIndex)));
        return;
    }

    UpdateCellInternal(newValue, rowIndex, colIndex);
}

private void UpdateCellInternal(object newValue, int rowIndex, int colIndex)
{
    if (rowIndex >= 0 && rowIndex < dataGridView1.RowCount &&
        colIndex >= 0 && colIndex < dataGridView1.ColumnCount)
    {
        dataGridView1.Rows[rowIndex].Cells[colIndex].Value = newValue;
        dataGridView1.RefreshEdit();
    }
}

Step 3: Call the method from TimerForm

// Inside TimerForm's value-retrieval logic
_mainForm.UpdateDataGridViewCell(newValue, targetRow, targetCol);
Key Notes
  • Cross-thread safety: Always check InvokeRequired! If you're using System.Timers.Timer, its events fire on a background thread—skipping this will throw an exception. System.Windows.Forms.Timer runs on the UI thread, but adding the check makes your code robust.
  • Data-bound grids: If your DataGridView is bound to a DataTable or other data source, update the source directly instead of the cell (e.g., yourDataTable.Rows[rowIndex]["ColumnName"] = newValue;). The grid will auto-reflect changes.
  • Index validation: Always check that your row/column indices are within bounds to avoid crashes.

内容的提问来源于stack exchange,提问作者MaxB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 12:42:39