none
WPF ListBoxItemで参照された画像ファイルの削除 RRS feed

  • 質問

  • 開発環境: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 誤記
    2019年7月2日 7:50

回答

  • CacheOption.OnLoadに設定しているのであれば、EndInitから返った時点でソースとなったストリームはもう使用されませんので、破棄してください。

    Using fs1 = New IO.FileStream(...) を使うのが便利です。

    • 回答としてマーク huahi11112 2019年7月2日 8:27
    2019年7月2日 8:09

すべての返信

  • CacheOption.OnLoadに設定しているのであれば、EndInitから返った時点でソースとなったストリームはもう使用されませんので、破棄してください。

    Using fs1 = New IO.FileStream(...) を使うのが便利です。

    • 回答としてマーク huahi11112 2019年7月2日 8:27
    2019年7月2日 8:09
  • そうか!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

    2019年7月2日 8:29