views:

57

answers:

2

I'm trying to implement a simple spreadsheet using WPF datagrid. When users input a formula in a cell, engine calculates the formula and update the cell with the calculated value. But most of calculations i handle take long time, so i want to calculate those in other threads.

I tried to implement this using CellEditEnding event like below. (the ItemsSource of dataGrid1 is bound to the DataTable dtab.)

private void dataGrid1_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e) {
    Action calc = () => {
        int r = dataGrid1.Items.IndexOf(e.Row.Item);
        int c = dataGrid1.Columns.IndexOf(e.Column);
        dtab.Rows[r].SetField(c, "X"); // a calculated value
    };            
    Action update = () => {
        if (dataGrid1.Dispatcher.CheckAccess()) calc();
        else dataGrid1.Dispatcher.BeginInvoke(calc);
    };

    //update(); // run from the same ui thread
    Task.Factory.StartNew(update); // run from a different thread
}

When it update the cell value from the same UI thread, cell is updated with value "X", but from the different thread, it is not. How can i update the cell with value "X" from a different thread?

EDIT: My code does not throw any InvalidOperationException bcz i used the Dispatcher.BeginInvoke(). My problem seems that the user input value (formula) overwrites the calculated value which i want to display.

A: 

You cannot update the GUI from another thread. Fortunately .Net provides a mechanism to handle this:

uiControl.**Dispatcher**.Invoke(delegate)

For example

dataGrid1.Dispatcher.Invoke(() => MyUpdateFunction(dataGrid1, data))

Edit: Sorry the original code was for Windows.Forms

sukru
i know about the Dispatcher.Invoke(). You can see my code. I already use it and my code does not throw any InvalidOperationException.
tk
Sorry I missed that.The issue might be with the anonymous function closure (i.e.: wrong values are stored).Did you try setting a breakpoint at the end of Calc routine (where it updates the cell value)?
sukru
One more thing, you might try moving the calculation of r and c outside.
sukru
A: 

Take a look at the WPF Dispatcher Class. You have quite a few options to perform threaded tasks from the Dispatcher. Review the BeginInvoke and Invoke methods.

Metro Smurf