Обновление WPF GUI из конструктора объектов - PullRequest
0 голосов
/ 08 июля 2019

Это мой первый пост, вот оно ... У меня есть класс с именем Job, который подключается к нескольким таблицам в базе данных в конструкторе и получает элемент из каждой таблицы. Доступ к базе данных осуществляется через веб-сервисы SOAP. Объект создается нажатием кнопки. Когда класс создается в main, в него передаются строка поиска и пользовательский элемент GUI индикатора выполнения с текстом.

Индикатор выполнения представляет собой пользовательский элемент управления и имеет метод Update () для обновления текста сообщения и хода выполнения.

Я пробовал несколько способов заставить GUI (Индикатор выполнения) обновляться из конструктора и нашел этот пост ( Как использовать WPF Background Worker ) очень полезным, однако графический интерфейс только обновление, когда весь метод завершен.

Я попытался удалить методы из конструктора класса Job и вызвать их из основного потока и обновить GUI между вызовами методов, я попытался использовать диспетчер для обновления GUI и даже ожидать их в качестве задачи. Я также попытался обновить значения пользовательского элемента управления напрямую. Тем не менее, кажется, что графический интерфейс обновляется только после завершения метода поиска.

Есть ли лучший способ сделать это? Я слишком много делаю в конструкторе класса Job? Даже до создания объекта графический интерфейс не обновляется.

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");
        }
    }

Графический интерфейс обновляется после завершения searchMethod, но не раньше. Некоторые из методов конструктора внутри метода поиска занимают несколько секунд, поэтому я ожидаю, что графический интерфейс будет обновляться несколько раз, но вместо этого будет только одно обновление, которое завершится.

1 Ответ

0 голосов
/ 08 июля 2019

Не обновляйте пользовательский интерфейс с помощью Task.Run, а используйте его для выполнения и ожидания длительных операций:

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 и обновите пользовательский интерфейс с помощью диспетчера:

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");
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...