簡體   English   中英

WPF-Datagrid綁定:INotifyPropertyChanged和BackgroundWorker沒有UI更新

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM