Обновление метки / текстового блока из асинхронного метода - PullRequest
0 голосов
/ 31 октября 2019

У меня странная проблема при попытке обновить мой интерфейс. Я использую IProgress, чтобы сообщить о состоянии моего асинхронного метода, который должен обновить метку в моем представлении. Происходит то, что асинхронный метод запускается, и метка обновляется только после завершения асинхронного метода. Я ожидаю, что метка будет обновляться несколько раз во время работы асинхронного метода.

Во время тестирования я заметил, что если я использую свойство Title окна вместо метки, чтобы показать прогресс асинхронного метода, тоэто работает точно так, как ожидалось. Я делаю это, привязывая свойство LblLoading к заголовку моего представления. Существует только проблема обновления метки или текстового блока во время работы асинхронного метода. Кто-нибудь может объяснить, почему это происходит, и как я могу это решить?

Я использую MVVM и Prism. Асинхронная работа начинается нажатием кнопки, которая запускает InitStartup(). Вот мой рабочий класс, который выполняет всю асинхронную работу:

public class Worker
{
    private string _status;

    public async Task DoWork(IProgress<string> progress)
    {
        for (int i = 0; i < 10000; i++)
        {
            Status = "Test" + i;
            progress.Report(Status);
        }
    }
}

Просмотр модели:

public class MainWindowViewModel : BindableBase
{
    public MainWindowViewModel()
    {
        StartCommand = new DelegateCommand(InitStartup);
    }

    public DelegateCommand StartCommand { get; set; }

    private string _lblLoading = "TEST"; 
    public string LblLoading
    {
        get { return _lblLoading; }
        set { SetProperty(ref _lblLoading, value); }
    }

    private void InitStartup()
    {
        Progress<string> progress = new Progress<string>();
        progress.ProgressChanged += UpdateProgress;

        var startup = new Worker();

        Task.Run(() => startup.DoWork(progress));
    }

    private void UpdateProgress(object sender, string status)
    {
        LblLoading = status;
    }
}

Просмотр:

<Window x:Class="AsyncProgressTest.Views.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:prism="http://prismlibrary.com/"
    prism:ViewModelLocator.AutoWireViewModel="True"
    Title="{Binding LblLoading}" Height="350" Width="525">
<Grid>
    <ContentControl prism:RegionManager.RegionName="ContentRegion" />
    <StackPanel>
        <Label Content="{Binding LblLoading}"/>
        <Button Content="Start" Command="{Binding StartCommand}"/>
    </StackPanel>
</Grid>

1 Ответ

0 голосов
/ 09 ноября 2019

1) Я думаю, это должно выглядеть так:

public class Worker
{
    public string Status { get; set; }

    public async Task DoWork(IProgress<string> progress)
    {
        for (int i = 0; i < 10000; i++)
        {
            Status = "Test" + i;
            progress.Report(Status);
            await Task.Delay(100);
        }
    }
}

2) Вы должны убедиться, что ваш MainWindowViewModel был создан. Я не понял, что вы пытаетесь сделать в этом коде, но с исправлениями этот код работает нормально.

Ваша проблема была в вашем методе DoWork. Это было сделано синхронно.

...