如何将Linq-To-Sql加载的SQL Image转换为WPF ImageBrush.ImageSource
解决Linq-To-Sql加载SQL Image类型转WPF ImageBrush.ImageSource的问题
嘿,我来帮你搞定这个问题!你其实走进了一个小误区——根本不需要把内存里的图像转换成URI,WPF的ImageSource可以直接从字节数组(SQL的Image类型本质就是byte数组)通过流来创建,这才是最直接高效的方式。
步骤1:编写字节数组转BitmapImage的工具方法
WPF里用BitmapImage作为ImageSource的实现类,我们可以写一个方法把从数据库拿到的byte数组转成它:
Imports System.IO Imports System.Windows.Media.Imaging Private Function ByteArrayToBitmapImage(ByVal byteArray As Byte()) As BitmapImage ' 空数组直接返回null If byteArray Is Nothing OrElse byteArray.Length = 0 Then Return Nothing End If Using stream As New MemoryStream(byteArray) Dim bitmapImage As New BitmapImage() bitmapImage.BeginInit() ' 必须设置这个选项!否则流关闭后图像会失效 bitmapImage.CacheOption = BitmapCacheOption.OnLoad bitmapImage.StreamSource = stream bitmapImage.EndInit() ' 可选:冻结图像提升性能,尤其适合绑定场景 bitmapImage.Freeze() Return bitmapImage End Using End Function
步骤2:调整绑定的数据源属性
你XAML里绑定的Picture属性,类型应该是ImageSource(而不是byte数组或者System.Drawing.Image)。假设你用的是ViewModel模式,修改你的类:
Imports System.ComponentModel Imports System.Windows.Media Public Class YourViewModel Implements INotifyPropertyChanged Private _picture As ImageSource Public Property Picture As ImageSource Get Return _picture End Get Set(value As ImageSource) _picture = value ' 触发属性变更通知,让UI更新 OnPropertyChanged(NameOf(Picture)) End Set End Property ' INotifyPropertyChanged接口实现 Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged Private Sub OnPropertyChanged(propertyName As String) RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName)) End Sub ' 加载数据时调用这个方法 Public Sub LoadImageFromDatabase() ' 从Linq-To-Sql获取byte数组(SQL的Image类型对应byte[]) Dim imageBytes As Byte() = listOfImage(...) ' 替换成你的实际数据获取逻辑 ' 转换后赋值给Picture属性 Me.Picture = ByteArrayToBitmapImage(imageBytes) End Sub End Class
步骤3:确认XAML和DataContext
你的XAML代码已经写对了,只要确保你的Rectangle所在的控件的DataContext设置为上面的ViewModel实例就行:
<Rectangle Grid.Row="1" RadiusX="3" RadiusY="3" Width="110" Height="80"> <Rectangle.Fill> <ImageBrush x:Name="brush" ImageSource="{Binding Picture}"/> </Rectangle.Fill> </Rectangle>
关键注意点
- 不要用System.Drawing.Image中转:你代码里提到的
System.Drawing.Image是WinForms的类型,WPF完全不需要它,直接处理byte数组更高效,也避免了跨UI框架的转换问题。 - 必须设置BitmapCacheOption.OnLoad:因为我们用的是Using块包裹MemoryStream,流会在块结束后被释放,如果不设置这个选项,BitmapImage会延迟加载,导致流关闭后图像无法显示。
- Freeze()的作用:调用这个方法可以让BitmapImage变成只读对象,不仅能提升WPF的渲染性能,还允许在非UI线程创建图像(不过绑定操作还是要在UI线程)。
内容的提问来源于stack exchange,提问作者joebohen




