方法: Windows Phone のバックグラウンド ファイル転送を実装する

2012/02/09

このトピックでは、BackgroundTransferService を使用してバックグラウンド ファイル転送を開始および監視する簡単なアプリケーションを作成する手順について説明します。この例では、2 つのページを作成します。1 番目のページでは、アプリケーションで現在行われているすべてのバックグラウンド ファイル転送のステータスが一覧表示され、ユーザーはアクティブな転送を取り消すことができます。これらはどちらも、バックグラウンド転送を使用するすべてのアプリケーションに必要な機能です。2 番目のページでは、ユーザーは新しいバックグラウンド転送をキューに追加できます。アプリケーションでは、[ダウンロードを開始] ボタンを提供するなどして、ユーザーがバックグラウンド転送を開始できるようにする必要があります。または、ユーザーに代わって転送を開始することをユーザーに警告する必要があります。このページでは、ユーザーはデバイスに Wi-Fi 接続があるときにのみ新しいバックグラウンド転送を実行するように制限することもできます。これは必須の機能ではありませんが、用意することを強くお勧めします。転送されるファイルが大きい場合には特にそうです。

バックグラウンド ファイル転送を作成するには、BackgroundTransferRequest オブジェクトを使用してファイル転送を表します。このオブジェクトのプロパティでは、ダウンロードまたはアップロードの対象となるファイル、転送先のパス、転送方法、および他の構成可能な設定を指定できます。BackgroundTransferRequestBackgroundTransferService オブジェクトの Add メソッドに渡されると、転送が開始されます。また、BackgroundTransferService オブジェクトを使用すると、アプリケーションに対して現在登録されている転送を表す BackgroundTransferRequest オブジェクトを取得することもできます。これらのオブジェクトを使用すると、アクティブな転送の現在のステータスを判別できます。

この例で作成する 1 番目のページでは、アプリケーションに現在登録されているすべてのバックグラウンド転送が一覧表示されます。このページでは、BackgroundTransferRequest オブジェクトの一覧にデータ バインドされた ListBox コントロールを使用します。

