Asyn c индикатор выполнения в WPF с использованием привязки - PullRequest
0 голосов
/ 19 февраля 2020

У меня проблема с визуализацией индикатора выполнения MVVM WPF. Мои методы для основного сценария выполняются, но индикатор выполнения вообще не обновляется. Я мог бы использовать советы по правильному направлению. В моих предыдущих кодах мне давали советы по использованию Progress<T> ( от @Jonathan Willcock ), но я не смог реализовать его успешно.

(Обратите внимание, что этот пост это не повторяющийся вопрос, потому что в прошлый раз я использовал нажатие кнопки, но я хочу, чтобы он просто запускался при привязке данных)

Вопрос

Как мне асинхронно привязывать индикатор выполнения к методу, который вызывается в моих моделях представления? Я использую команду Delegate для вызова моих методов, и я не хочу использовать событие нажатия кнопки.

Что я имею в виду - XAML

У меня есть два Основные функции здесь, индикатор выполнения и кнопка. Кнопка запускает вызов метода успешно, но индикатор выполнения не загружается.

    <ProgressBar Name="pbStatus"
                         Minimum="0"
                         Value="{Binding PrgBarVal, Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"
                         Maximum="100"
                         Height="20"/>
    <Button x:Name = "ApplyButton" Margin="0 1 0 1" Content ="Run software" Command="{Binding RunCalcBtn, Mode=TwoWay}"/>

Что у меня есть в XAML.cs

Что я знаю из Фоновый рабочий метод заключается в том, что он пытается запустить его asyn c. У меня есть проблема здесь, я добавил точку останова, чтобы проверить, выполняется ли код через метод Window_ContentRendered, но это не так.

    public partial class UserInterface: UserControl
    {
        public UserInterface()
        {
            InitializeComponent();
        }
        private void Window_ContentRendered(object sender, EventArgs e)
        {
            BackgroundWorker worker = new BackgroundWorker();
            worker.WorkerReportsProgress = true;
            worker.DoWork += worker_DoWork; //Do I need a worker.ProgressChanged here?
            worker.RunWorkerAsync();
        }
        thenamespace.ViewModel.SelectedViewModel get = new thenamespace.ViewModel.SelectedViewModel ();
        void worker_DoWork(object sender, DoWorkEventArgs e)
        {

            for (int i = Convert.ToInt32(get.PrgBarVal); i < 100; i++)
            {
                (sender as BackgroundWorker).ReportProgress(i);
            }
        }
    }

То, что у меня есть в View Model

В модели представления я использую команду делегата для вызова моих методов привязки данных.

public SelectedViewModel() - это место, где вызывается метод Run(). В методе Run() функции там работают правильно и корректно обновляют значение PrgBarVal. Однако это не обновляет индикатор выполнения вообще.

    public class SelectedViewModel : ModelView, INotifyPropertyChanged
    {
        public ModelView modelView { get; set; }

        private DelegateCommand _runCalcBtn;
        public DelegateCommand RunCalcBtn
        {
            get { return _runCalcBtn; }
            set
            {
                _runCalcBtn = value;
                SetPropertyChanged("RunCalcBtn"); //Same as RaisedPropertyChanged
            }
        }
        public SelectedViewModel()
        {
            modelView = new ModelView();
            RunCalcBtn = new DelegateCommand(Run);
        }

        private int _prgBarVal;
        public int PrgBarVal
        {
            get { return _prgBarVal; }
            set
            {
                _prgBarVal = value;
                OnPropertyChanged("PrgBarVal"); //Same as RaisedPropertyChanged
            }
        }

        //Main Function
        private async void Run()
        {

            MethodToWork(); //Function that calls other methods to run 
        }

Большое спасибо за вашу помощь!

1 Ответ

0 голосов
/ 19 февраля 2020

Вот ViewModel (используется NuGet ReactiveUI.WPF )

public class MainViewModel : ReactiveObject
{
    private int _workProgress;

    public MainViewModel()
    {
        IProgress<int> progress = new Progress<int>( e => WorkProgress = e );
        StartWork = ReactiveCommand.CreateFromTask( () => ExecuteStartWorkAsync( progress ) );

    }

    private async Task ExecuteStartWorkAsync( IProgress<int> progress )
    {
        progress.Report( 0 );
        for ( int i = 0; i < 1000; i++ )
        {
            await Task.Delay( 10 ).ConfigureAwait( false );
            progress.Report( (int)Math.Floor( i / 1000.0 * 100.0 ) );
        }
    }


    public int WorkProgress { get => _workProgress; private set => this.RaiseAndSetIfChanged( ref _workProgress, value ); }
    public ICommand StartWork { get; }
}

и View

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.DataContext>
        <local:MainViewModel/>
    </Window.DataContext>
    <Grid>
        <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
            <Button Content="Start work" Command="{Binding StartWork}" Width="80"/>
            <ProgressBar Value="{Binding WorkProgress,Mode=OneWay}" Width="120"/>
        </StackPanel>
    </Grid>
</Window>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...