【问题标题】:Silverlight images not displayingSilverlight 图像不显示
【发布时间】:2012-08-20 10:12:34
【问题描述】:

我正在 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;
    }
}

提前致谢。

【问题讨论】:

  • 您是否调试并检查是否在转换器中创建了图像?
  • 我在 Converter 类中添加断点。然后我单击 DataGrid 中的一行来查看图像。但是应用程序没有到达断点。所以,有些不对劲。但是什么?
  • 你是如何设置 DataContext 的?
  • 我不确定这是否有问题,因为您使用的是 MemoryStream,但您不应该释放与 BitmapImage 关联的流。
  • 检查您的输出是否有异常,可能是绑定错误。

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


【解决方案1】:

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

无论如何,您都可以在这里找到并下载测试项目: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 我写了一个小程序来测试你给我的文件(顺便说一下重命名的文件): 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 中的字节数组已损坏。但是由于您可以实际看到图像,因此我认为您保存错误。

【讨论】:

  • 说实话我已经在控制台应用程序中测试过字节数组。一切都奏效了。所以我认为字节数组可能会被破坏。
  • @FarhadJabiyev 字节数组确实已损坏。查看我的最新更新
  • 我已经在控制台应用程序中测试过了。然后我将图像保存在驱动器中。显示出来了。我认为这个问题不在这里。不过还是谢谢。
  • 你能把 sql 中的一个 blob 保存到一个文件中,然后放到网上,这样我就可以对其进行一些测试了吗?
  • 有时重新启动 web 服务会有所帮助,或者在构建之前进行清理。有时你可以把头发拉出来......
【解决方案2】:

更新:

在您的方法GamesList 中将blob 直接分配给您的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 时,流将设置为关闭。所以不能从使用SetSource设置的流中读取BitmapImage。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多