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

コードを使用して簡単なテスト プロジェクトを作成しましたが、問題を再現できませんでした。バイト配列が壊れている可能性がありますか? (ただの推測です..)

いずれにせよ、ここでテスト プロジェクトを見つけてダウンロードできます。その画像を開き、バイト配列に変換しました。次に、バインディングを使用して画像を表示しました。

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

アップデート:

メソッドの gameImage-Property に blob を直接割り当てるだけで十分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;
 }

-Statementを使用して MemoryStream をusing破棄すると、ストリームはクローズに設定されます。を使用して設定されたストリームから BitmapImage を読み取ることはできませんSetSource

于 2012-08-20T10:32:24.367 に答える