WPF 数据绑定 ProgressBar

WPF databinding ProgressBar

我正在制作一个 WPF 应用程序,我在其中使用 WebClient 下载文件。我想在 ProgressBar 控制器中显示 ProgressPercentage。我在 class 中有一个方法,我使用 WebClient 下载文件。我的问题是如何将 ProgressBar 数据绑定到 e.ProgressPercentage.

Class 中的方法(下载文件):

public async Task DownloadProtocol(string address, string location)
{

        Uri Uri = new Uri(address);
        using (WebClient client = new WebClient())
        {
            //client.DownloadFileCompleted += new AsyncCompletedEventHandler(Completed);
            //client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(DownloadProgress);
            client.DownloadProgressChanged += (o, e) =>
            {
                Console.WriteLine(e.BytesReceived + " " + e.ProgressPercentage);
                //ProgressBar = e.ProgressPercentage???
            };

            client.DownloadFileCompleted += (o, e) =>
            {
                if (e.Cancelled == true)
                {
                    Console.WriteLine("Download has been canceled.");
                }
                else
                {

                    Console.WriteLine("Download completed!");
                }

            };

            await client.DownloadFileTaskAsync(Uri, location);
        }

}

进度条:

<ProgressBar HorizontalAlignment="Left" Height="24" Margin="130,127,0,0" VerticalAlignment="Top" Width="249"/>

你应该在你的方法中添加一个 IProgress<double> progress 参数,每当你的客户想要更新进度时调用 progress.Report()IProgress 在你的 view/window 端将指向一个方法,你将在其中实现 MyProgressBar.Value = value 或其他任何东西。

使用 IProgress 有效地删除了与将提供更新的目标控件的交互,此外它还负责调用调度程序,因此您不会遇到通常的无效跨线程调用错误。

请参阅此 post 示例:

http://blogs.msdn.com/b/dotnet/archive/2012/06/06/async-in-4-5-enabling-progress-and-cancellation-in-async-apis.aspx

对于干净的解决方案,您需要一个 ViewModel class,我们在其中创建了一个 StartDownload 方法,您可以通过 Commandbutton 点击你的 window

另一方面,有一个很好的 Type 名为 IProgress<T>。它作为我们的 informer 工作,您可以像下面的示例一样使用它 ;)


里面DownloadViewModel.cs:

public sealed class DownloadViewModel : INotifyPropertyChanged
{
    private readonly IProgress<double> _progress;
    private double _progressValue;

    public double ProgressValue
    {
        get
        {
            return _progressValue;
        }
        set
        {
            _progressValue = value;
            OnPropertyChanged();
        }
    }

    public DownloadViewModel()
    {
        _progress = new Progress<double>(ProgressValueChanged);
    }

    private void ProgressValueChanged(double d)
    {
        ProgressValue = d;
    }

    public async void StartDownload(string address, string location)
    {
        await new MyDlClass().DownloadProtocol(_progress, address, location);
    }

    //-----------------------------------------------------------------------
    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

在 MyDlClass 中。 CS

public class MyDlClass
{
    public async Task DownloadProtocol(IProgress<double> progress, string address, string location)
    {

        Uri Uri = new Uri(address);
        using (WebClient client = new WebClient())
        {
            //client.DownloadFileCompleted += new AsyncCompletedEventHandler(Completed);
            //client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(DownloadProgress);
            client.DownloadProgressChanged += (o, e) =>
            {
                Console.WriteLine(e.BytesReceived + " " + e.ProgressPercentage);
                progress.Report(e.ProgressPercentage);
            };

            client.DownloadFileCompleted += (o, e) =>
            {
                if (e.Cancelled == true)
                {
                    Console.WriteLine("Download has been canceled.");
                }
                else
                {

                    Console.WriteLine("Download completed!");
                }

            };

            await client.DownloadFileTaskAsync(Uri, location);
        }

    }
}

里面 MyWindow.Xaml.cs & MyWindow.Xaml:

现在你应该用 DownloadViewModel class 的实例填充你的 window DataContext(通过 Xaml 或代码隐藏)。

绑定到 ProgressValue 属性 of DownloadViewModel.cs class:

<ProgressBar HorizontalAlignment="Left" Height="24" Margin="130,127,0,0" VerticalAlignment="Top" Width="249"
             Minimum="0"
             Maximum="100"
             Value="{Binding Path=ProgressValue}"/>

最后,在您的按钮 OnClick 中写入:

if(this.DataContext!=null)
   ((DownloadViewModel)this.DataContext).StartDownload("__@Address__","__@Location__");
else
    MessageBox.Show("DataContext is Null!");

结果: