Search code examples
c#silverlightxamlwcf-ria-servicesivalueconverter

Silverlight images not displaying


I am creating application in Silverlight. There is only a DataGrid right now. I am using WCF RIA Service for getting datas from database. Everything works fine expect Images. I am getting images as byte array and trying to convert them to BitmapImage using Converter. I want to show images in RowDetailsTemplate of DataGrid.

Here it is:

    <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>

And converter:

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;
        }
    }

But images are not displaying.

The method in my wcf service is like that:

   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;
                }
            }
        }

And in mainPage.xaml.cs I am setting ItemsSource of my datagrid.

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;
    }
}

Thanks in advance.


Solution

  • I have created a simple test project with your code and I could not recreate your problem. It might be the case that the byte array is corrupted? (Just a guess..)

    Any way, you can find and download the test project here: https://skydrive.live.com/redir?resid=DEB5DDFF6A505390!278 I have made a simple project with an embedded image. I opened that image and converted it into a byte array. Then I used binding to display the image.

    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>
    

    And the image was included in the project as a resource.

    UPDATE

    I saw you used the following code in your project:

    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();
        }
    }
    

    This code won't work. You use GetBuffer() this code returns (according to msdn):

    The byte array from which this stream was created, or the underlying array if a byte array was not provided to the MemoryStream constructor during construction of the current instance.

    To get to right array use the ToArray() function of the MemoryStream class:

    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();
        }
    }
    

    And with a little refactoring:

    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();
        }
    }
    

    UPDATE 2 I wrote a little program to test the file you gave me (renamed the file 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);
                        }
                    }
                }
            }
        }
    }
    

    This program throws an ArgumentException on the line: var bm = Image.FromStream(fs);

    Hence I think that or the file you gave me doesn't contain the actual byte array from the sql (aka you saved it wrong) or the byte array in the sql is corrupt. But since you can actual see the image I think you saved it wrong.