此页面有用吗?
您对此内容的反馈非常重要。 请告诉我们您的想法。
更多反馈?
1500 个剩余字符
导出 (0) 打印
全部展开
信息
您所需的主题如下所示。但此主题未包含在此库中。

如何实现 Windows Phone 8 的后台文件传输

2014/6/18

适用于:Windows Phone 8 和 Windows Phone Silverlight 8.1 | Windows Phone OS 7.1

 

本主题将带您完成创建一个简单的应用,该应用使用 BackgroundTransferService 来启动和监视后台文件传输。在此示例中,您将创建两个页面。第一个页面将列出所有应用当前后台文件传输的状态并允许用户取消任何活动的传输,这两者都是使用后台传输的所有应用的要求。第二个页面将允许用户向队列中添加新的后台传输。应用需要允许用户启动后台传输,如提供“开始下载”按钮。否则,应用必须警告用户正在代表用户启动传输。该页面还将允许用户限制新的后台传输仅在设备具有 Wi-Fi 连接时发生。这不是必须的,但强烈建议这样做,尤其是传输的文件比较大时。

若要创建后台文件传输,您将使用 BackgroundTransferRequest 对象代表文件传输。除了其他可配置的设置之外,该对象的属性还允许您指定要下载或上传的文件以及传输的目标路径和传输方法。BackgroundTransferRequest 传递给 BackgroundTransferService 对象的 Add 方法来启动传输。还可以使用 BackgroundTransferService 对象检索 BackgroundTransferRequest 对象,该对象表示当前已为您的应用注册的传输。可以使用这些对象来确定活动传输的当前状态。

本主题包括以下部分。

 

在此示例中,您将创建的第一个页面列出当前已为该应用注册的所有后台传输。该页面将使用将数据绑定到 BackgroundTransferRequest 对象列表的 ListBox 控件。

