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)

1Option Strict On

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

1Imports Windows.Storage

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

1Imports Windows.UI.Popups
2Public NotInheritable Class MainPage
3  Inherits Page

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

1Dim myPictureFolder As StorageFolder

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

1Dim fileNameList As New List(Of String)

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

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

1Protected Overrides Sub OnNavigatedTo(e As Navigation.NavigationEventArgs)
2  DataShow()
3End 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が追加されていると、その処理が非同期で行われることを意味します。

01Private Async Sub DataShow()
02  myPictureFolder = KnownFolders.PicturesLibrary
03  Dim myPictureFiles As IReadOnlyList(Of IStorageFile) = Await myPictureFolder.GetFilesAsync()
04  ListBox1.Items.Clear()
05  For Each myFile In myPictureFiles
06    Dim bmp As New BitmapImage
07    bmp.SetSource(Await myFile.OpenReadAsync)
08    fileNameList.Add(Path.GetFileName(myFile.Path))
09    Dim myImage As New Image
10    myImage.Margin = New Thickness(0, 0, 0, 0)
11    myImage.Width = 320
12    myImage.Height = 240
13    myImage.Source = bmp
14    ListBox1.Items.Add(myImage)
15  Next
16End 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が追加されていると、その処理が非同期で行われることを意味します。

01Private Async Sub ListBox1_RightTapped(sender As Object, e As RightTappedRoutedEventArgs) Handles ListBox1.RightTapped
02  Dim myPoint As Point = New Point(e.GetPosition(ListBox1).X + ListBox1.Width, e.GetPosition(ListBox1).Y - (ListBox1.Height / 2))
03  Dim mySize As New Size(ListBox1.ActualWidth, ListBox1.ActualHeight)
04  Dim myRect As New Rect(myPoint, mySize)
05 
06  Dim myPopup As New PopupMenu
07 
08  myPopup.Commands.Add(New UICommand("画像の削除", Sub(command)
09                                                   ImageDelete()
10                                         End Sub))
11  Await myPopup.ShowForSelectionAsync(myRect, Placement.Left)
12End Sub

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

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

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

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

01  Private Async Sub ImageDelete()
02    If ListBox1.SelectedIndex < 0 Then
03      Dim message = New MessageDialog("画像を選択してください。")
04      Await message.ShowAsync
05      Exit Sub
06    Else
07   
08      Dim DeleteImageFile = Await myPictureFolder.GetFileAsync(fileNameList(ListBox1.SelectedIndex))
09      fileNameList.RemoveAt(ListBox1.SelectedIndex)
10      Await DeleteImageFile.DeleteAsync()
11      Dim message = New MessageDialog("削除しました。")
12      Await message.ShowAsync
13      DataShow()
14    End If
15  End Sub
16End 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メルマガ会員のサービス内容を見る

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