ファイル転送一覧表示ページを作成するには

  1. Visual Studio で、新しい Windows Phone アプリケーション プロジェクトを作成します。このテンプレートは、Silverlight for Windows Phone カテゴリにあります。

  2. 転送一覧表示ページを作成する最初の手順は、XAML でユーザー インターフェイスを作成することです。見た目のよい UI を作成するために必要な XAML コードは膨大になることがあるので、最初に XAML コードを示した後、重要な要素に注目します。Silverlight コントロールの使用の詳細については、「Windows Phone のコントロール」を参照してください。

    プロジェクトの 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. 1 番目の TextBlock コントロールは、表示するバックグラウンド転送がないときにユーザーにメッセージを表示するために使用されます。C# 分離コード ページでは、一覧に項目がないときはこのコントロールの Visibility プロパティを Visible に切り替え、一覧に表示する項目があるときは Collapsed に切り替えます。

    2. ListBox 要素では、すべてのバックグラウンド転送とその関連データを一覧表示するコントロールを定義します。この XAML コードの残りの部分は、実際にリストに項目を追加するわけではありません。代わりに、バインドされたデータの表示方法を ListBox に指示する DataTemplate を含んでいます。ListBox の名前 TransferListBox は、C# 分離コード ページでコントロールを参照するために使用する名前です。

    3. Grid 要素と StackPanel 要素は、他のコントロールのレイアウトを構成するのに使用されるコンテナー コントロールです。

    4. StackPanel コントロールの内部にある TextBlock 要素は、BackgroundTransferRequest クラスのプロパティの値を表示します。たとえば、TransferStatus プロパティは転送が待機中、転送中、または完了済みかどうかを示します。BytesReceived プロパティでは、転送で受信されたバイト数が示されます。Tag プロパティでは、カスタム データを転送要求に添付できます。この例では、Tag プロパティを使用してダウンロードの表示名を渡します。構文 {Binding RecurrenceType} は、これらの各コントロールの Text プロパティを指定されたプロパティ名にマッピングします。各値にラベルを提供するため、追加の TextBlock コントロールが含まれます。

    5. 最後に、Button を追加して、ユーザーがバックグラウンド転送要求を削除できるようにします。この機能は、バックグラウンド転送を使用するすべてのアプリケーションに必要です。BackgroundTransferRequestRequestId プロパティは、各転送要求を一意に識別するために使用されます。ボタンに対する Click イベント ハンドラー RemoveButton_Click が削除する転送を特定できるように、この値を ButtonTag プロパティにバインドします。このハンドラーは、あとから C# 分離コード ページに追加されます。

  3. 最後に MainPage.xaml に追加する必要があるのは、ApplicationBar です。ApplicationBar にある 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 宣言の下で、次の 4 つの Boolean 変数を宣言します。

      // 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 という名前のメソッドを作成します。このメソッドは、このアプリケーションの BackgroundTransferService で登録されている BackgroundTransferRequest オブジェクトを取得するために定義した UpdateRequestsList メソッドを使用します。ListBoxItemsSource プロパティに、転送の一覧を含む IEnumerable クラス変数が設定されます。これにより、ListBox が強制的に更新されます。最後に、ListBox に項目が 1 つでも含まれる場合は、転送が登録されていないことをユーザーに通知するテキスト ボックスが表示されなくなります。項目がない場合は表示されます。次のメソッド定義を 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) メソッドをオーバーライドします。このメソッドは、アプリケーションが起動されたときや、ページを初めて表示する場合などを含めて、ユーザーがページに移動したときに呼び出されます。このメソッドでは、転送が保留中かどうかを監視するために使用される Boolean 値が 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 オブジェクトについて、TransferStatusChanged イベントおよび TransferProgressChanged イベントのハンドラーを割り当てます。これらのハンドラーは後で定義します。次に、各転送要求に対してヘルパー メソッド ProcessTransfer を呼び出します。これらのメソッドは、転送が完了したファイルを移動し、キューから削除します。また、いずれかの転送が保留中の場合は対応する Boolean 値を設定します。各転送要求に対して ProcessTransfer を呼び出した後、いずれかの転送が保留中の場合は、メッセージ ボックスがユーザーに対して表示されます。

    private void InitialTansferStatusCheck()
    {
      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 property を使用して判別します。ステータスが Completed の場合は、転送がアクティブではなくなっていることを意味しますが、転送が成功したことは意味しません。完了した転送が成功したかどうかを確認するには、転送の HTTP ステータス コードを含む StatusCode プロパティを評価します。サーバーの構成により、成功した転送のステータスは 200 または 206 になります。

    転送が成功している場合、アプリケーションはヘルパー メソッド RemoveTransferRequest を呼び出してキューから転送要求を削除します。各アプリケーションがキューに入れることができる転送要求は常に 5 個以下に制限されており、完了した転送がシステムによってキューから自動的に削除されることはないので、完了した転送をアプリケーションで削除して新しい転送のためのスロットを解放することが重要です。次に、すべての転送のダウンロード先である /shared/transfers から、正常に転送されたファイルを移動します。

    200 または 206 以外のステータス コードが返されたために転送が正常に完了しなかった場合は、アプリケーションで何らかの処理を実行して問題を解決できますが、キューから転送を削除することが重要です。この例では、TransferError メッセージを調べて、大きいファイルの転送がバッテリー電源で試みられたかどうかを判断し、そうである場合は、要求を再びキューに入れます。

    処理されている転送要求の TransferStatus で、転送が保留中でユーザーの操作を待っていることが示されている場合は、メッセージ ボックスをユーザーに対して表示できるように、適切な Boolean 値を設定します。

    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. 次に、TransferStatusChanged および TransferProgressChanged に対するイベント ハンドラーを実装します。TransferStatusChanged は、転送のステータスが変化すると呼び出されます (たとえば、Transferring から Completed など)。前に定義したヘルパー メソッド 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 プロパティは、各転送の一意の RequestIdClick イベント ハンドラーに渡すために使用されます。ヘルパー メソッド 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 に対する最後の更新では、ユーザーが新しいバックグラウンド転送を追加するときにタップする ApplicationBarIconButtonClick イベント ハンドラーを作成します。アプリケーションを AddBackgroundTransfer.xaml に移動するには、Navigate メソッドを使用します。これについては次のセクションで実装します。

    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));
    }
    
    

