Silverlight изображения не отображаются
Я создаю приложение в Silverlight. Сейчас существует только DataGrid. Я использую службу WCF RIA для получения данных из базы данных. Все работает нормально, ожидайте изображения. Я получаю изображения в виде байтового массива и пытаюсь преобразовать их в BitmapImage с помощью Converter. Я хочу показать изображения в RowDetailsTemplate DataGrid.
Вот:
<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;
}
}
Заранее спасибо.
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 во время создания текущего экземпляра.
Чтобы добраться до нужного массива, используйте 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 поврежден. Но так как вы можете видеть изображение, я думаю, что вы сохранили его неправильно.
Обновить:
Этого должно быть достаточно, чтобы назначить 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;
Также, когда вы вызываете GetBuffer в MemoryStream, вы получите массив, который передается в ctor-памяти MemoryStream. В вашем случае вы получите пустой массив или ноль. Я не уверен.
Начальное:
Изменить ConvertByteArrayToBitMapImage
метод к следующему
public BitmapImage ConvertByteArrayToBitMapImage(byte[] imageByteArray) {
BitmapImage img = new BitmapImage();
MemoryStream memStream = new MemoryStream(imageByteArray);
img.SetSource(memStream);
return img;
}
При утилизации MemoryStream с помощью using
-Состояние, поток закрывается. Так что BitmapImage не может читать из потока, который установлен с помощью SetSource
,