C# 通过访问另一个类中的backgroundWorker更新ProgressBar

C# 通过访问另一个类中的backgroundWorker更新ProgressBar,c#,wpf,progress-bar,backgroundworker,C#,Wpf,Progress Bar,Backgroundworker,我是WPF和C编程新手,并且已经习惯了OOP,我正在尝试使用最佳编程实践编写我的程序,但我已经被困了几天,我无法想出如何完成这项工作,希望有人能提供帮助 我尝试做的很简单,我有一个WPF窗口,有一个进度条和一个按钮,就是这样,在这个窗口的C#后端代码中,我有一个单击事件,从另一个文件调用另一个类中的方法,在这个类中我有一个BackgroundWorker,我一直在尝试根据BackgroundWorker更新一个进度条 我确认代码是通过在控制台中编写进度和事件来工作的,我不知道如何访问另一个类中的

我是WPF和C编程新手,并且已经习惯了OOP,我正在尝试使用最佳编程实践编写我的程序,但我已经被困了几天,我无法想出如何完成这项工作,希望有人能提供帮助

我尝试做的很简单,我有一个WPF窗口,有一个进度条和一个按钮,就是这样,在这个窗口的C#后端代码中,我有一个单击事件,从另一个文件调用另一个类中的方法,在这个类中我有一个BackgroundWorker,我一直在尝试根据BackgroundWorker更新一个进度条

我确认代码是通过在控制台中编写进度和事件来工作的,我不知道如何访问另一个类中的BackgroundWorker来更新我的xaml文件中的进度条,或者如果这不是最好的方法,我想知道什么是最好的方法

XAML:


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>