2013-11-10 78 views
3

这是发生了一个图片库WPF应用程序,其中显示了列表框和所选图像缩略图使用XAML异常在FileInfo.Delete - IOException异常

的问题 - 有没有办法安全地删除当前选中的图像没有得到IOException?

仅供参考 - 用户拥有所有权限的目录,没有其他进程正在使用该文件

下面的代码删除文件

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(); 
} 

的例外是

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() 

用于缩略图的XAML是

<ListBox 
    IsSynchronizedWithCurrentItem="True" 
    Name="PhotosListBox" 
    Style="{StaticResource PhotoListBoxStyle}" 
    Margin="5" 
    SelectionMode="Extended" 
    ItemsSource="{Binding ViewList}" 
    SelectedIndex="0" 
    SelectionChanged="PhotosListBox_SelectionChanged" 
    > 

.... //资源XAML是....

<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> 

全尺寸图像XAML仅仅是

<Image Source="{Binding SelectedPhoto.FilePath}" HorizontalAlignment="Center" VerticalAlignment="Center" /> 

回答

2

回答你的问题是:没有,没有安全删除文件的方法,你需要处理IOException。可能有多种原因,如:

  • 您可能没有访问权限以删除文件
  • 该文件是由另一个进程使用(某人/某物人打开该文件)
  • 的文件已经被删除,不存在

在特定情况下,检查了这个问题:Problems overwriting (re-saving) image when it was set as image source

+0

感谢,更新了上面的问题,简而言之,用户是admin,没有其他进程正在使用该文件,FILE存在并且当前显示在缩略图和另一个图像控件中 – Kumar

+0

您可以尝试手动删除文件?那样有用吗? – Szymon

+0

我更新了答案 – Szymon

1

您应该关闭/处理图像的原始文件流。加载时将它们复制到MemoryStrean。

+0

这个绑定是通过使用隐喻完成的,所以没有MemoryStream来处置 – Kumar

+0

这个作品呢!但选择的答案是少代码 – Kumar

+0

库马尔我会改变这个比喻。绑定到照片的实际内存副本,而不是保持文件句柄打开。 – atomaras

0
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; 
    } 

如果需要说明,将进行编辑。