创建文件传输列表页面的步骤

  1. 在 Visual Studio 中创建新的 Windows Phone 应用  项目。此模板在“Windows Phone”类别中。

  2. 创建传输列表页面的第一步是采用 XAML 创建用户界面。由于创建外观美观的 UI 所需的 XAML 代码非常多,因此首先提供 XAML 代码,然后再突出显示重要的元素。有关使用控件的详细信息,请参见 Windows Phone 8 的控件

    将以下代码粘贴到您项目的 MainPage.xaml 文件中。该代码应粘贴在名为“ContentPanel”的 Grid 元素中。

    <TextBlock Text="you have no transfers registered" Name="EmptyTextBlock" Visibility="Collapsed"/>
      <ListBox Name="TransferListBox">
        <ListBox.ItemTemplate>
          <DataTemplate>
            <Grid Background="Transparent" Margin="0,0,0,30">
              <Grid.ColumnDefinitions>
                <ColumnDefinition Width="380"/>
                <ColumnDefinition Width="50"/>
              </Grid.ColumnDefinitions>
            <Grid Grid.Column="0">
    
            <StackPanel Orientation="Vertical">
              <TextBlock Text="{Binding Tag}"  Foreground="{StaticResource PhoneAccentBrush}" FontWeight="Bold"/>
              <StackPanel Orientation="Horizontal">
                <TextBlock Text="status: "/>
                <TextBlock Text="{Binding TransferStatus}" HorizontalAlignment="Right"/>
              </StackPanel>
              <StackPanel Orientation="Horizontal">
                <TextBlock Text="bytes received: "/>
                <TextBlock Text="{Binding BytesReceived}" HorizontalAlignment="Right"/>
              </StackPanel>
              <StackPanel Orientation="Horizontal">
                <TextBlock Text="total bytes: "/>
                <TextBlock Text="{Binding TotalBytesToReceive}" HorizontalAlignment="Right"/>
              </StackPanel>
            </StackPanel>
    
            </Grid>
            <Grid Grid.Column="1">
              <Button Tag="{Binding RequestId}" Click="CancelButton_Click" Content="X" BorderBrush="Red" Background="Red" Foreground="{StaticResource PhoneBackgroundBrush}" VerticalAlignment="Top" BorderThickness="0" Width="50" Padding="0,0,0,0"></Button>
            </Grid>
          </Grid>
        </DataTemplate>
      </ListBox.ItemTemplate>
    </ListBox>
    
    
    

    查看您粘贴的代码并注意以下元素:

    1. 第一个 TextBlock 控件用于在没有后台传输显示时向用户显示消息。C# 代码隐藏页面在列表中没有项时将该控件的 Visibility 属性切换为 Visible,在列表中有要显示的项时切换为 Collapsed

    2. ListBox 元素定义将列出所有后台传输及其关联数据的控件。其余 XAML 代码实际上并不向列表中添加项。而是包含一个告知 ListBox 如何显示绑定到它的数据的 DataTemplateListBox 名称“TransferListBox”将用于在 C# 代码隐藏页面中引用该控件。

    3. GridStackPanel 元素是用于组织其他控件布局的容器控件。

    4. StackPanel 控件中的 TextBlock 元素显示 BackgroundTransferRequest 类中的属性值。例如,TransferStatus 属性指示传输是正在等待、正在传输还是已完成。BytesReceived 属性告知您传输已接收的字节数。Tag 属性允许您将自定义数据附加到传输请求。在此示例中,使用 Tag 属性传递下载的友好名称。语法 {Binding RecurrenceType} 将每个控件的 Text 属性映射到指定的属性名称。包含其他 TextBlock 控件是为了为每个值提供一个标签。

    5. 最后,添加了一个 Button 以允许用户删除后台传输请求。该功能是使用后台传输的所有应用所必需的。BackgroundTransferRequestRequestId 属性用于唯一标识每个传输请求。该值绑定到 ButtonTag 属性,以便该按钮的 Click 事件处理程序 RemoveButton_Click 可以确定要删除的传输。稍后会将该处理程序添加到 C# 代码隐藏页面。

  3. 需要添加到 MainPage.xaml 的最后一项为 ApplicationBarApplicationBar 将拥有一个 ApplicationBarIconButton,用户可以通过单击该按钮转到用于添加新传输的页面。使用另一个按钮允许用户从列表中删除所有已完成的传输。将以下代码粘贴到模板中包含的已注释掉的示例 ApplicationBar 代码上。确保正确替换注释以便此代码不会被注释掉。

    <phone:PhoneApplicationPage.ApplicationBar>
      <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
        <shell:ApplicationBarIconButton IconUri="/Images/add.png" Text="Add" Click="AddBackgroundTransferButton_Click"/>
        <shell:ApplicationBarIconButton IconUri="/Images/remove.png" Text="Cancel All" Click="CancelAllButton_Click"/>
      </shell:ApplicationBar>
        </phone:PhoneApplicationPage.ApplicationBar>
    
    
  4. 接下来要修改 MainPage.xaml.cs 中的代码。首先,需要添加 using 指令来纳入包含 BackgroundTransferRequest 类的命名空间。该应用将删除独立存储中已完成的传输文件,因此还需要 System.IO.IsolatedStorage 命名空间。

    using Microsoft.Phone.BackgroundTransfer;
    using System.IO.IsolatedStorage;   
    
    
  5. 接下来,添加一个类型为 IEnumerable<BackgroundTransferRequest> 的类变量。变量类型的“<BackgroundTransferRequest>”部分指示 IEnumerable 对象将包含 BackgroundTransferRequest 对象。

    public partial class MainPage : PhoneApplicationPage
    {
      IEnumerable<BackgroundTransferRequest> transferRequests;
    
    
  6. 有时,后台传输将处于挂起状态,正在等待某个条件以进行更改。例如,可以将传输配置为仅当设备具有 Wi-Fi 连接时继续。当用户导航到传输状态页面时,该应用将警告用户传输正在挂起。在 transferRequests 声明下面声明以下四个布尔变量。

      // Booleans for tracking if any transfers are waiting for user
      // action. 
      bool WaitingForExternalPower;
      bool WaitingForExternalPowerDueToBatterySaverMode;
      bool WaitingForNonVoiceBlockingNetwork;
      bool WaitingForWiFi;
    
    
  7. 创建一个名为 UpdateRequestsList 的方法。该方法使用 BackgroundTransferService 类的 Requests 属性检索当前已为该应用注册的传输请求列表。该属性返回新 BackgroundTransferRequest 对象的列表。由于对象是新的,因此请确保针对任何现有对象引用调用 Dispose 以避免内存泄露。

    private void UpdateRequestsList()
    {
      // The Requests property returns new references, so make sure that
      // you dispose of the old references to avoid memory leaks.
      if (transferRequests != null)
      {
        foreach (var request in transferRequests)
        {
          request.Dispose();
        }
      }
      transferRequests = BackgroundTransferService.Requests;
    }
    
    
  8. 创建一个名为 UpdateUI 的方法。该方法使用刚刚定义的 UpdateRequestsList 方法获取已为该应用向 BackgroundTransferService 注册的 BackgroundTransferRequest 对象。ListBoxItemsSource 属性设置为包含传输列表的 IEnumerable 类变量。这将强制 ListBox 自行更新。最后,如果 ListBox 包含一个或多个项,则会将通知用户没有注册传输的文本块折叠,否则会使其可见。 将以下方法定义粘贴到 MainPage 类定义中。

    private void UpdateUI()
    {
      // Update the list of transfer requests
      UpdateRequestsList();       
    
      // Update the TransferListBox with the list of transfer requests.
      TransferListBox.ItemsSource = transferRequests;
    
      // If there are 1 or more transfers, hide the "no transfers"
      // TextBlock. IF there are zero transfers, show the TextBlock.
      if (TransferListBox.Items.Count > 0)
      {
        EmptyTextBlock.Visibility = Visibility.Collapsed;
      }
      else
      {
        EmptyTextBlock.Visibility = Visibility.Visible;
      }          
    
    }
    
    
  9. 重写页面的 PhoneApplicationPage 基类的 OnNavigatedTo(NavigationEventArgs) 方法。只要用户导航到该页面(包括应用启动并第一次显示该页面时)就调用该方法。在该方法中,使用布尔值监视挂起的任何传输是否设置为 false。接下来,将调用将在后面的步骤中定义的帮助器方法 InitialTransferStatusCheck。在该方法的结尾处,调用 UpdateUI 以向用户显示当前传输状态。

    protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
    {
      // Reset all of the user action Booleans on page load.
      WaitingForExternalPower = false;
      WaitingForExternalPowerDueToBatterySaverMode = false;
      WaitingForNonVoiceBlockingNetwork = false;
      WaitingForWiFi = false;
    
      // When the page loads, refresh the list of file transfers.
      InitialTransferStatusCheck();
      UpdateUI();
    }   
    
    
  10. 创建 InitialTransferStatusCheck 帮助器方法。首先,调用 UpdateRequestsList 帮助器方法以获取当前的传输请求列表。然后,对于列表中的每个 BackgroundTransferRequest 对象,为 TransferStatusChangedTransferProgressChanged 事件分配一个处理程序。稍后将定义这些处理程序。接下来,对每个传输请求调用帮助器方法 ProcessTransfer。该方法将处理已完成并且正在从队列中删除的正在移动的已传输文件。还设置相应的布尔值(如果任何传输正在挂起)。对每个传输请求调用 ProcessTransfer 之后,如果任何传输正在挂起,则会向用户显示一个消息框。

    private void InitialTransferStatusCheck()
    {
      UpdateRequestsList();
    
      foreach (var transfer in transferRequests)
      {
        transfer.TransferStatusChanged += new EventHandler<BackgroundTransferEventArgs>(transfer_TransferStatusChanged);
        transfer.TransferProgressChanged += new EventHandler<BackgroundTransferEventArgs>(transfer_TransferProgressChanged);
        ProcessTransfer(transfer);  
      }
    
      if (WaitingForExternalPower)
      {
        MessageBox.Show("You have one or more file transfers waiting for external power. Connect your device to external power to continue transferring.");
      }
      if (WaitingForExternalPowerDueToBatterySaverMode)
      {
        MessageBox.Show("You have one or more file transfers waiting for external power. Connect your device to external power or disable Battery Saver Mode to continue transferring.");
      }
      if (WaitingForNonVoiceBlockingNetwork)
      {
        MessageBox.Show("You have one or more file transfers waiting for a network that supports simultaneous voice and data.");
      }
      if (WaitingForWiFi)
      {
        MessageBox.Show("You have one or more file transfers waiting for a WiFi connection. Connect your device to a WiFi network to continue transferring.");
      }
    }
    
    
    
  11. 帮助器方法 ProcessTransfer 将 BackgroundTransferRequest 对象作为参数,然后根据传输的状态采取操作。使用 TransferStatus 属性确定传输的状态。如果状态为“已完成”,则意味着传输不再处于活动状态,但不意味着传输成功。若要确定已完成的传输是否成功,请计算包含传输的 HTTP 状态代码的 StatusCode 属性的值。根据服务器配置,成功传输的状态为 200 或 206。

    如果传输成功,则应用会通过调用帮助器方法 RemoveTransferRequest 从队列中删除传输请求。在任何时间,每个应用的队列中仅限 25 个传输请求,而且系统不会自动从队列中删除已完成的传输,因此您的应用一定要删除已完成的传输,以便为更多的传输释放槽。接下来,成功的已传输文件从所有传输必须下载到的“/shared/transfers”目录中移出。

    如果已完成的传输未成功(因为返回的状态代码不是 200 或 206),则您的应用可能会尝试采取一些操作来解决此问题,但一定要从队列中删除该传输。在此示例中,检查 TransferError 消息,以确定是否尝试采用电池电源进行较大文件的传输,如果是这样,则重新排列此请求。

    对于正在处理的传输请求具有指示传输已挂起,正在等待用户操作的 TransferStatus 的情况,则设置适当的布尔值以便可以向用户显示一个消息框。

    private void ProcessTransfer(BackgroundTransferRequest transfer)
    {
      switch(transfer.TransferStatus)
      {
        case TransferStatus.Completed:
                
          // If the status code of a completed transfer is 200 or 206, the
          // transfer was successful
          if (transfer.StatusCode == 200 || transfer.StatusCode == 206)
          {
            // Remove the transfer request in order to make room in the 
            // queue for more transfers. Transfers are not automatically
            // removed by the system.
            RemoveTransferRequest(transfer.RequestId);
    
            // In this example, the downloaded file is moved into the root
            // Isolated Storage directory
            using (IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication())
            {
              string filename = transfer.Tag;
              if (isoStore.FileExists(filename))
              {
                isoStore.DeleteFile(filename);
              }
              isoStore.MoveFile(transfer.DownloadLocation.OriginalString, filename);
            }
          }
          else
          {
            // This is where you can handle whatever error is indicated by the
            // StatusCode and then remove the transfer from the queue. 
            RemoveTransferRequest(transfer.RequestId);
    
            if (transfer.TransferError != null)
            {
              // Handle TransferError if one exists.
            }
        }
        break;
    
    
        case TransferStatus.WaitingForExternalPower:
          WaitingForExternalPower = true;
          break;
    
        case TransferStatus.WaitingForExternalPowerDueToBatterySaverMode:
          WaitingForExternalPowerDueToBatterySaverMode = true;
          break;
    
        case TransferStatus.WaitingForNonVoiceBlockingNetwork:
          WaitingForNonVoiceBlockingNetwork = true;
          break;
    
        case TransferStatus.WaitingForWiFi:
          WaitingForWiFi = true;
          break;
      }
    }
    
    
  12. 接下来,实现 TransferStatusChangedTransferProgressChanged 的事件处理程序。当传输状态发生更改(如从 Transferring 更改为 Completed)时调用 TransferStatusChanged。调用先前定义的帮助器方法 ProcessTransfer 来处理传输,然后调用 UpdateUI。当传输的字节数发生更改时调用 TransferProgressChanged。该处理程序只是调用 UpdateUI

    void transfer_TransferStatusChanged(object sender, BackgroundTransferEventArgs e)
    {
      ProcessTransfer(e.Request);
      UpdateUI();
    }
    
    void transfer_TransferProgressChanged(object sender, BackgroundTransferEventArgs e)
    {
      UpdateUI();
    }
    
    
    
  13. 使用后台传输的应用需要提供一个供用户取消后台传输请求的机制。在该页面的 XAML 定义中,为每个后台传输请求创建了一个取消按钮。所有这些按钮都共享同一个事件处理程序。使用每个按钮的 Tag 属性将每个传输的唯一 RequestId 传递给 Click 事件处理程序。调用帮助器方法 RemoveTransferRequest 以删除关联的传输。将在下面显示该方法的定义。删除传输请求之后,调用 UpdateUI

    private void CancelButton_Click(object sender, EventArgs e)
    {
      // The ID for each transfer request is bound to the
      // Tag property of each Remove button.
      string transferID = ((Button)sender).Tag as string;
    
      // Delete the transfer request
      RemoveTransferRequest(transferID);
    
      // Refresh the list of file transfers
      UpdateUI();
    }
    
    
  14. 下面的帮助方法获取传输的 RequestId 并调用 Remove(BackgroundTransferRequest) 以向服务注销传输请求。

    private void RemoveTransferRequest(string transferID)
    {
      // Use Find to retrieve the transfer request with the specified ID.
      BackgroundTransferRequest transferToRemove = BackgroundTransferService.Find(transferID);
    
      // Try to remove the transfer from the background transfer service.
      try
      {
        BackgroundTransferService.Remove(transferToRemove);
      }
      catch (Exception e)
      {
        // Handle the exception.
      }
    }
    
    
  15. 在该页面的 XAML 中,创建了一个 ApplicationBarIconButton 按钮以允许用户从应用的列表中删除所有已完成的传输。在该按钮的 Click 处理程序中,循环通过列表中的传输。如果传输的 TransferStatusCompleted,则调用 RemoveTransferRequest 帮助器方法以将其删除。最后,调用 UpdateUI

    private void CancelAllButton_Click(object sender, EventArgs e)
    {
      // Loop through the list of transfer requests
      foreach (var transfer in BackgroundTransferService.Requests)
      {
        RemoveTransferRequest(transfer.RequestId);
      }
    
      // Refresh the list of file transfer requests.
      UpdateUI();
    }
    
    
  16. MainPage.xaml.cs 的最后更新是为用户通过点按来添加新后台传输的 ApplicationBarIconButton 创建 Click 事件处理程序。使用 Navigate 方法将应用导航到将在下一节中实现的 AddBackgroundTransfer.xaml。

    private void AddBackgroundTransferButton_Click(object sender, EventArgs e)
    {
      // Navigate to the AddBackgroundTransfer page when the Add button
      // is tapped.
      NavigationService.Navigate(new Uri("/AddBackgroundTransfer.xaml", UriKind.RelativeOrAbsolute));
    }
    
    

本演练的下一步是创建一个允许用户向队列中添加后台传输的页面。使用后台传输的应用必须警告用户正在执行后台传输或让用户启动传输。本例将显示较大的远程文件的硬编码列表。对于每个地址,都将有一个“添加”按钮,单击该按钮时会为文件创建后台传输。

创建用来添加后台传输的页面

  1. 向您的项目中添加一个新页面。从“项目”菜单中,选择“添加新项...”。选择“Windows Phone 纵向页面”。在“名称”文本框中,键入 AddBackgroundTransfer.xaml

  2. “解决方案资源管理器”中,双击 AddBackgroundTransfer.xaml 以将其打开。接下来,添加允许用户选择要传输的文件的控件。将下面的代码粘贴到 AddBackgroundTransfer.xaml 中。该代码应粘贴在名为“ContentPanel”的 Grid 元素中。

    <StackPanel>
      <StackPanel Orientation="Horizontal">
        <CheckBox Name="wifiOnlyCheckbox" IsChecked="True" ></CheckBox>
        <TextBlock Text="only download when WiFi is available." VerticalAlignment="Center" Foreground="{StaticResource PhoneAccentBrush}"></TextBlock>
      </StackPanel>
      <StackPanel Orientation="Horizontal">
        <CheckBox Name="externalPowerOnlyCheckbox" IsChecked="True" ></CheckBox>
        <TextBlock Text="only download when connected to external power." VerticalAlignment="Center" Foreground="{StaticResource PhoneAccentBrush}" TextWrapping="Wrap" Height="60" Width="374"></TextBlock>
      </StackPanel>
    
      <ListBox Name="URLListBox" >
        <ListBox.ItemTemplate>
          <DataTemplate>
            <Grid Background="Transparent" Margin="0,0,0,30">
              <Grid.ColumnDefinitions>
                <ColumnDefinition Width="350"/>
                <ColumnDefinition Width="80"/>
              </Grid.ColumnDefinitions>
              <Grid Grid.Column="0">
                <TextBlock Text="{Binding}" TextWrapping="Wrap" HorizontalAlignment="Left"/>
              </Grid>
              <Grid Grid.Column="1">
                <Button Tag="{Binding}" Content="Add" Height="72" HorizontalAlignment="Left" Name="button1" VerticalAlignment="Top" Width="80" FontSize="15" Click="addButton_Click"/>
              </Grid>
            </Grid>
          </DataTemplate>
        </ListBox.ItemTemplate>
      </ListBox>
    </StackPanel>
    
    
    

    就像 MainPage.xaml 中的 XAML 一样,该代码定义一个 ListBox 并且定义一个将用于显示列表中项的模板。在此示例中,为每一项添加一个 TextBlock 和一个 Button 控件。TextBlockText 属性以及该按钮的 Tag 属性都绑定到 URL 数组(将在 C# 代码隐藏页面中定义)中的值。

    此 XAML 代码中还包含两个 CheckBox 控件,它们用于允许用户选择仅在设备具有 Wi-Fi 连接和外部电源时才执行的传输。我们建议所有应用都提供该功能,尤其是传输的文件较大时更是如此。

  3. 在 AddBackgroundTransfer.xaml.cs 中,为 BackgroundTransferIsolatedStorage 命名空间添加 using 指令。

    using Microsoft.Phone.BackgroundTransfer;
    using System.IO.IsolatedStorage;
    
    
  4. 定义一个类变量,该变量是用户将能够为其添加后台传输的文件 URL 列表。大多数应用都将包含要从 Web 服务动态下载的文件 URL。若要使本示例自我包含,则对这些 URL 进行硬编码。将此定义粘贴到所示的页面类定义中。

    public partial class AddBackgroundTransfer : PhoneApplicationPage
    {
      private readonly List<string> urls =
        new List<string>
        {
          "http://www.contoso.com/assets/cms/images/samples/windowsphonetestfile1.png",  
          "http://www.contoso.com/assets/cms/images/samples/windowsphonetestfile2.png",  
          "http://www.contoso.com/assets/cms/images/samples/windowsphonetestfile3.png",  
          "http://www.contoso.com/assets/cms/images/samples/windowsphonetestfile4.png",  
          "http://www.contoso.com/assets/cms/images/samples/windowsphonetestfile5.png",  
        };
    
    
  5. 在该页面的构造函数中,首先将在 XAML 中定义的 ListBoxItemsSource 属性设置为刚刚创建的 URL 列表。 然后,进行检查以确保独立存储的根目录中存在名为“/shared/transfers”的目录,如果不存在,则创建该目录。所有后台传输都必须在该目录中执行。BackgroundTransferRequest 对象的 DownloadLocationUploadLocation 属性必须指向该目录中的某个位置。如果您选择的话,可以在该目录中创建子目录,但是尝试将文件保存到“/shared/transfers”目录之外的目录或从“/shared/transfers”目录之外的目录上传文件都将引发异常。

    public AddBackgroundTransfer()
    {
      InitializeComponent();
    
      // Bind the list of URLs to the ListBox.
      URLListBox.ItemsSource = urls;
    
      // Make sure that the required "/shared/transfers" directory exists
      // in isolated storage.
      using (IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication())
      {
        if (!isoStore.DirectoryExists("/shared/transfers"))
        {
           isoStore.CreateDirectory("/shared/transfers");
        }
      }
    }
    
    
  6. 对于向用户显示的每个 URL,创建一个“添加”按钮。 所有这些按钮都共享同一个事件处理程序 addButton_Click。本节中所有剩余的代码都将放置在该处理程序中。

    private void addButton_Click(object sender, RoutedEventArgs e)
    {
      // The following code goes here.
    }
    
    
  7. 对于 UI 中的每个“添加”按钮,Tag 属性都绑定到要下载的文件的 URL。每个应用一次仅限 25 个并发传输请求。Click 事件处理程序中的第一步是查看是否已达到该限制。如果已达到该限制,则警告用户以便他们可以决定是等待还是取消现有传输。或者,您也可以保存传输信息,然后在稍后有可用的槽时将其添加到队列。接下来,获取 URL 字符串并从中创建 URI 对象。如果 URL 字符串尚未转义,则使用 EscapeUriString 进行转义。将此 URI 传递给 BackgroundTransferRequest 的构造函数。接下来,设置传输方法。本例使用 GET,但也支持 POST。

    
      // Check to see if the maximum number of requests per app has been exceeded.
      if (BackgroundTransferService.Requests.Count() >= 25)
      {
        // Note: Instead of showing a message to the user, you could store the
        // requested file URI in isolated storage and add it to the queue later.
        MessageBox.Show("The maximum number of background file transfer requests for this application has been exceeded. ");
        return;
      }
    
      // Get the URI of the file to be transferred from the Tag property
      // of the button that was clicked.
      string transferFileName = ((Button)sender).Tag as string;
      Uri transferUri = new Uri(Uri.EscapeUriString(transferFileName), UriKind.RelativeOrAbsolute);
    
    
      // Create the new transfer request, passing in the URI of the file to 
      // be transferred.
      BackgroundTransferRequest transferRequest = new BackgroundTransferRequest(transferUri);
      
      // Set the transfer method. GET and POST are supported.
      transferRequest.Method = "GET";
    
    
    
  8. 下面,从 URL 的结尾提取文件名。在独立存储的“transfers”目录中创建一个 URI 并设置 DownloadLocation 属性。可以使用 Tag 属性来传递自定义数据以及传输请求。在此示例中,使用 Tag 来传递传输文件的友好名称。

      // Get the file name from the end of the transfer URI and create a local URI 
      // in the "transfers" directory in isolated storage.
      string downloadFile = transferFileName.Substring(transferFileName.LastIndexOf("/") + 1);
      Uri downloadUri = new Uri("shared/transfers/" + downloadFile, UriKind.RelativeOrAbsolute);
      transferRequest.DownloadLocation = downloadUri;
    
      // Pass custom data with the Tag property. In this example, the friendly name
      // is passed.
      transferRequest.Tag = downloadFile;
    
    
  9. 下面,检查 CheckBox 控件的 IsChecked 属性,看用户是否希望仅在有 Wi-Fi 连接或外部电源时才执行传输。使用 TransferPreferences 属性来指定数据连接和设备电源的要求。

      // If the Wi-Fi-only check box is not checked, then set the TransferPreferences
      // to allow transfers over a cellular connection.
      if (wifiOnlyCheckbox.IsChecked == false)
      {
        transferRequest.TransferPreferences = TransferPreferences.AllowCellular;
      }
      if (externalPowerOnlyCheckbox.IsChecked == false)
      {
        transferRequest.TransferPreferences = TransferPreferences.AllowBattery;
      }
      if (wifiOnlyCheckbox.IsChecked == false && externalPowerOnlyCheckbox.IsChecked == false)
      {
        transferRequest.TransferPreferences = TransferPreferences.AllowCellularAndBattery;
      }
    
    
    
  10. 最后,通过调用 BackgroundTransferServiceAdd(BackgroundTransferRequest) 方法注册传输请求。添加传输请求时可能会引发异常,因此在 try 块内调用该方法。

      // Add the transfer request using the BackgroundTransferService. Do this in 
      // a try block in case an exception is thrown.
      try
      {
        BackgroundTransferService.Add(transferRequest);
      }
      catch (InvalidOperationException ex)
      {      
        MessageBox.Show("Unable to add background transfer request. " + ex.Message);
      }
      catch (Exception)
      {
        MessageBox.Show("Unable to add background transfer request.");
      }
    
    

显示:
© 2015 Microsoft