【问题标题】:C# WPF - Load Image from bytearray into DatagridC# WPF - 将图像从 bytearray 加载到 Datagrid
【发布时间】:2015-10-19 12:27:36
【问题描述】:

我有一个 WPF 表单(我完全是 WPF 的初学者),其中包含一个 Datagrid。这个Datagrid 通过一个简单的List<AudioFile> 获取它的内容。在扩展AudioFile 的类Mp3File 内部(它在PCL 内部)是一个名为GetCoverAsByteArray() 的方法,它以byte[] 的形式返回加载的AudioFile 的封面。 现在我想在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 所说的那样实现了 Converted,现在我的代码如下所示:

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.Data 错误:40:BindingExpression 路径错误:在“对象”“Mp3File”(HashCode=54312533)上找不到“GetCoverAsByteArray()”属性。 BindingExpression:Path=GetCoverAsByteArray(); DataItem='Mp3File' (HashCode=54312533);目标元素是'图像'(名称='');目标属性是'Source'(类型'ImageSource')

System.Windows.Data 错误:40:BindingExpression 路径错误:在“对象”“Mp3File”(HashCode=54312533)上找不到“Key”属性。绑定表达式:路径=键; DataItem='Mp3File' (HashCode=54312533);目标元素是'TextBlock'(名称='');目标属性是“文本”(类型“字符串”)

【问题讨论】:

    标签: c# image datagrid


    【解决方案1】:

    您可以使用 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 元素,如果您不想缓存图像,您可以将位图转换为 bitmapImage 并将其绑定到视图中的图像元素。

    【讨论】:

    • 好吧,我用丹尼斯的回答做到了。我实现了一个名为 CoverByBytes 的新属性并正确设置了绑定。非常感谢大家的帮助
    【解决方案2】:

    数据绑定仅适用于属性。您必须向AudioFile 类添加一个属性才能返回封面数据。如果您出于某些原因不想更改AudioFile,请将其映射/包装到视图模型中,并将属性放入该视图模型中。

    那么你将有两个选择。

    选项 1。

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

    XAML 将如下所示:

    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <Image Source="{Binding CoverAsImageSource}"/>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
    

    选项 2。

    您可以写一个值converterbyte[] 值转换为ImageSource

    在这种情况下,XAML 将如下所示:

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

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

    【讨论】:

    • 对不起,我忘了提到AudioFile 在 PCL 中,所以选项 1 不起作用:/ 在选项 2 中,YourConverterKey 是什么?
    • 我已经提到,您可以将AudionFile 映射到视图模型(或将其包装到视图模型中)。这就是存在视图模型的原因。 YourConverterKey 是您的 IValueConverter 实现的关键,在资源的上方某处声明。见此链接,例如:wpftutorial.net/ValueConverters.html
    猜你喜欢
    • 2016-08-15
    • 2017-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多