Reputation: 11369
This is happening for a image gallery WPF application which shows the thumbnails in a listbox and the selected image using xaml
Question - Is there a way to delete the currently selected image safely without getting the IOException ?
FYI - the user has ALL rights to the directory, no other process is using the file
here's the code to delete the file
void deleteCurrentlySelectedImageClick()
{
var o = SelectedPhoto; // class MyPhoto with a string FilePath
string path = o.FilePath;
// ViewList is of type List<MyPhoto> bound to listbox for displaying thumbnails
// for the purists
// it can/should be of type ObservableCollection<>
// but this doesn't change that often here :)
ViewList.Remove(o);
o = null;
firePropertyChanged("ViewList");
firePropertyChanged("SelectedPhoto");
FileInfo fi = new FileInfo(path);
fi.Delete();
}
the exception is
System.IO.IOException was unhandled by user code
HResult=-2147024864
Message=The process cannot access the file 'C:\<path>\US-wp2.jpg' because it is being used by another process.
Source=mscorlib
StackTrace:
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileInfo.Delete()
the XAML for thumbnails is
<ListBox
IsSynchronizedWithCurrentItem="True"
Name="PhotosListBox"
Style="{StaticResource PhotoListBoxStyle}"
Margin="5"
SelectionMode="Extended"
ItemsSource="{Binding ViewList}"
SelectedIndex="0"
SelectionChanged="PhotosListBox_SelectionChanged"
>
.... // resources xaml is ....
<DataTemplate DataType="{x:Type sample1:MyPhoto}">
<Grid VerticalAlignment="Center" HorizontalAlignment="Center" Margin="6">
<!-- Drop Shadow -->
<Border HorizontalAlignment="Stretch" VerticalAlignment="Stretch" CornerRadius="4" Background="#44000000">
<Border.RenderTransform>
<TranslateTransform X="5" Y="5" />
</Border.RenderTransform>
<Border.BitmapEffect>
<BlurBitmapEffect Radius="8" />
</Border.BitmapEffect>
</Border>
<!-- Image Template -->
<Border Padding="4" Background="White" BorderBrush="#22000000" BorderThickness="1">
<StackPanel Orientation="Vertical">
<Image Source="{Binding FilePath}"/>
</StackPanel>
</Border>
</Grid>
</DataTemplate>
<!-- Main photo catalog view -->
<Style TargetType="{x:Type ListBox}" x:Key="PhotoListBoxStyle">
<Setter Property="Foreground" Value="White" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBox}" >
<WrapPanel Margin="5" IsItemsHost="True" Orientation="Horizontal"
ItemHeight="{Binding ElementName=ZoomSlider, Path='Value'}"
ItemWidth="{Binding ElementName=ZoomSlider, Path='Value'}"
VerticalAlignment="Top" HorizontalAlignment="Stretch" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Style for an individual generic item -->
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}" >
<Border SnapsToDevicePixels="True" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="{TemplateBinding Background}">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="#445B6249" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The full-size image xaml is simply
<Image Source="{Binding SelectedPhoto.FilePath}" HorizontalAlignment="Center" VerticalAlignment="Center" />
Upvotes: 3
Views: 2685
Reputation: 1378
public static bool Delete(FileInfo fi)
{
int retries = 40;
bool ret = false;
SpinWait _sw = new SpinWait();
while (!ret && retries-- > 0)
{
if (fi?.Exists ?? false)
{
fi.IsReadOnly = false;
try
{
fi.Delete();
ret = true;
}
catch (IOException) { _sw.SpinOnce(); }
}
else break;
}
return ret;
}
Will edit if explanation is needed.
Upvotes: 0
Reputation: 43023
The answer to your question is: no, there's no safe way of deleting a file and you need to handle IOException
. There may be multiple reasons, e.g.:
In your specific case, check this question: Problems overwriting (re-saving) image when it was set as image source
Upvotes: 2
Reputation: 2568
You should close/dispose the original file stream of the image. Copy them to a MemoryStrean when loading.
Upvotes: 1