2016-08-14 21 views
1

我正在處理我的新應用程序,它已完成,但只有我有問題與BackgroundDownloader。在一個XAML創建使用此代碼我的下載操作: 這是DownloadManagerClass:BackgroundDownloader進度不會在uwp中更新C#

class DownloadManager 
{ 
    public static DispatcherTimer dt; 
    //Here is Download Manager functionallity 
    public static async Task<IReadOnlyList<DownloadOperation>> GetActiveDownloadsAsync() 
    { 
     return await BackgroundDownloader.GetCurrentDownloadsAsync(); 
    } 
    public static ToastNotification CreateFailureToast(string FileName) 
    { 
     string title = "Download Failed"; 
     string name = FileName; 
     return CreateToast(title, name); 
    } 
    public static ToastNotification CreateSuccessToast(string FileName) 
    { 
     string title = "Download Completed"; 
     string name = FileName; 
     return CreateToast(title, name); 
    } 
    private static ToastNotification CreateToast(string title, string name) 
    { 
     // Create xml template 
     XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02); 

     // Set elements 
     XmlNodeList stringElements = toastXml.GetElementsByTagName("text"); 
     IXmlNode element0 = stringElements[0]; 
     element0.AppendChild(toastXml.CreateTextNode(title)); 

     IXmlNode element1 = stringElements[1]; 
     element1.AppendChild(toastXml.CreateTextNode(name)); 

     // Create toast 
     return new ToastNotification(toastXml); 
    } 


    public static async Task CreateNewDownload(Uri Uri, string FileName) 
    { 
     var bgdl = new BackgroundDownloader(); 

     bgdl.SuccessToastNotification = CreateSuccessToast(FileName); 
     //var res = await ConvertUriToDownloadInfo(Uri); 
     StorageFile File; 
     DownloadOperation dl; 
     try 
     { 
      File = await (await KnownFolders.MusicLibrary.CreateFolderAsync("WikiSeda", CreationCollisionOption.OpenIfExists)). 
        CreateFileAsync(FileName, CreationCollisionOption.FailIfExists); 
      dl = bgdl.CreateDownload(Uri, File); 
      dl.StartAsync().AsTask(); 
      try 
      { 
       StatusBar.GetForCurrentView().ProgressIndicator.Text = "Downloading..."; 
       await StatusBar.GetForCurrentView().ProgressIndicator.ShowAsync(); 
       dt = new DispatcherTimer() { Interval = new TimeSpan(0, 0, 3) }; 
       dt.Tick += Dt_Tick; 
       dt.Start(); 
      } 
      catch { } 
     } 
     catch 
     {} 

    } 

    private static async void Dt_Tick(object sender, object e) 
    { 
     dt.Stop(); 
     dt.Interval = new TimeSpan(); 
     dt.Tick -= Dt_Tick; 
     dt = null; 
     try 
     { 
      await StatusBar.GetForCurrentView().ProgressIndicator.HideAsync(); 
     } 
     catch { } 
    } 


    public static async Task<IReadOnlyList<StorageFile>> GetDownloadedItemsList() 
    { 
     try 
     { 
      var WikiSeda = await KnownFolders.MusicLibrary.GetFolderAsync("WikiSeda"); 
      return (await WikiSeda.GetFilesAsync()); 
     } 
     catch { return null; } 
    } 

} 

之後,如果用戶到我的下載頁面看到有兩種類型的數據模板的列表。 這裏是XAML代碼:

