2010-07-27 2 views
0

Я пытаюсь реализовать простую таблицу с использованием WPat datagrid. Когда пользователь вводит формулу в ячейке, двигатель вычисляет формулу и обновляет ячейку с вычисленным значением. Но большинство вычислений, которые я обрабатываю, занимают много времени, поэтому я хочу рассчитать их в других потоках.обновление wpf datagrid cell из другой темы

Я попытался реализовать это, используя событие CellEditEnding, как показано ниже. (The ItemsSource из DataGrid1 связан с 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 
} 

Когда он обновляет значение ячейки из одной и той же UI потоке, клетка обновляется со значением «X», а из другого потока, это не , Как я могу обновить ячейку со значением «X» из другого потока?

EDIT: мой код не выбрасывает InvalidOperationException bcz, я использовал Dispatcher.BeginInvoke(). Моя проблема кажется, что входное значение (формула) пользователя перезаписывает вычисленное значение, которое я хочу отобразить.

ответ

1

Вы не можете обновить GUI из другого потока. К счастью .Net обеспечивает механизм для обработки этого:

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

Например

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

Edit: К сожалению исходный код был для Windows.Forms

+0

я знаю о Dispatcher.Invoke(). Вы можете увидеть мой код. Я уже использую его, и мой код не вызывает никакого InvalidOperationException. –

+0

Извините, я пропустил это. Проблема может заключаться в закрытии анонимной функции (то есть: неправильные значения сохраняются). Вы пытались установить точку останова в конце процедуры Calc (где она обновляет значение ячейки)? – sukru

+0

Еще одна вещь, вы можете попытаться переместить вычисления r и c снаружи. – sukru

0

Посмотрите на WPF Dispatcher Class. У вас довольно много вариантов выполнения задач с потоком из Диспетчера. Просмотрите методы BeginInvoke и Invoke.

1

Использование диспетчера - не очень хорошая идея. Это может привести к тому, что ваш пользовательский интерфейс не будет реагировать, если он не правильно закодирован. Если вы планируете использовать datagrid в многопоточной настройке, вы должны использовать события для отражения обновлений. Я бы рекомендовал комбинацию ObservableCollection с INotifyPropertyChanged как лучшей альтернативой. Я опубликовал здесь шаблон:

http://www.codeproject.com/Articles/1086714/A-Template-For-Using-Datagrid-in-Monitoring-UI

Смежные вопросы