Silverlight图像无法显示

时间:2012-08-20 10:12:35

标签: c# silverlight xaml wcf-ria-services ivalueconverter

我正在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中我设置了datagrid的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;
    }
}

提前致谢。

2 个答案:

答案 0 :(得分: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));
            }
        }
    }
}

<强> MainPage.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构造函数提供字节数组   在构建当前实例期间。

要获得正确的数组,请使用MemoryStream类的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())
{
    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 我写了一个小程序来测试你给我的文件(改名为btw文件): 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);
                    }
                }
            }
        }
    }
}

此程序在行var bm = Image.FromStream(fs);

上抛出ArgumentException

因此我认为或者你给我的文件不包含sql中的实际字节数组(也就是你保存错误)或者sql中的字节数组已损坏。但既然你可以真实地看到图像,我认为你把它保存错了。

答案 1 :(得分:1)

<强>更新

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

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设置的流中读取。