<Page.Resources> 
    <DataTemplate x:Key="DownloadedItemTemplate"> 
     <Grid Padding="10,0"> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="Auto"/> 
       <ColumnDefinition Width="*"/> 
       <ColumnDefinition Width="Auto"/> 
      </Grid.ColumnDefinitions> 
      <Image Grid.Column="0" Source="{Binding Thumb}" MaxWidth="50" MaxHeight="50" VerticalAlignment="Center" HorizontalAlignment="Center"/> 
      <Grid Grid.Column="1" VerticalAlignment="Center" Padding="10,0"> 
       <TextBlock Text="{Binding Message}" VerticalAlignment="Center"/> 
      </Grid> 
     </Grid> 
    </DataTemplate> 
    <DataTemplate x:Key="DownloadingTemplate"> 
     <Grid Padding="10,0"> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="Auto"/> 
       <ColumnDefinition Width="*"/> 
       <ColumnDefinition Width="Auto"/> 
      </Grid.ColumnDefinitions> 
      <Image Grid.Column="0" Source="{Binding Thumb}" MaxWidth="50" MaxHeight="50" VerticalAlignment="Center" HorizontalAlignment="Center"/> 
      <Grid Grid.Column="1"> 
       <Grid.RowDefinitions> 
        <RowDefinition Height="Auto"/> 
        <RowDefinition Height="Auto"/> 
       </Grid.RowDefinitions> 
       <TextBlock Text="{Binding Message}" FontSize="15" Grid.Row="0"/> 
       <ProgressBar Value="{Binding Percent, UpdateSourceTrigger=PropertyChanged}" Grid.Row="1" Minimum="0" Maximum="100"/> 
      </Grid> 
      <Grid Grid.Column="2" VerticalAlignment="Center"> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition Width="*"/> 
       </Grid.ColumnDefinitions> 
       <Button Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="" Grid.Column="0" Click="CancelDLBTN" Tag="{Binding GUID}"/> 
      </Grid> 
     </Grid> 
    </DataTemplate> 
    <local:MessageDataTemplateSelecotr x:Key="MessageDataTemplateSelecotr" 
            DownloadedItemTemplate="{StaticResource DownloadedItemTemplate}" 
            DownloadingTemplate="{StaticResource DownloadingTemplate}"/> 
</Page.Resources> 

<Grid Background="{ThemeResource SystemControlForegroundChromeMediumBrush}"> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="*"/> 
    </Grid.RowDefinitions> 
    <ListView Grid.Row="0" ItemTemplateSelector="{StaticResource MessageDataTemplateSelecotr}" ItemsSource="{x:Bind listViewCollection}" ItemContainerStyle="{StaticResource ListViewContainerStrecher}" 
      SelectionMode="None" IsItemClickEnabled="True" ItemClick="ListView_ItemClick"/> 
</Grid> 

,這裏是C#代碼:

public class MessageDataTemplateSelecotr : DataTemplateSelector 
{ 
    public DataTemplate DownloadedItemTemplate { get; set; } 
    public DataTemplate DownloadingTemplate { get; set; } 
    protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) 
    { 
     var message = item as MessageModel; 
     if (message.MessageType.ToString() == "Downloaded") 
      return DownloadedItemTemplate; 
     else 
      return DownloadingTemplate; 
    } 
} 

public class MessageModel : INotifyPropertyChanged 
{ 
    private Enum _MessageType { get; set; } 
    private BitmapImage _Thumb { get; set; } 
    private bool _IsIndeterminate { get; set; } 
    private Guid _GUID { get; set; } 
    private double _Percent { get; set; } 
    public string Message { get; set; } 

    public Enum MessageType 
    { 
     get 
     { 
      return _MessageType; 
     } 
     set 
     { 
      if (value != _MessageType) 
      { 
       _MessageType = value; 
       OnPropertyChanged("MessageType"); 
      } 
     } 
    } 

    public BitmapImage Thumb 
    { 
     get 
     { 
      return _Thumb; 
     } 
     set 
     { 
      if (value != _Thumb) 
      { 
       _Thumb = value; 
      } 
     } 
    } 

    public bool IsIndeterminate 
    { 
     get 
     { 
      return _IsIndeterminate; 
     } 
     set 
     { 
      if (value != _IsIndeterminate) 
      { 
       _IsIndeterminate = value; 
      } 
     } 
    } 

    public double Percent 
    { 
     get 
     { 
      return _Percent; 
     } 
     set 
     { 
      if (value != _Percent) 
      { 
       _Percent = value; 
       OnPropertyChanged("Percent"); 
      } 
     } 
    } 

