0

AutoCAD の選択した図面ファイル内のファイル内のテキストを置き換えるために wpf UserControl を使用しています。wpf コントロールは、任意の時点で処理されたファイルの数を示すステータス (ProgressBar) を表示します。そこで、次のコードを作成しましたが、ProgressBar には進行状況がまったく表示されません。関連するコードの一部を次に示します。

XAML:

<ProgressBar HorizontalAlignment="Stretch" Name="pgrSearch" Minimum="0" Maximum="{Binding Path=ProgressBarMaximum}"
                 Value="{Binding Path=ProgressBarCurrent}" Height="20" Margin="10"  />

分離コード:

public partial class ReplaceUserControl : UserControl, INotifyPropertyChanged {
    public ReplaceUserControl() {
        InitializeComponent();
        this.DataContext = this;
    }
    ....

    private int _progressBarMaximum;
    public int ProgressBarMaximum {
        get { return _progressBarMaximum; }
        set { _progressBarMaximum = value; RaisePropertyChanged("ProgressBarMaximum"); }
    }

    private int _progressBarCurrent;
    private int ProgressBarCurrent {
        get { return _progressBarCurrent; }
        set { _progressBarCurrent = value; RaisePropertyChanged("ProgressBarCurrent"); }
    }


    private void ReplaceTextInFiles() { //Called from Button_Click Handler
        ....

        ProgressBarMaximum = filesList.Count - 1;

        SearchReplaceWorker replaceWorker = new SearchReplaceWorker(); //The Work Horse
        replaceWorker.FileProcessed += new FileProcessedEventHandler(worker_FileProcessed); //Raised by Work Horse when each file is processed

        BackgroundWorker workerThread = new BackgroundWorker(); //The Background Worker Thread
        workerThread.DoWork += (o, e) => {
            replaceWorker.ReplaceTextInFiles(SearchText, ReplaceText, filesList, ReportFolderPath, MatchCase, MatchSubstring);
        };
        workerThread.RunWorkerAsync(); //Start the Background Thread Async
    }

    void worker_FileProcessed(object sender, EventArgs e) {
        ProgressBarCurrent = ProgressBarCurrent + 1; //Update the ProgressBar status
    }

上記のコードで示されているように、ProgressBarCurrent がインクリメントされたときに、ProgressBar 自体が更新されないのはなぜですか。

編集: UI スレッドで ProgressBar 更新コードを処理するために、以下に示すように BackgroundWorker.ReportProgress() を使用するようにコードを変更しました。

UserControl の分離コード:

private void ReplaceTextInFiles() { //Called from Button_Click()
    if (!Directory.Exists(SearchFolderPath)) {
        MessageBox.Show("Invalid Directory Selected for Search");
        return;
    }

    if (!Directory.Exists(ReportFolderPath)) {
        MessageBox.Show("Invalid Directory Selected for Report File");
        return;
    }

    List<string> filesList = null;
    try {
        if (LookInSubFolders) {
            filesList = Directory.GetFiles(@SearchFolderPath, "*.dwg", SearchOption.AllDirectories).ToList();
        }
        else {
            filesList = Directory.GetFiles(@SearchFolderPath, "*.dwg", SearchOption.TopDirectoryOnly).ToList();
        }
    }
    catch (Exception ex) {
        MessageBox.Show("Error Occurred getting the files list. Contact Admin");
    }

    pgrSearch.Visibility = Visibility.Visible;
    ProgressBarMaximum = filesList.Count - 1;

    SearchReplaceWorker replaceWorker = new SearchReplaceWorker(); 

    BackgroundWorker workerThread = new BackgroundWorker(); 
    workerThread.WorkerReportsProgress = true;
    workerThread.ProgressChanged += (o, e) => { //This event handler gets called correctly.
        ProgressBarCurrent++; 
    };
    workerThread.RunWorkerCompleted += new RunWorkerCompletedEventHandler(workerThread_RunWorkerCompleted);
    workerThread.DoWork += (o, e) => {
        replaceWorker.ReplaceTextInFiles(workerThread, SearchText, ReplaceText, filesList, ReportFolderPath, MatchCase, MatchSubstring);
    };
    workerThread.RunWorkerAsync(); 
}

バックグラウンド ワーカー:

public void ReplaceTextInFiles(BackgroundWorker workerThread, string searchText, string replaceText, List<string> filesList, string reportPath,
                                      bool MatchCase, bool MatchSubstring) {
    ...
    workerThread.ReportProgress(50);
}

それでも、ProgressBar 自体は更新されません。

4

1 に答える 1

2

最初のコードでテストプロジェクトを作成しました。しばらくして、ProgressBarCurrentプロパティをprivateとして宣言していることがわかりました。公開に変更した後、それは私のために働いた。したがって、UIスレッドのプロパティを更新する必要はないようです。Dispatcher.Invoke呼び出しは、更新されたプロパティ値を読み戻すときに内部的に行われるように見えます。

于 2012-06-20T07:04:44.380 に答える