1

我正在 Silverlight 中创建应用程序。现在只有一个 DataGrid。我正在使用 WCF RIA 服务从数据库中获取数据。一切正常,期待图像。我将图像作为字节数组获取并尝试使用 Converter 将它们转换为 BitmapImage。我想在 DataGrid 的 RowDetailsTemplate 中显示图像。

这里是:

    <sdk:DataGrid.RowDetailsTemplate>
        <DataTemplate>
            <StackPanel> 
                <StackPanel>
                    <Image x:Name="thumbNail"  Width="60" Height="60" VerticalAlignment="Center" ImageFailed="thumbNail_ImageFailed"
                           Source="{Binding gameImage,Converter={StaticResource byteToImageConverter}}">
                    </Image>
                </StackPanel>
            </StackPanel>
        </DataTemplate>
    </sdk:DataGrid.RowDetailsTemplate>

和转换器:

public class ByteToImageConverter : IValueConverter
    {
        public BitmapImage ConvertByteArrayToBitMapImage(byte[] imageByteArray)
        {
            BitmapImage img = new BitmapImage();
            using (MemoryStream memStream = new MemoryStream(imageByteArray))
            {
                img.SetSource(memStream);
            }
            return img;
        }

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            BitmapImage img = new BitmapImage();
            if (value != null)
            {
                img = this.ConvertByteArrayToBitMapImage(value as byte[]);
            }
            return img;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return null;
        }
    }

但是没有显示图像。

我的 wcf 服务中的方法是这样的:

   public List<Games> GamesList()
        {
            string gmConn = ConfigurationManager.ConnectionStrings["GamesConnectionString"].ConnectionString;
            var gamesList = new List<Games>();

            using (SqlConnection conn = new SqlConnection(gmConn))
            {
                string sql = @"Select Name, Developer,Longevity,Distributor,Year,State,Type,graphics, gameplay,sound,general,photo From Games join scores on Games.G_ID=Scores.G_ID";
                conn.Open();

                using (SqlCommand cmd = new SqlCommand(sql, conn))
                {
                    SqlDataReader dr = cmd.ExecuteReader();
                    if (dr != null)
                        while (dr.Read())
                        {
                            Games game = new Games
                            {
                                Name = dr.GetString(0),
                                developer = dr.GetString(1),
                                Longevity = dr.GetInt32(2),
                                Distributor = dr.GetString(3),
                                Year = dr.GetString(4),
                                State = dr.GetString(5),
                                Type = dr.GetString(6),
                                Graphics = dr.GetDouble(7),
                                Gameplay = dr.GetDouble(8),
                                Sound = dr.GetDouble(9),
                                General = dr.GetDouble(10)
                            };
                            if (!dr.IsDBNull(11))
                            {
                                byte[] blob = new byte[(dr.GetBytes(11, 0, null, 0, int.MaxValue))];
                                dr.GetBytes(11, 0, blob, 0, blob.Length);
                                using (MemoryStream ms = new MemoryStream())
                                {
                                    ms.Write(blob, 0, blob.Length - 0);
                                    Bitmap bm = (Bitmap)Image.FromStream(ms);
                                    using (MemoryStream msJpg = new MemoryStream())
                                    {
                                        bm.Save(msJpg, ImageFormat.Jpeg);
                                        game.gameImage = msJpg.GetBuffer();
                                    }
                                }
                            }
                            gamesList.Add(game);
                        }
                    return gamesList;
                }
            }
        }

在 mainPage.xaml.cs 我正在设置我的数据网格的 ItemsSource。

public partial class MainPage : UserControl
{
    public MainPage()
    {
        InitializeComponent();

        SampleServiceClient client = new SampleServiceClient();

        client.GamesListCompleted += new EventHandler<GamesListCompletedEventArgs>(client_GamesListCompleted);
        client.GamesListAsync();
    }

    void client_GamesListCompleted(object sender, GamesListCompletedEventArgs e)
    {
        CustomerGrid.ItemsSource = e.Result;
    }
}

提前致谢。

4

2 回答 2

2

我用您的代码创建了一个简单的测试项目,但无法重现您的问题。字节数组可能已损坏?(只是猜测..)

无论如何,您可以在这里找到并下载测试项目:https ://skydrive.live.com/redir?resid=DEB5DDFF6A505390!278我制作了一个带有嵌入式图像的简单项目。我打开该图像并将其转换为字节数组。然后我使用绑定来显示图像。

MainPage.xaml.cs

using System;
using System.ComponentModel;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Resources;

namespace SilverlightTest
{
    public partial class MainPage : UserControl, INotifyPropertyChanged
    {
        public MainPage()
        {
            InitializeComponent();

            using (var ms = new MemoryStream())
            {
                StreamResourceInfo sr = Application.GetResourceStream(new Uri("SilverlightTest;component/Koala.jpg", UriKind.Relative));
                sr.Stream.CopyTo(ms);
                _photo = ms.ToArray();
            }

            this.DataContext = this;
        }

