c# WPF -加载图像从字节数组到数据网格

本文关键字:数组 数据 数据网 网格 字节数 字节 WPF 加载 图像 | 更新日期: 2023-09-27 18:18:31

我有一个WPF形式(我完全是一个初学者在WPF),其中包含一个Datagrid。这个Datagrid通过一个简单的List<AudioFile>得到它的内容。在扩展AudioFileMp3File类内部(它在PCL内部)是一个名为GetCoverAsByteArray()的方法,它将加载的AudioFile的覆盖返回为byte[]。现在我想在DataGrid中显示封面图像,但我不知道怎么做。你能帮帮我吗?

这是我目前为止的代码:

<DataGrid x:Name="tvFiles" AutoGenerateColumns="False" MaxColumnWidth="1000" Margin="10,95,10,10" MinHeight="100">
                    <DataGrid.Columns>
                        <DataGridTemplateColumn Header="Cover" Width="*" MinWidth="64">
                            <DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                    
                                </DataTemplate>
                            </DataGridTemplateColumn.CellTemplate>
                        </DataGridTemplateColumn>
                        <DataGridTextColumn Header="Filename" Width="*" MinWidth="100" Binding="{Binding Filename}"/>
                        <DataGridTextColumn Header="Artist" Width="*" MinWidth="50" Binding="{Binding Artist}"/>
                        <DataGridTextColumn Header="Title" Width="*" MinWidth="50" Binding="{Binding Title}"/>
                        <DataGridTextColumn Header="Album" Width="*" MinWidth="50" Binding="{Binding Album}"/>
                        <DataGridTextColumn Header="BPM" Width="*" MinWidth="50" Binding="{Binding BPM}"/>
                        <DataGridTextColumn Header="Comment" Width="*" MinWidth="100" Binding="{Binding Comment}"/>
                        <DataGridTextColumn Header="Year" Width="*" MinWidth="40" Binding="{Binding Year}"/>
                        <DataGridTextColumn Header="Key" Width="*" MinWidth="40" Binding="{Binding Key}"/>
                        <DataGridTextColumn Header="Bitrate" Width="*" MinWidth="60" Binding="{Binding Bitrate}"/>
                        <DataGridTextColumn Header="Length" Width="*" MinWidth="50" Binding="{Binding Duration}"/>
                    </DataGrid.Columns>
                </DataGrid>

谢谢你的帮助

编辑1

我像Dennis说的那样实现了转换,现在我的代码看起来像这样:

class ByteArrayToImageConverter : IValueConverter {
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
        byte[] bytes = (byte[])value;
        if (bytes == null || bytes.Length == 0) return null;
        var image = new BitmapImage();
        using (var mem = new MemoryStream(bytes)) {
            mem.Position = 0;
            image.BeginInit();
            image.CreateOptions = BitmapCreateOptions.PreservePixelFormat;
            image.CacheOption = BitmapCacheOption.OnLoad;
            image.UriSource = null;
            image.StreamSource = mem;
            image.EndInit();
        }
        image.Freeze();
        return image;
    }
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
        throw new NotImplementedException();
    }
}
<Window.Resources>
    <local:ByteArrayToImageConverter x:Key="converter" />
