[英]WPF - Datagrid Binding: INotifyPropertyChanged and BackgroundWorker no UI-Update
我在View中使用了DataGrid,它綁定到ViewModel實例的DataTable。
ViewModel線程中DataTable的每次更改都會通知該視圖,並且該視圖是最新的。 所以這很好。 但是,如果我使用backgroundworker編輯DataTable的數據並在RunWorkerCompleted Event中進行通知,則視圖將不會更新。
我已經嘗試在相應的Dispatcher中引發PropertyChange事件,但是沒有任何更改。
因此,我檢查了ThreadId,所有代碼將在正確的線程中執行。 我的ViewModel:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;
namespace BackgroundWorker_vs_INotifyPropertyChange
{
class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
BackgroundWorker worker;
#region Properties
private DataTable data = new DataTable();
public DataTable Data
{
get
{
return data;
}
}
#endregion
#region Commands
ButtonCommand btnCommand;
public ICommand btnExecuteClick
{
get
{
return btnCommand;
}
}
#endregion
public ViewModel()
{
Debug.WriteLine("ViewModel_" + Thread.CurrentThread.ManagedThreadId);
// Default data for datatable
data.Columns.Add("Firstname");
data.Columns.Add("Lastname");
// -- Sample data
data.Rows.Add("Andreas", "Anderson");
// Commands
btnCommand = new ButtonCommand(worker_Start);
// BackgroundWorker
worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.WorkerSupportsCancellation = true;
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.ProgressChanged +=
new ProgressChangedEventHandler(worker_ProgressChanged);
worker.RunWorkerCompleted +=
new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
}
private void worker_Start()
{
worker.RunWorkerAsync();
}
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
Debug.WriteLine("worker_" + Thread.CurrentThread.ManagedThreadId);
// Process some work like filling the aDataTable with new data
// ...
int percentFinished = 0;
while (!worker.CancellationPending && percentFinished < 100)
{
percentFinished++;
worker.ReportProgress(percentFinished);
System.Threading.Thread.Sleep(50);
data.Rows.Add(percentFinished.ToString(), percentFinished.ToString());
}
e.Result = percentFinished;
}
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
}
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{// Worker finished
// Notify the PropertyChanged Listener the change of ProgressStateOfWork Property
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
new Action(() =>
{
this.RaisePropertyChanged("Data");
Debug.WriteLine("Dispatcher_" + Thread.CurrentThread.ManagedThreadId);
//PropertyChanged(this, new PropertyChangedEventArgs("Data"));
}
));
MessageBox.Show("Completed");
}
protected void RaisePropertyChanged(string s)
{
Debug.WriteLine("RaisePropertyChanged_" + Thread.CurrentThread.ManagedThreadId);
var temp = PropertyChanged;
if (temp != null)
{
temp(this, new PropertyChangedEventArgs(s));
}
}
}
}
我的視圖的資源
<Window.Resources>
<local:ViewModel x:Key="aViewModel"></local:ViewModel>
</Window.Resources>
綁定到DataTable:
<DataGrid x:Name="dataGrid"
ItemsSource="{Binding Data,Source={StaticResource aViewModel}}" />
該按鈕僅執行線程工作程序。
按照@Peter的建議使用ObservableColletion for Data並修改代碼
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
new Action(() =>
{
Data.Rows.Add(percentFinished.ToString(), percentFinished.ToString());
}
));
希望這有效!!
將窗口的DataContext
屬性設置為視圖模型的實例:
<Window.DataContext>
<local:ViewModel />
</Window.DataContext>
...
<DataGrid x:Name="dataGrid" ItemsSource="{Binding Data}" />
然后,只要為視圖模型的Data
屬性引發PropertyChanged
事件,就應該更新DataGrid
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.