        private byte[] _photo;
        public byte[] Photo
        {
            get
            {
                return _photo;
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string prop)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(prop));
            }
        }
    }
}

主页.xaml

<UserControl x:Class="SilverlightTest.MainPage"
    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:SilverlightTest"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">
    <UserControl.Resources>
        <local:ByteToImageConverter x:Name="byteToImageConverter" />
    </UserControl.Resources>

    <Grid x:Name="LayoutRoot" Background="White">
        <Image Width="320" Height="240" VerticalAlignment="Center" Source="{Binding Path=Photo, Converter={StaticResource byteToImageConverter}}" />
    </Grid>
</UserControl>

并且图像作为资源包含在项目中。

更新

我看到您在项目中使用了以下代码:

byte[] blob = new byte[(dr.GetBytes(11, 0, null, 0, int.MaxValue))];
dr.GetBytes(11, 0, blob, 0, blob.Length);
using (MemoryStream ms = new MemoryStream())
{
    ms.Write(blob, 0, blob.Length - 0);
    Bitmap bm = (Bitmap)Image.FromStream(ms);
    using (MemoryStream msJpg = new MemoryStream())
    {
        bm.Save(msJpg, ImageFormat.Jpeg);
        game.gameImage = msJpg.GetBuffer();
    }
}

此代码将不起作用。您使用GetBuffer()此代码返回(根据 msdn):

创建此流的字节数组,或者如果在当前实例的构造期间未向 MemoryStream 构造函数提供字节数组,则为基础数组。

要获得正确的数组,请使用ToArray()MemoryStream 类的函数:

byte[] blob = new byte[(dr.GetBytes(11, 0, null, 0, int.MaxValue))];
dr.GetBytes(11, 0, blob, 0, blob.Length);
using (MemoryStream ms = new MemoryStream())
{
    ms.Write(blob, 0, blob.Length - 0);
    Bitmap bm = (Bitmap)Image.FromStream(ms);
    using (MemoryStream msJpg = new MemoryStream())
    {
        bm.Save(msJpg, ImageFormat.Jpeg);
        game.gameImage = msJpg.ToArray();
    }
}

并进行一些重构:

byte[] blob = new byte[(dr.GetBytes(11, 0, null, 0, int.MaxValue))];
dr.GetBytes(11, 0, blob, 0, blob.Length);
using (MemoryStream ms = new MemoryStream(blob))
{
    Bitmap bm = (Bitmap)Image.FromStream(ms);
    using (MemoryStream msJpg = new MemoryStream())
    {
        bm.Save(msJpg, ImageFormat.Jpeg);
        game.gameImage = msJpg.ToArray();
    }
}

更新 2 我写了一个小程序来测试你给我的文件(顺便说一下重命名文件): SilverlightTestV2.zip

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;

namespace ByteTransformer
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var fs = File.OpenRead("byteArray.dat"))
            {
                var bm = Image.FromStream(fs);

                using (MemoryStream msJpg = new MemoryStream())
                {
                    bm.Save(msJpg, ImageFormat.Jpeg);
                    using (var ts = File.Create("out.jpg"))
                    {
                        var img = msJpg.ToArray();
                        ts.Write(img, 0, img.Length);
                    }
                }
            }
        }
    }
}

这个程序在行上抛出一个 ArgumentException:var bm = Image.FromStream(fs);

因此,我认为或者您给我的文件不包含 sql 中的实际字节数组(也就是您保存错误),或者 sql 中的字节数组已损坏。但是由于您可以实际看到图像,因此我认为您将其保存错误。

于 2012-08-20T10:59:59.983 回答
1

更新:

在您的方法中将 blob 直接分配给您的 gameImage-Property 就足够了GamesList。其他代码应该没用。

byte[] blob = new byte[(dr.GetBytes(11, 0, null, 0, int.MaxValue))];
dr.GetBytes(11, 0, blob, 0, blob.Length);
game.gameImage = blob;

此外,当您在 MemoryStream 上调用GetBuffer时,您将获得在 MemoryStream 的 ctor 中传递的数组。在您的情况下,您将得到一个空数组或 null。我不知道。

最初的:

将方法更改ConvertByteArrayToBitMapImage为以下

 public BitmapImage ConvertByteArrayToBitMapImage(byte[] imageByteArray) {
   BitmapImage img = new BitmapImage();
   MemoryStream memStream = new MemoryStream(imageByteArray);

   img.SetSource(memStream);

   return img;
 }

当您使用using-Statement 处理 MemoryStream 时,流将设置为关闭。所以不能从使用设置的流中读取 BitmapImage SetSource

于 2012-08-20T10:32:24.367 回答