ListBoxに表示された画像をポップアップメニューから削除する+1つのサンプル

2013年2月8日(金)
薬師寺 国安

今回は2つのサンプルを紹介します。「ListBoxに表示された画像をポップアップメニューから削除する」と「複数の画像を連続表示する」の2つです。

まずは、「ListBoxに表示された画像をポップアップメニューから削除する」サンプルから紹介します。

ListBoxに表示された画像をポップアップメニューから削除する

このサンプルは、ListBoxに表示されている任意の画像を選択し、マウスの右クリックで表示されるポップアップメニューから、「画像の削除」をクリックすると、選択されていた画像が削除されるというものです(図1)。「画像の削除」を実行する際には、必ず削除する画像を選択状態にして実行してください。なお、今回もピクチャライブラリ内の画像を使用しますので、ピクチャライブラリ内に何枚かの画像を配置しておいてください。

図1:ListBox内の任意の画像を削除した(クリックで拡大)

実際に動かした動画は下記のようになります。Windows Store Applicationの動画を撮るアプリケーションが存在していませんので、スマホで撮った動画です。見難い点はご了承願います。

サンプル一式は、会員限定特典としてダウンロードできます。記事末尾をご確認ください。

プロジェクトの作成

VS 2012のメニューから[ファイル(F)/新規作成(N)/プロジェクト(P)]と選択します。次に、「テンプレート」から「Windows ストア」を選択し、右に表示される項目名から「新しいアプリケーション(XAML)」を選択します。「名前(N)」に任意のプロジェクト名を指定します。ここでは「Win8_DeleteImageFile」という名前を付けています。

コントロールの配置

ツールボックスからデザイン画面上にListBoxコントロールを1個配置します。

書き出されるXAMLコードは省略します。レイアウトは図2になります。

図2:ListBoxコントロールを配置した(クリックで拡大)

ピクチャライブラリへのアクセス許可の設定

今回のサンプルは、ピクチャライブラリにアクセスしますので、「画像ライブラリ」へのアクセス許可が必要になります。ソリューションエクスプローラー内にpackage.appxmanifestというファイルがありますので、このファイルをダブルクリックします。「機能」タブをクリックして、表示される画面の「機能:」にある、「画像ライブラリ」にチェックを付けます(図3)。

図3:package.appxmanifestファイルを開き「画像ライブラリ」にチェックを付ける(クリックで拡大)

次に、ソリューションエクスプローラー内のMainWindow.xamlを展開して表示される、MainWindow.xaml.vbをダブルクリックしてリスト1のコードを記述します。

ロジックコードを記述する

リスト1 (MainWindow.xaml.vb)

Option Strict On

ファイル、フォルダー、およびアプリケーションの設定を管理するクラスの含まれる、Windows.Storage名前空間をインポートします。

Imports Windows.Storage

PopupMenuであるコンテキストメニューを表示させるのに必要なクラスの含まれる、Windows.UI.Popups名前空間をインポートします。

Imports Windows.UI.Popups
Public NotInheritable Class MainPage
  Inherits Page

フォルダーとその内容についての情報を提供する、StorageFolderクラス型のメンバ変数、myPictureFolderを宣言します。

  Dim myPictureFolder As StorageFolder

文字列型の新しいリストであるfileNameメンバ変数を宣言します。

  Dim fileNameList As New List(Of String)

ページがアクティブになった時の処理

ListBox内に画像の一覧を表示するDataShowプロシージャを実行します。

  Protected Overrides Sub OnNavigatedTo(e As Navigation.NavigationEventArgs)
    DataShow()
  End Sub

ListBox内にピクチャライブラリ内の画像を表示する処理

ピクチャライブラリにアクセスします。GetFilesAsyncメソッドで、ピクチャライブラリ内のファイルを取得し、コレクション変数myPictureFilesに格納しておきます。
ListBox内を一度クリアしておきます。この処理をしていないと、画像が重複して表示されますので、ご注意ください。

ファイル名を格納しているmyPictureFilesコレクション内のファイルを、変数myFileに格納しながら、反復処理を行います。
BitmapImageクラスの新しいインスタンスbmpオブジェクトを作成し、SetSourceメソッドに、Await myFile.OpenReadAsyncと指定して、ランダムアクセス用ストリームを開いていきます。また、文字列のリストであるfileNameListオブジェクトにAddメソッドでパス付きファイル名を追加していきます。

Imageの新しいインスタンスmyImageオブジェクトを作成します。
WidthとHeightを指定し、Sourceプロパティにbmpオブジェクトを指定します。
ListBoxコントロールにAddメソッドでmyImageファイルオブジェクトを追加します。これで、ListBoxコントロール内にピクチャライブラリ内の画像一覧が表示されます。

非同期処理で行われるため、メソッドの先頭にAsyncを追加します。Asyncが追加されていると、その処理が非同期で行われることを意味します。

  Private Async Sub DataShow()
    myPictureFolder = KnownFolders.PicturesLibrary
    Dim myPictureFiles As IReadOnlyList(Of IStorageFile) = Await myPictureFolder.GetFilesAsync()
    ListBox1.Items.Clear()
    For Each myFile In myPictureFiles
      Dim bmp As New BitmapImage
      bmp.SetSource(Await myFile.OpenReadAsync)
      fileNameList.Add(Path.GetFileName(myFile.Path))
      Dim myImage As New Image
      myImage.Margin = New Thickness(0, 0, 0, 0)
      myImage.Width = 320
      myImage.Height = 240
      myImage.Source = bmp
      ListBox1.Items.Add(myImage)
    Next
  End Sub

