`
public class ViewModel : INotifyPropertyChanged {
private string _itemName;
public string ItemName {
get => _itemName;
set { _itemName = value; OnPropertyChanged(); OnPropertyChanged(nameof(ItemImage)); }
}
public BitmapImage ItemImage {
get {
if (string.IsNullOrEmpty(_itemName) || !File.Exists(_itemName)) return null;
var bmp = new BitmapImage();
bmp.BeginInit();
bmp.CacheOption = BitmapCacheOption.OnLoad; // 釋放文件鎖定
bmp.UriSource = new Uri(_itemName, UriKind.Absolute);
bmp.EndInit();
bmp.Freeze(); // 跨線程可用
return bmp;
}
}
}
```xml
[ValueConversion(typeof(string), typeof(BitmapImage))]
public class PathToImageConverter : IValueConverter {
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
if (value is string path && File.Exists(path)) {
var bmp = new BitmapImage();
bmp.BeginInit();
bmp.CacheOption = BitmapCacheOption.OnLoad;
bmp.UriSource = new Uri(path);
bmp.EndInit();
bmp.Freeze();
return bmp;
}
return DependencyProperty.UnsetValue;
}
public object ConvertBack(...) => throw new NotSupportedException();
}
```xml
**不能直接用絕對路徑**。必須:
public class StorageFileToImageConverter : IValueConverter {
public async object Convert(object value, Type targetType, object parameter, string language) {
if (value is StorageFile file) {
var bmp = new BitmapImage();
using (var stream = await file.OpenReadAsync()) {
await bmp.SetSourceAsync(stream);
}
return bmp;
}
return null;
}
// ConvertBack 不實現
}
| 現象 | 原因 | 修正 |
|---|---|---|
| 圖片不顯示、無報錯 | 路徑字符串未轉 BitmapImage | 用 Converter 或 VM 屬性轉換 |
| 第二次打開同圖報錯 "文件被佔用" | BitmapImage 預設鎖定文件 | `CacheOption = BitmapCacheOption.OnLoad` |
| UWP 綁定 C:\ 路徑無效 | 沙箱隔離無權限 | 用 FileOpenPicker / 複製到 LocalFolder |
| 相對路徑 `Images/a.png` 失效 | 基準目錄非專案輸出目錄 | `new Uri("pack://application:,,,/Images/a.png")` 或 `ms-appx:///` |
**WPF:Converter + BitmapImage.OnLoad + Freeze**;**UWP:StorageFile + SetSourceAsync**。絕不直接綁定字符串路徑。