C# 通过访问另一个类中的backgroundWorker更新ProgressBar
我是WPF和C编程新手,并且已经习惯了OOP,我正在尝试使用最佳编程实践编写我的程序,但我已经被困了几天,我无法想出如何完成这项工作,希望有人能提供帮助 我尝试做的很简单,我有一个WPF窗口,有一个进度条和一个按钮,就是这样,在这个窗口的C#后端代码中,我有一个单击事件,从另一个文件调用另一个类中的方法,在这个类中我有一个BackgroundWorker,我一直在尝试根据BackgroundWorker更新一个进度条 我确认代码是通过在控制台中编写进度和事件来工作的,我不知道如何访问另一个类中的BackgroundWorker来更新我的xaml文件中的进度条,或者如果这不是最好的方法,我想知道什么是最好的方法 XAML:C# 通过访问另一个类中的backgroundWorker更新ProgressBar,c#,wpf,progress-bar,backgroundworker,C#,Wpf,Progress Bar,Backgroundworker,我是WPF和C编程新手,并且已经习惯了OOP,我正在尝试使用最佳编程实践编写我的程序,但我已经被困了几天,我无法想出如何完成这项工作,希望有人能提供帮助 我尝试做的很简单,我有一个WPF窗口,有一个进度条和一个按钮,就是这样,在这个窗口的C#后端代码中,我有一个单击事件,从另一个文件调用另一个类中的方法,在这个类中我有一个BackgroundWorker,我一直在尝试根据BackgroundWorker更新一个进度条 我确认代码是通过在控制台中编写进度和事件来工作的,我不知道如何访问另一个类中的
c#XAML后端:
名称空间进度条
{
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
}
私有无效btn\u开始\u单击(对象发送方,路由目标)
{
GeneralTasks GT=新的GeneralTasks();
GT.start();
}
}
}
最后是不可读的类“GeneralTasks”:
公共类GeneralTasks
{
BackgroundWorker工人=新的BackgroundWorker();
公开作废开始()
{
worker.RunWorkerCompleted+=worker\u RunWorkerCompleted;
worker.WorkerReportsProgress=true;
worker.DoWork+=worker\u DoWork;
worker.ProgressChanged+=worker\u ProgressChanged;
worker.RunWorkerAsync();
}
私有void worker\u ProgressChanged(对象发送方,ProgressChangedEventArgs e)
{
Console.WriteLine(e.ProgressPercentage+“%”+(string)e.UserState);
}
私有void worker_DoWork(对象发送方,DoWorkEventArgs e)
{
var worker=发送方作为后台工作人员;
worker.ReportProgress(0,string.Format(“完成百分比:0”);
对于(int i=0;i我会跳过GeneralTasks;它除了持有BGW并订阅其事件之外似乎什么都不做,但对它们却没有任何用处。我会将BGW放入XAML后端代码中,然后从ProgressChanged事件更新ProgressBar(连接到后端中更改PB值的方法)在DoWork处理程序(也连接到XAML后端文件)调用ReportProgress时调用
如果您想使用GeneralTasks类作为各种“执行应该在后台执行的操作的方法”的持有者,那么基本上可以将其作为一个方法集合,其签名与DoWork对齐,将其中一个指定为工作处理程序,然后启动worker来完成工作
如果你想让GT持有BGW,你需要做一些事情,比如公开一个GT在进度发生变化时可以引发的事件,或者传入一个可以连接到ProgressChanged的委托,并让XAML后端代码传递一个更改progressbar的委托(或者更简单地说,将progressbar传递给GT)
就我个人而言,我只是将所有BGW内容放在XAML后端文件中(除非它将执行大量不同的操作,在这种情况下,我会将这些内容放在GT中,并从XAML后端的DoWork处理程序调用它们)
我是WPF和C编程新手,并且已经习惯了OOP
我建议您在培训中使用更典型的现代WPF和Sharp实现
BackgroundWorker-有点过时。现在,任务和异步/等待方法用于实现异步
获取值的主要方法对于UI元素的属性是
绑定到数据上下文的属性。绑定还解决
在任何线程中异步更改源属性的问题,
这不能直接使用UI元素属性完成
为了在WPF中调用数据上下文的方法,它们被包装在
命令和一些UI元素(包括按钮、菜单项)可以
调用这些命令
由于与数据通信的主要方式是绑定,所以WPF
实际上不在Windows后面使用代码
任务的演示示例,但以更现代的方式实现
ViewModel类-用于设置数据上下文。
使用实现
使用简化的;
使用制度;
使用System.Threading.Tasks;
命名空间进程视图
{
公共类ProgressViewModel:BaseInpc
{
私人bool程序执行;
专用RelayCommand _startProgressCommand;
私人时间跨度(progressTime);;
私人双端;
私人双人房;
私有双_currentValue;
公共双RangeBegin{get=>_RangeBegin;set=>set(ref _RangeBegin,value);}
公共双RangeEnd{get=>_RangeEnd;set=>set(ref _RangeEnd,value);}
公共TimeSpan ProgressTime{get=>_ProgressTime;set=>set(ref _ProgressTime,value);}
公共双CurrentValue{get=>\u CurrentValue;私有集=>set(ref\u CurrentValue,value);}
public RelayCommand StartProgressCommand=>\u StartProgressCommand
?(_startProgressCommand=新继电器命令
(
StartProgressExecuteAsync,
()=>!i程序执行
));
私有异步void StartProgressExecuteAsync()
{
如果(isProgressExecute)
返回;
isProgressExecute=true;
StartProgressCommand.RaiseCanExecuteChanged();
双开始=范围开始;
双端=测距端;
双量程
using Simplified;
using System;
using System.Threading.Tasks;
namespace ProgressView
{
public class ProgressViewModel : BaseInpc
{
private bool isProgressExecute;
private RelayCommand _startProgressCommand;
private TimeSpan _progressTime;
private double _rangeEnd;
private double _rangeBegin;
private double _currentValue;
public double RangeBegin { get => _rangeBegin; set =>Set(ref _rangeBegin, value); }
public double RangeEnd { get => _rangeEnd; set => Set(ref _rangeEnd, value); }
public TimeSpan ProgressTime { get => _progressTime; set =>Set(ref _progressTime, value); }
public double CurrentValue { get => _currentValue; private set => Set(ref _currentValue, value); }
public RelayCommand StartProgressCommand => _startProgressCommand
?? (_startProgressCommand = new RelayCommand
(
StartProgressExecuteAsync,
() => !isProgressExecute
));
private async void StartProgressExecuteAsync()
{
if (isProgressExecute)
return;
isProgressExecute = true;
StartProgressCommand.RaiseCanExecuteChanged();
double begin = RangeBegin;
double end = RangeEnd;
double range = end - begin;
TimeSpan time = ProgressTime;
DateTime beginTime = DateTime.Now;
TimeSpan elapsed;
while ((elapsed = DateTime.Now - beginTime) < time)
{
CurrentValue = begin + range * elapsed.TotalMilliseconds / time.TotalMilliseconds;
await Task.Delay(10);
}
CurrentValue = end;
isProgressExecute = false;
StartProgressCommand.RaiseCanExecuteChanged();
}
}
}
<Window x:Class="ProgressView.ProgressWindow"
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:ProgressView"
mc:Ignorable="d"
Title="ProgressWindow" Height="450" Width="800">
<Window.DataContext>
<local:ProgressViewModel RangeBegin="0"
RangeEnd="100"
ProgressTime="0:0:10"/>
</Window.DataContext>
<UniformGrid Columns="2">
<TextBlock Text="Begin: " VerticalAlignment="Center" HorizontalAlignment="Right"/>
<TextBox Text="{Binding RangeBegin}" VerticalAlignment="Center"/>
<TextBlock Text="End: " VerticalAlignment="Center" HorizontalAlignment="Right"/>
<TextBox Text="{Binding RangeEnd}" VerticalAlignment="Center"/>
<TextBlock Text="Time: " VerticalAlignment="Center" HorizontalAlignment="Right"/>
<TextBox Text="{Binding ProgressTime}" VerticalAlignment="Center"/>
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Right">
<Run Text="Curent:"/>
<Run Text="{Binding CurrentValue, Mode=OneWay}"/>
</TextBlock>
<ProgressBar VerticalAlignment="Center" Height="20"
Minimum="{Binding RangeBegin}"
Maximum="{Binding RangeEnd}"
Value="{Binding CurrentValue, Mode=OneWay}"/>
<Button Content="Start Progress"
Command="{Binding StartProgressCommand, Mode=OneWay}"/>
</UniformGrid>
</Window>