ListBox上にポインターがあった時、右タップの入力刺激があった時の処理

2次元空間でのXとY座標のペアを表すPoint構造体を、右タップされた時点のXとY座標で初期化します。位置合わせを行っています。

ListBoxの描画時の幅と高さで初期化された、新しいSizeのインスタンスmySizeオブジェクトを作成します。Size構造体はオブジェクトの幅と高さを表します。

四角形の幅、高さ、および原点を表すRect構造体を、Point構造体のオブジェクトmyPointと、Size構造体のオブジェクトmySizeで初期化した、新しいRectのインスタンス、myRectオブジェクトを作成します。

コンテキストメニューを表すPopupMenuクラスのインスタンス、myPopupオブジェクトを作成します。

Command.Addメソッドで、PopupMenuに項目名と、その項目をタップした際のコマンドを追加します。UICommandクラスは、コンテキストメニュー内のコマンドを表します。PopupMenuに「画像の削除」の項目を追加し、それに対するコマンド(ImageDelete)を追加します。

ShowForSelectionAsyncメソッドで、指定された選択項目を基準とする適切な位置に、コンテキストメニューを表示します。この場合はListBox内で右タップがされた位置の左側(Placement.Left)にコンテキストメニューが表示されます。Placement列挙体については、下記のURLを参考にしてください。
→ Placement enumeration (Windows)

非同期処理で行われるため、メソッドの先頭にAsyncを追加します。Asyncが追加されていると、その処理が非同期で行われることを意味します。

  Private Async Sub ListBox1_RightTapped(sender As Object, e As RightTappedRoutedEventArgs) Handles ListBox1.RightTapped
    Dim myPoint As Point = New Point(e.GetPosition(ListBox1).X + ListBox1.Width, e.GetPosition(ListBox1).Y - (ListBox1.Height / 2))
    Dim mySize As New Size(ListBox1.ActualWidth, ListBox1.ActualHeight)
    Dim myRect As New Rect(myPoint, mySize)
 
    Dim myPopup As New PopupMenu

    myPopup.Commands.Add(New UICommand("画像の削除", Sub(command)
                                                     ImageDelete()
                                           End Sub))
    Await myPopup.ShowForSelectionAsync(myRect, Placement.Left)
  End Sub

選択された画像を削除する処理

ListBoxコントロール内の画像が選択状態になっていない場合は、警告メッセージを表示して、処理を抜けます。

それ以外の場合は、以下の処理を行います。ファイル名を格納しているリストオブジェクトである、fileNameListで、ListBoxのインデックスに対応するファイルを、GetFileAsyncメソッドで取得し、DeleteImageFileに格納します。
リストであるfileNameListからListBoxのインデックスに対応するファイル名を、RemoveAtメソッドで削除します。
同様に、DeleteFileAsyncメソッドで、DeleteImageFileに格納されているファイルを削除します。
削除した旨のメッセージを表示し、ListBox内を更新するためにDataShowプロシージャを実行します。

非同期処理で行われるため、メソッドの先頭にAsyncを追加します。Asyncが追加されていると、その処理が非同期で行われることを意味します。

  Private Async Sub ImageDelete()
    If ListBox1.SelectedIndex < 0 Then
      Dim message = New MessageDialog("画像を選択してください。")
      Await message.ShowAsync
      Exit Sub
    Else
  
      Dim DeleteImageFile = Await myPictureFolder.GetFileAsync(fileNameList(ListBox1.SelectedIndex))
      fileNameList.RemoveAt(ListBox1.SelectedIndex)
      Await DeleteImageFile.DeleteAsync()
      Dim message = New MessageDialog("削除しました。")
      Await message.ShowAsync
      DataShow()
    End If
  End Sub
End Class
  • ListBoxに表示された画像をポップアップメニューから削除するWindowsアプリ

  • 複数の画像を連続表示する

薬師寺国安事務所

薬師寺国安事務所代表。Visual Basic プログラミングと、マイクロソフト系の技術をテーマとした、書籍や記事の執筆を行う。
1950年生まれ。事務系のサラリーマンだった40歳から趣味でプログラミングを始め、1996年より独学でActiveXに取り組む。1997年に薬師寺聖とコラボレーション・ユニット PROJECT KySS を結成。2003年よりフリーになり、PROJECT KySS の活動に本格的に参加、.NETやRIAに関する書籍や記事を多数執筆する傍ら、受託案件のプログラミングも手掛ける。Windows Phoneアプリ開発を経て、現在はWindows ストア アプリを多数公開中

Microsoft MVP for Development Platforms - Client App Dev (Oct 2003-Sep 2012)。Microsoft MVP for Development Platforms - Windows Phone Development(Oct 2012-Sep 2013)。Microsoft MVP for Development Platforms - Client Development(Oct 2013-Sep 2014)。Microsoft MVP for Development Platforms-Windows Platform Development (Oct 2014-Sep 2015)。

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています