トップ回答者
WPF ListBoxItemで参照された画像ファイルの削除

質問
-
開発環境:VS2017 Community,Windows 7です。
ListBoxItemに指定したjpegファイルを参照して表示させるサンプルプログラムです。
ListBoxの全要素をMe.LB1.Items.Clear() として全消去した後に、参照されたjpegファイルを削除しようとしてもできません。
例外内容:System.IO.IOException: '別のプロセスで使用されているため、プロセスはファイル 'C:\001.jpg' にアクセスできません。'
この例外を発生させず、jpegファイルを削除するにはどうしたら良いのか教えて下さい。
◆XAML
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp0701"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<ListBox x:Name="LB1" HorizontalAlignment="Left" Height="371" Margin="27,23,0,0" VerticalAlignment="Top" Width="386"/>
<Button x:Name="BT1" Content="要素削除" HorizontalAlignment="Left" Height="57" Margin="447,128,0,0" VerticalAlignment="Top" Width="85" />
<Button x:Name="BT_DEL" Content="ファイル削除" HorizontalAlignment="Left" Height="57" Margin="447,224,0,0" VerticalAlignment="Top" Width="85" />
</Grid>
</Window>
◆コード
Imports System.IO
Class MainWindow
Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
'C:\001.jpg、C:\002.jpg 2つのファイルを用意しておく
addImage("C:\001.jpg")
addImage("C:\002.jpg")
End Sub
'ListBox1要素を全削除
Private Sub Button_Click(sender As Object, e As RoutedEventArgs) Handles BT1.Click
Me.LB1.Items.Clear()
'↑これだけで全削除できないのか?
Debug.Print("LB1.Items.Cleared")
End Sub
'使われなくなったJPGファイルを削除したい
Private Sub BT_DEL_Click(sender As Object, e As RoutedEventArgs) Handles BT_DEL.Click
Dim arrFiles() = System.IO.Directory.GetFiles("C:\")
For Each s1 In arrFiles
If Path.GetExtension(s1).ToLower = ".jpg" Then System.IO.File.Delete(s1) 'ここで削除できない System.IO.IOException: '別のプロセスで使用されているため、プロセスはファイル 'C:\001.jpg' にアクセスできません。'
Next
End Sub
'JPG画像をListBox1に追加
Private Sub addImage(ByRef fs As String)
Dim sp As New StackPanel
Dim im As New System.Windows.Controls.Image
Dim bi = New BitmapImage
Dim fs1 As New IO.FileStream(fs, FileMode.Open, FileAccess.Read)
If Not IO.File.Exists(fs) Then Exit Sub
bi.BeginInit()
bi.CacheOption = BitmapCacheOption.OnLoad
bi.StreamSource = fs1
bi.EndInit()
im.Source = bi
im.Width = bi.PixelWidth
im.Height = bi.PixelHeight
sp.Children.Add(im)
Me.LB1.Items.Add(sp)
End Sub
End Class
- 編集済み huahi11112 2019年7月2日 7:51 誤記
回答
-
CacheOption.OnLoadに設定しているのであれば、EndInitから返った時点でソースとなったストリームはもう使用されませんので、破棄してください。
Using fs1 = New IO.FileStream(...) を使うのが便利です。
- 回答としてマーク huahi11112 2019年7月2日 8:27
すべての返信
-
CacheOption.OnLoadに設定しているのであれば、EndInitから返った時点でソースとなったストリームはもう使用されませんので、破棄してください。
Using fs1 = New IO.FileStream(...) を使うのが便利です。
- 回答としてマーク huahi11112 2019年7月2日 8:27
-
そうか!FileStreamをCloseしていなかったんですね。
Hongliangさんには今回も御教授いただき、ありがとうございました。
’書き直して動作したメソッド
Private Sub addImage(ByRef fs As String)
Dim sp As New StackPanel
Dim im As New System.Windows.Controls.Image
Dim bi = New BitmapImage
If Not IO.File.Exists(fs) Then Exit Sub
Using fs2 = New IO.FileStream(fs, FileMode.Open, FileAccess.Read)
bi.BeginInit()
bi.CacheOption = BitmapCacheOption.OnLoad
bi.StreamSource = fs2
bi.EndInit()
End Using
im.Source = bi
im.Width = bi.PixelWidth
im.Height = bi.PixelHeight
sp.Children.Add(im)
Me.LB1.Items.Add(sp)
End Sub