</Window.Resources>
<DataGrid x:Name="tvFiles" AutoGenerateColumns="False" MaxColumnWidth="1000" Margin="10,95,10,10" MinHeight="100">
                    <DataGrid.Columns>
                        <DataGridTemplateColumn Header="Cover" Width="*" MinWidth="64">
                            <DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                    <Image Source="{Binding GetCoverAsByteArray, Converter={StaticResource converter}}"/>
                                </DataTemplate>
                            </DataGridTemplateColumn.CellTemplate>
                        </DataGridTemplateColumn>
                        <DataGridTextColumn Header="Filename" Width="*" MinWidth="100" Binding="{Binding Filename}"/>
                        <DataGridTextColumn Header="Artist" Width="*" MinWidth="50" Binding="{Binding Artist}"/>
                        <DataGridTextColumn Header="Title" Width="*" MinWidth="50" Binding="{Binding Title}"/>
                        <DataGridTextColumn Header="Album" Width="*" MinWidth="50" Binding="{Binding Album}"/>
                        <DataGridTextColumn Header="BPM" Width="*" MinWidth="50" Binding="{Binding BPM}"/>
                        <DataGridTextColumn Header="Comment" Width="*" MinWidth="100" Binding="{Binding Comment}"/>
                        <DataGridTextColumn Header="Year" Width="*" MinWidth="40" Binding="{Binding Year}"/>
                        <DataGridTextColumn Header="Key" Width="*" MinWidth="40" Binding="{Binding Key}"/>
                        <DataGridTextColumn Header="Bitrate" Width="*" MinWidth="60" Binding="{Binding Bitrate}"/>
                        <DataGridTextColumn Header="Length" Width="*" MinWidth="50" Binding="{Binding Duration}"/>
                    </DataGrid.Columns>
                </DataGrid>

现在我得到以下消息时,加载AudioFile到Datagrid:

System.Windows。数据错误:40:BindingExpression路径错误:'GetCoverAsByteArray()'属性未在'对象''Mp3File' (HashCode=54312533)'上找到。BindingExpression:路径= GetCoverAsByteArray ();DataItem = ' Mp3File ' (HashCode = 54312533);目标元素是'Image' (Name= ");目标属性为'Source'(类型为'ImageSource')

System.Windows。数据错误:40:BindingExpression路径错误:'Key'属性在'对象''Mp3File' (HashCode=54312533)'上找不到。BindingExpression: =关键路径;DataItem = ' Mp3File ' (HashCode = 54312533);目标元素是'TextBlock' (Name= ");目标属性为"Text"(类型为"String")

c# WPF -加载图像从字节数组到数据网格

数据绑定仅适用于属性。您必须向AudioFile类添加属性以返回覆盖数据。如果出于某些原因不想更改AudioFile,那么将其映射/包装到视图模型中,并将属性放置到该视图模型中。

那么你有两个选择。

<标题>选项1。

代替public byte[] CoverAsByteArray { get; },你可以写一个属性,它返回ImageSource实例,类似于public ImageSource CoverAsImageSource { get; }

XAML看起来像这样:

<DataGridTemplateColumn.CellTemplate>
    <DataTemplate>
        <Image Source="{Binding CoverAsImageSource}"/>
    </DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<标题>选项2。

可以编写一个值转换器,将byte[]的值转换为ImageSource的值。

在本例中,XAML看起来像这样:

<DataGridTemplateColumn.CellTemplate>
    <DataTemplate>
        <Image Source="{Binding CoverAsByteArray, Converter={StaticResource YourConverterKey}}"/>
    </DataTemplate>
</DataGridTemplateColumn.CellTemplate>

假设byte[]表示位图,您可以使用,例如,此答案将其转换为适当的图像源

您可以使用Microsoft.WindowsAPICodePack.Shell从mp3文件中获取图像

private string cacheLocalFile(string mp3fileName)
    {
        try
        {
            using (var shell = ShellFile.FromParsingName(mp3fileName))
            {
                Bitmap bmp = shell.Thumbnail.Bitmap;
                var cachedFileName = shell.Properties.System.FileName.Value;
                bmp.Save(Path.Combine(AppCacheDirectory, cachedFileName), ImageFormat.Jpeg);
                bmp.Dispose();
                return Path.Combine(AppCacheDirectory, cachedFileName);
            }
        }
        catch
        {
            return String.Empty;
        }
    }

你得到了缩略图,保存到文件中并将src文件返回到Image元素,如果你不想缓存图像你可以将bitmap转换为bitmapImage并将其绑定到视图中的Image元素