    public Guid GUID 
    { 
     get 
     { 
      return _GUID; 
     } 
     set 
     { 
      if (value != _GUID) 
      { 
       _GUID = value; 
      } 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    private void OnPropertyChanged(string propertyName) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler == null) return; 
     handler(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

/// <summary> 
/// An empty page that can be used on its own or navigated to within a Frame. 
/// </summary> 
public sealed partial class PageDLs : Page 
{ 
    List<Task> tasks = new List<Task>(); 
    public static CancellationTokenSource cts = new CancellationTokenSource(); 
    ObservableCollection<MessageModel> listViewCollection = new ObservableCollection<MessageModel>(); 
    private enum _MessageType 
    { 
     Downloaded, 
     Downloading 
    } 
    protected override async void OnNavigatedTo(NavigationEventArgs e) 
    { 
     var dls = await DownloadManager.GetDownloadedItemsList(); 
     if (dls == null || dls.Count == 0) return; 
     var d1 = dls.OrderByDescending(p => p.DateCreated); 
     foreach (var item in d1) 
     { 
      var bmp = (await item.GetScaledImageAsThumbnailAsync(ThumbnailMode.MusicView)).AsStreamForWrite().AsRandomAccessStream(); 
      var bmpi = new BitmapImage(); 
      bmpi.SetSource(bmp); 
      listViewCollection.Add(new MessageModel() 
      { 
       Message = item.Name, 
       MessageType = _MessageType.Downloaded, 
       Thumb = bmpi 
      }); 
     } 
     DetectActiveDownloads(); 
    } 

    async void DetectActiveDownloads() 
    { 
     var dls = await DownloadManager.GetActiveDownloadsAsync(); 
     if (dls.Count == 0) return; 
     foreach (var dl in dls) 
     { 
      tasks.Add(HandleDownloadAsync(dl, false)); 
      double p = 0; 
      if (dl.Progress.TotalBytesToReceive > 0 && dl.Progress.BytesReceived >= 0) 
       p = dl.Progress.BytesReceived/dl.Progress.TotalBytesToReceive * 100; 
      listViewCollection.Add(new MessageModel() 
      { 
       Message = dl.ResultFile.Name, 
       MessageType = _MessageType.Downloading, 
       GUID = dl.Guid, 
       Percent = p 
      }); 

     } 
     await Task.WhenAll(tasks); 
    } 
    private async Task HandleDownloadAsync(DownloadOperation download, bool start) 
    { 
     try 
     { 
      Progress<DownloadOperation> progressCallback = new Progress<DownloadOperation>(ProgressCallback); 
      if (start) 
      { 
       // Start the download and attach a progress handler. 
       await download.StartAsync().AsTask(cts.Token, progressCallback); 
      } 
      else 
      { 
       // The download was already running when the application started, re-attach the progress handler. 
       await download.AttachAsync().AsTask(cts.Token, progressCallback); 
      } 
      //progressCallback.ProgressChanged += ProgressCallback_ProgressChanged; 
      ResponseInformation response = download.GetResponseInformation(); 

      // GetResponseInformation() returns null for non-HTTP transfers (e.g., FTP). 
      string statusCode = response != null ? response.StatusCode.ToString() : String.Empty; 
      foreach (MessageModel item in listViewCollection) 
      { 
       if (item.GUID == download.Guid) 
       { 
        if (download.Progress.TotalBytesToReceive > 0 && download.Progress.BytesReceived >= 0) 
         item.Percent = download.Progress.BytesReceived/download.Progress.TotalBytesToReceive * 100; 
       } 
      } 
      //LogStatus(
      // String.Format(
      //  CultureInfo.CurrentCulture, 
      //  "Completed: {0}, Status Code: {1}", 
      //  download.Guid, 
      //  statusCode), 
      // NotifyType.StatusMessage); 
     } 
     catch (TaskCanceledException) 
     { 
      //LogStatus("Canceled: " + download.Guid, NotifyType.StatusMessage); 
     } 
     catch (Exception ex) 
     { 
      //if (!IsExceptionHandled("Execution error", ex, download)) 
      //{ 
      // throw; 
      //} 
     } 
     finally 
     { 

     } 
    } 
    private void ProgressCallback_ProgressChanged(object sender, DownloadOperation obj) 
    { 
     MessageModel DLItem = null; 
     foreach (var item in listViewCollection) 
     { 
      if (((MessageModel)item).GUID == obj.Guid) DLItem = (MessageModel)item; 

     } 
     if (obj.Progress.TotalBytesToReceive > 0 && obj.Progress.BytesReceived >= 0) 
      DLItem.Percent = obj.Progress.BytesReceived/obj.Progress.TotalBytesToReceive * 100; 
     if (DLItem.Percent == 100) 
     { 
      DLItem.MessageType = _MessageType.Downloaded; 
      listViewCollection.Remove(DLItem); 
     } 
     //progress = obj.Progress.BytesReceived * 100/obj.Progress.TotalBytesToReceive; 
     //if (progress > 0) 
     //{ 
     // //txtProgress.Text = string.Format("Downloading your file.... {0}%", progress); 
     // //pbDownloading.Value = progress; // passing progress bar value 
     //} 

    } 
    private void ProgressCallback(DownloadOperation obj) 
    { 
     MessageModel DLItem = null; 
     foreach (var item in listViewCollection) 
     { 
      if (((MessageModel)item).GUID == obj.Guid) DLItem = (MessageModel)item; 

     } 

     if (obj.Progress.TotalBytesToReceive > 0 && obj.Progress.BytesReceived >= 0) 
      DLItem.Percent = obj.Progress.BytesReceived/obj.Progress.TotalBytesToReceive * 100; 
     if (DLItem.Percent == 100) 
     { 
      DLItem.MessageType = _MessageType.Downloaded; 
      listViewCollection.Remove(DLItem); 
     } 
     //progress = obj.Progress.BytesReceived * 100/obj.Progress.TotalBytesToReceive; 
     //if (progress > 0) 
     //{ 
     // //txtProgress.Text = string.Format("Downloading your file.... {0}%", progress); 
     // //pbDownloading.Value = progress; // passing progress bar value 
     //} 

    } 

} 

所以我不知道的是,爲什麼我的進度條不附加下載後的工作,我試着用計時器,它完美的作品。 謝謝

+0

沒有人知道? :( – Ali

+0

什麼是你的'DownloadManager'? –

+0

DownloadManager是一個類,我把類的重要部分發布到我的代碼的第一部分開頭:public static DispatcherTimer dt; public static ToastNotification CreateFailureToast(string FileName) – Ali

回答

2

發現你的問題。在你ProgressCallback方法,你計算Percent這樣的:

DLItem.Percent = obj.Progress.BytesReceived/obj.Progress.TotalBytesToReceive * 100; 

問題是,obj.Progress.BytesReceived在實時操作的同時會更新,如果我們直接使用它進行計算,結果將始終爲0,直到下載操作關閉,結果將爲100,並且您在Percent == 100時刪除該項目,因此我們無法看到ProgressBar的更新。因此,我們需要做一個本地副本,以便我們計算Percent,你可以修改你ProgressCallback方法是這樣的:

private void ProgressCallback(DownloadOperation obj) 
{ 
    MessageModel DLItem = listViewCollection.First(p => p.GUID == obj.Guid); 
    if (obj.Progress.TotalBytesToReceive > 0) 
    { 
     double br = obj.Progress.BytesReceived; 
     var result = br/obj.Progress.TotalBytesToReceive * 100; 
     DLItem.Percent = result; 
    } 

    if (DLItem.Percent == 100) 
    { 
     DLItem.MessageType = _MessageType.Downloaded; 
     listViewCollection.Remove(DLItem); 
    } 
} 
+0

謝謝你,它的作品:)真的,你的答案是有益的 – Ali