wpf - WPF中使用绑定的异步进度条
问题描述
我在可视化 MVVM WPF 进度条时遇到问题。我的主脚本方法运行但进度条根本没有更新。我可以使用提示来获得正确的方向。在我之前的代码中,我得到了使用技巧Progress<T>
(@Jonathan Willcock),但我无法成功实现它。
(请注意,这篇文章不是重复的问题,因为上次我使用了按钮单击,但我希望它纯粹在数据绑定上运行)
问题
如何将进度条异步绑定到视图模型中调用的方法?我正在使用委托命令来调用我的方法,并且我不想使用按钮单击事件。
我在视图中的内容 - 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 中有什么
我从后台工作人员方法中知道的是它尝试异步运行它。我在这里有一个问题,我在这里添加了一个断点来检查代码是否通过'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);
}
}
}
我在视图模型中拥有的东西
在视图模型中,我使用委托命令来调用我的数据绑定方法。
这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
}
非常感谢您的帮助!
解决方案
这是 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; }
}
和视图
<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>
推荐阅读
- html - 无法在 Django 1.9 中加载 style.css
- angularjs - 通过 ASP.NET 样板中的 cookie 进行本地化
- git - 将更改发布到 packagegist 的正确方法?
- ios - Swift 从核心数据中获取图像到表视图
- python - 我在从 python 脚本进行 api 调用时生成了输出。我只需要该输出中的特定项目
- php - 在 Magento 2.2 上添加额外产品属性的正确方法
- azure - 是否有可能使用 Microsoft Azure Bot Services 创建 Java 聊天机器人?
- excel-formula - 如何通过列传播公式
- python - 在熊猫中如何基于相同的ID遍历两个数据帧
- html - 基于类而不是 id 连接到链接的锚标记