2015-08-21 2 views
2

Я делаю приложение WPF, где я использую WebClient для загрузки файла. Я хочу показать ProgressPercentage в контроллере ProgressBar. У меня есть метод в классе, где я использую WebClient для загрузки файла. Мой вопрос заключается в том, как сделать привязку ProgressBar к e.ProgressPercentage.WPF привязка данных ProgressBar

метод в классе (DownloadFile):

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:

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

'ProgressBar.Valu e = e.ProgressPercentage'? –

+0

Я не могу получить доступ к моему ProgressBar в другом классе? @ PhilippeParé –

+0

Вы можете создать четное (т. Е. «Публичное событие ProgressChangedEventHandler ProgressChanged») и поднять его каждый раз, когда запускается DownloadProgressChanged. Затем вы делаете свой контроллер progressbar подпиской на это событие. – Dietz

ответ

3

Для чистого раствора вам нужен ViewModel класс и в нем мы создаем метод StartDownload и вы можете вызвать его с помощью Command или под button мыши в вашем window.

С другой стороны, есть хороший Type по имени IProgress<T>. Он работает как информера для нас, и вы можете играть с ним, как в следующем примере;)


Внутри 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:

Теперь вы должны заполнить окно DataContext с экземпляром DownloadViewModel класса (по Xaml или Code-Behind).

Связывание ProgressValue свойство DownloadViewModel.cs класса:

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

Finnaly, писать в вашей кнопки OnClick:

if(this.DataContext!=null) 
    ((DownloadViewModel)this.DataContext).StartDownload("[email protected]__","[email protected]__"); 
else 
    MessageBox.Show("DataContext is Null!"); 

Результат:

enter image description here

+0

Благодарим вас за ответ @RAM. Я поместил свой класс Datacontext = DownloadViewModel, но индикатор прогресса не изменился? –

+0

Извините, я немного ошибся здесь: '_progressValue = d;' Должно быть: 'ProgressValue = d;'. Кроме того, для лучшей реализации я изменил «общедоступное свойство Progress» на простой «частный член» в классе «ViewModel». Теперь я изменил ответ и сам испытал его. Он работает ... – RAM

+0

Спасибо! оно работает! : D –

0

Вы должны добавить IProgress<double> progress параметр в ваш метод, когда ваш клиент хочет обновить прогресс затем вызвать progress.Report(). IProgress со стороны вашего вида/окна укажет на способ, в котором вы будете использовать MyProgressBar.Value = value или что-то еще.

Использование IProgress эффективно удаляет взаимодействие с целевым элементом управления, который будет предоставлять обновления, кроме того, он также заботится о вызове диспетчера, чтобы вы не получали обычные недопустимые ошибки перекрестных потоков.

Увидеть этот пост для примера:

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

Смежные вопросы