从对象构造器更新WPF GUI

时间:2019-07-08 13:49:25

标签: c# wpf xaml user-interface

这是我的第一篇文章,就这样... 我有一个名为Job的类,该类连接到构造函数中数据库中的多个表,并从每个表中获取一个项目。正在通过SOAP Web服务访问该数据库。通过单击按钮创建对象。在main中创建类时,将传入搜索字符串和带有文本的自定义进度栏GUI元素。

进度条是一个自定义用户控件,并具有Update()方法来更新消息文本和进度。

我尝试了多种方法来从构造函数中获取GUI(进度条)进行更新,并发现本文(How to use WPF Background Worker)非常有帮助,但是GUI仅在整个方法完成后才进行更新

我尝试从Job类的构造函数中删除方法,并从主线程调用它们,并在两次方法调用之间更新GUI,我尝试使用分派器更新GUI,甚至将它们作为任务等待。我还尝试过直接更新自定义控件的值。尽管如此,GUI似乎只是在搜索方法完成后才更新。

是否有更好的方法来解决此问题?我在Job类的构造函数中做得太多吗?即使在创建对象之前,GUI似乎也没有更新。

private async void AddMasterJob_Click(object sender, RoutedEventArgs e)
    {
        SearchMethod();
    }
//Search method is used in multiple places.
private async void SearchMethod()
    {
        //This does not change the GUI until the whole method is complete. 
        await Task.Run(() => CurrentProgressControl.Visibility = Visibility.Visible);
        await Task.Run(() => CurrentProgressControl.BringIntoView());

        //Checks if record exists during constructor
        var tempJob = new Job(SearchBox.Text, CurrentProgressControl);
        //Only assign _masterJob if search was successful.
        if (tempJob.MasterJob != null)
        {
            //Try updating the GUI fields directly
            await Task.Run(() => CurrentProgressControl.progressBar.Value = 25);
            await Task.Run(() => CurrentProgressControl.label.Content = "Getting SubJobs");
            //Gets the subjobs and creates an array of subjob objects
            tempJob.GetSubJobs();
            //Try updating using the update method built into the custom control
            CurrentProgressControl.Update("Getting Planning Lines and Ledger Entries.", 45);
            //Get the planning lines and ledger entries
            tempJob.GetPlanningLinesandLedgerEntries();
            CurrentProgressControl.Update("Creating the Estimate Line List.", 60);
            //Combines Subjobs, Planning Lines, and Ledger Entries
            //Calls CalculateTable(_tableLines)
            tempJob.CreateEstimateLineList();
            CurrentProgressControl.Update("Separating into Labor and Material.", 75);
            //Populate _laborLines and _materialLines
            tempJob.SeparateTableLines(tempJob.TableLines);
            CurrentProgressControl.Update("Creating SubTotals.", 85);
            //Insert the subtotal Lines
            tempJob.CreateSubtotalLines(tempJob.LaborLines);
            tempJob.CreateSubtotalLines(tempJob.MaterialLines);
            CurrentProgressControl.Update("Calculating Totals.", 95);
            //Calculate the total estimate column and subtotal lines
            tempJob.CalculateTable(tempJob.MaterialLines);
            tempJob.CalculateTable(tempJob.LaborLines);

            //Calculate the totals for the whole Job
            tempJob.CalculateTotals();
            CurrentProgressControl.Update("Completed Successfully.", 100);

            _masterJob = tempJob;
            RaisePropertyChanged("MasterJob");
        }
    }

GUI将在searchMethod完成之后更新,但不是在此之前更新。搜索方法内部的某些构造方法需要花费几秒钟的时间,因此我希望GUI可以更新多次,而只能完成一次更新,即完成。

1 个答案:

答案 0 :(得分:0)

请勿通过Task.Run更新UI,而应使用它来执行并等待长时间运行的操作:

private async void AddMasterJob_Click(object sender, RoutedEventArgs e)
{
    await SearchMethod();
}

private async Task SearchMethod()
{
    CurrentProgressControl.Visibility = Visibility.Visible;
    CurrentProgressControl.BringIntoView();

    var tempJob = new Job(SearchBox.Text, CurrentProgressControl);

    if (tempJob.MasterJob != null)
    {
        CurrentProgressControl.progressBar.Value = 25;
        CurrentProgressControl.label.Content = "Getting SubJobs";

        await Task.Run(() => tempJob.GetSubJobs());

        CurrentProgressControl.Update("Getting Planning Lines and Ledger Entries.", 45);

        await Task.Run(() => tempJob.GetPlanningLinesandLedgerEntries());

        CurrentProgressControl.Update("Creating the Estimate Line List.", 60);

        await Task.Run(() => tempJob.CreateEstimateLineList());

        CurrentProgressControl.Update("Separating into Labor and Material.", 75);

        await Task.Run(() => tempJob.SeparateTableLines(tempJob.TableLines));

        CurrentProgressControl.Update("Creating SubTotals.", 85);

        await Task.Run(() =>
        {
            tempJob.CreateSubtotalLines(tempJob.LaborLines);
            tempJob.CreateSubtotalLines(tempJob.MaterialLines);
        });

        CurrentProgressControl.Update("Calculating Totals.", 95);

        await Task.Run(() =>
        {
            tempJob.CalculateTable(tempJob.MaterialLines);
            tempJob.CalculateTable(tempJob.LaborLines);
            tempJob.CalculateTotals();
        });

        CurrentProgressControl.Update("Completed Successfully.", 100);

        _masterJob = tempJob;
        RaisePropertyChanged("MasterJob");
    }
}

或者使用一个Task.Run调用并通过其Dispatcher更新UI:

private async Task SearchMethod()
{
    CurrentProgressControl.Visibility = Visibility.Visible;
    CurrentProgressControl.BringIntoView();

    var tempJob = new Job(SearchBox.Text, CurrentProgressControl);

    if (tempJob.MasterJob != null)
    {
        CurrentProgressControl.progressBar.Value = 25;
        CurrentProgressControl.label.Content = "Getting SubJobs";

        await Task.Run(() =>
        {
            tempJob.GetSubJobs());

            Dispatcher.Invoke(() => CurrentProgressControl.Update("Getting Planning Lines and Ledger Entries.", 45));

            tempJob.GetPlanningLinesandLedgerEntries();

            Dispatcher.Invoke(() => CurrentProgressControl.Update("Creating the Estimate Line List.", 60));

            tempJob.CreateEstimateLineList();

            Dispatcher.Invoke(() => CurrentProgressControl.Update("Separating into Labor and Material.", 75));

            tempJob.SeparateTableLines(tempJob.TableLines);

            Dispatcher.Invoke(() => CurrentProgressControl.Update("Creating SubTotals.", 85));

            tempJob.CreateSubtotalLines(tempJob.LaborLines);
            tempJob.CreateSubtotalLines(tempJob.MaterialLines);

            Dispatcher.Invoke(() => CurrentProgressControl.Update("Calculating Totals.", 95));

            tempJob.CalculateTable(tempJob.MaterialLines);
            tempJob.CalculateTable(tempJob.LaborLines);
            tempJob.CalculateTotals();
        });

        CurrentProgressControl.Update("Completed Successfully.", 100);

        _masterJob = tempJob;
        RaisePropertyChanged("MasterJob");
    }
}

如果可能,使作业方法异步:

private async Task SearchMethod()
{
    CurrentProgressControl.Visibility = Visibility.Visible;
    CurrentProgressControl.BringIntoView();

    var tempJob = new Job(SearchBox.Text, CurrentProgressControl);

    if (tempJob.MasterJob != null)
    {
        CurrentProgressControl.progressBar.Value = 25;
        CurrentProgressControl.label.Content = "Getting SubJobs";

        await tempJob.GetSubJobsAsync();

        CurrentProgressControl.Update("Getting Planning Lines and Ledger Entries.", 45);

        await tempJob.GetPlanningLinesandLedgerEntriesAsync();

        CurrentProgressControl.Update("Creating the Estimate Line List.", 60);

        await tempJob.CreateEstimateLineListAsync();

        CurrentProgressControl.Update("Separating into Labor and Material.", 75);

        await tempJob.SeparateTableLinesAsync(tempJob.TableLines);

        CurrentProgressControl.Update("Creating SubTotals.", 85);

        await tempJob.ob.CreateSubtotalLinesAsync(tempJob.LaborLines);
        await tempJob.CreateSubtotalLinesAsync(tempJob.MaterialLines);

        CurrentProgressControl.Update("Calculating Totals.", 95);

        await tempJob.CalculateTableAsync(tempJob.MaterialLines);
        await tempJob.CalculateTableAsync(tempJob.LaborLines);
        await tempJob.CalculateTotalsAsync();

        CurrentProgressControl.Update("Completed Successfully.", 100);

        _masterJob = tempJob;
        RaisePropertyChanged("MasterJob");
    }
}