次の手順では、ユーザーがバックグラウンド転送をキューに追加できるページを作成します。バックグラウンド転送を使用するアプリケーションでは、バックグラウンド転送が実行中であることをユーザーに通知するか、またはユーザーが転送を開始できるようにする必要があります。この例では、大きいリモート ファイルのハード コーディングされた一覧を表示します。各アドレスに対し、クリックするとファイルのバックグラウンド転送が作成される [Add] ボタンがあります。

バックグラウンド転送を追加するページを作成するには

  1. 新しいページをプロジェクトに追加します。[プロジェクト] メニューから、[新しい項目の追加] を選択します。[Windows Phone Portrait Page] を選択します。[名前] テキスト ボックスに、「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 プロパティは、C# 分離コード ページで定義されている URL の配列の値にバインドされています。

    また、この XAML コードには、デバイスに Wi-Fi 接続および外部電源があるときにのみ転送を実行することをユーザーが選択できるようにするために使用される 2 つの CheckBox コントロールも含まれます。すべてのアプリケーションでこの機能を提供することをお勧めします。転送されるファイルが大きい場合は特に必要です。

  3. AddBackgroundTransfer.xaml.cs で、BackgroundTransfer および IsolatedStorage 名前空間に using ディレクティブを追加します。

    using Microsoft.Phone.BackgroundTransfer;
    using System.IO.IsolatedStorage;
    
    
  4. ユーザーがバックグラウンド転送を追加できるファイルの URL の一覧であるクラス変数を定義します。ほとんどのアプリケーションでは、ダウンロードするファイルの URL を Web サービスから動的に取得します。この例を自己完結させるため、これらの URL はハード コーディングします。この定義を、次に示すようにページ クラス定義の内側に貼り付けます。

    public partial class AddBackgroundTransfer : PhoneApplicationPage
    {
      private readonly List<string> urls =
        new List<string>
        {
          "http://create.msdn.com/assets/cms/images/samples/windowsphonetestfile1.png",  
          "http://create.msdn.com/assets/cms/images/samples/windowsphonetestfile2.png",  
          "http://create.msdn.com/assets/cms/images/samples/windowsphonetestfile3.png",  
          "http://create.msdn.com/assets/cms/images/samples/windowsphonetestfile4.png",  
          "http://create.msdn.com/assets/cms/images/samples/windowsphonetestfile5.png",  
        };
    
    
  5. ページのコンストラクターで、最初に XAML で定義されている ListBoxItemsSource プロパティを、作成した URL の一覧に設定します。次に、/shared/transfers という名前のディレクトリが分離ストレージのルートに存在することを確認し、ない場合は、ディレクトリを作成します。すべてのバックグラウンド転送は、このディレクトリ内で実行される必要があります。BackgroundTransferRequest オブジェクトの DownloadLocation および UploadLocation プロパティは、このディレクトリ内の場所を指している必要があります。必要に応じてこのディレクトリ内にサブディレクトリを作成できますが、/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 ごとに、[Add] ボタンが作成されます。これらのボタンはすべて、同じイベント ハンドラー addButton_Click を共有します。このセクションで残っているすべてのコードは、このハンドラー内に格納します。

    private void addButton_Click(object sender, RoutedEventArgs e)
    {
      // The following code goes here.
    }
    
    
  7. UI の各 [Add] ボタンで、Tag プロパティをダウンロードするファイルの URL にバインドします。特定の時点で、各アプリケーションが実行できる同時転送要求は 5 つだけです。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() >= 5)
      {
        // 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.");
      }
    
    

表示: