ネタ元
ListBox にイメージをデータバインドした時に画像を削除する方法
確かにWPFでImageのSourceにstringをBindingしたときは、ファイルがしばらくロックされちゃって困ることがあります。これをロックされないようにするには、自前のコンバーターでファイルロックをしないようにする必要があります。
ロックされる版のアプリ
以下のようにピクチャーフォルダのjpgへのパスをDataContextにつっこみます。
using System; using System.IO; using System.Linq; using System.Windows; namespace ImageApp { /// <summary> /// MainWindow.xaml の相互作用ロジック /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); var picturesFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures); this.DataContext = Directory.GetFiles(picturesFolderPath, "*.jpg", SearchOption.AllDirectories) .ToArray(); } } }
そして、それをListBoxのItemsSourceにバインドしてItemTemplateでImageのSourceにバインドします。
<Window x:Class="ImageApp.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:ImageApp" mc:Ignorable="d" Title="MainWindow" Height="350" Width="525"> <Grid> <ListBox ItemsSource="{Binding}"> <ListBox.ItemTemplate> <DataTemplate> <Image Source="{Binding}" Height="50" /> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </Grid> </Window>
実行すると以下のように表示されます。
このときファイルを消そうとすると以下のようにロックされてることが確認できます。
ロックされないようにする
デフォルトのコンバーターがダメなので自前コンバーターを仕込みます。
using System; using System.Globalization; using System.IO; using System.Windows.Data; using System.Windows.Media.Imaging; namespace ImageApp { public class ImageConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var path = (string)value; using (var fs = new FileStream(path, FileMode.Open)) { var decoder = BitmapDecoder.Create( fs, BitmapCreateOptions.None, BitmapCacheOption.OnLoad); var bmp = new WriteableBitmap(decoder.Frames[0]); bmp.Freeze(); return bmp; } } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } }
参考: http://pieceofnostalgy.blogspot.jp/2012/02/wpf-bitmapsource.html
あとは、このConverterをImageのSourceに設定します。
<Window x:Class="ImageApp.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:ImageApp" mc:Ignorable="d" Title="MainWindow" Height="350" Width="525"> <Window.Resources> <local:ImageConverter x:Key="ImageConverter"/> </Window.Resources> <Grid> <ListBox ItemsSource="{Binding}"> <ListBox.ItemTemplate> <DataTemplate> <Image Source="{Binding Converter={StaticResource ImageConverter}}" Height="50" /> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </Grid> </Window>
実行するとちゃんと画像が表示されて、画像の削除もできるようになります。