简体   繁体   English

WPF字节数组到ImageSource而不使用MemoryStream

[英]WPF Byte Array to ImageSource without using MemoryStream

I have an application that creates WPF Image controls on-the-fly to display images from a SQL Server database table. 我有一个可动态创建WPF图像控件的应用程序,以显示SQL Server数据库表中的图像。 The panels that display the controls get replaced frequently. 显示控件的面板经常更换。 I use MemoryStreams to allow the controls to access the byte arrays loaded from the database. 我使用MemoryStreams允许控件访问从数据库加载的字节数组。 I cannot close these streams as long as the Image controls are displayed and still have the images displayed. 只要显示“图像”控件并且仍然显示图像,我就无法关闭这些流。 My concern is that these streams will be left open until the Garbage Collector gets around to disposing of the Image controls and hopefully closing the streams too. 我担心的是,这些流将一直保持打开状态,直到垃圾回收器开始处理Image控件并希望也关闭这些流为止。 I will probably end up just making sure that I close the streams or dispose of the Image controls before the panels are replaced but would like to know if there is an issue with leaving these streams open and if there is a way around this. 我可能最终只会确保在更换面板之前关闭流或丢弃Image控件,但想知道打开这些流是否存在问题,以及是否有解决办法。

Here's the code that I am using. 这是我正在使用的代码。

public class ImageToSql
{
    private static OpenFileDialog _openFileDialog = new OpenFileDialog();

    static ImageToSql()
    {
        _openFileDialog = new OpenFileDialog();
        _openFileDialog.AddExtension = true;
        _openFileDialog.CheckFileExists = true;
        _openFileDialog.DefaultExt = ".jpg";
        _openFileDialog.Filter = "JPEG files (*.jpg)|*.jpg|All files (*.*)|*.*";
        _openFileDialog.FilterIndex = 1;
        _openFileDialog.Multiselect = false;
    }

    public static BitmapImage LoadImageFromFile(string caption)
    {
        BitmapImage bi = new BitmapImage();

        _openFileDialog.Title = caption;
        if (_openFileDialog.ShowDialog() == true)
        {
            bi.BeginInit();
            bi.StreamSource = File.OpenRead(_openFileDialog.FileName);
            bi.EndInit();
        }

        return bi;
    }

    public static int StoreImage(string connectionString, string sql, string imageParameterName, BitmapImage bitmapImage)
    {
        SqlConnection conn = new SqlConnection(connectionString);
        try
        {
            conn.Open();
            sql += ";SELECT @@IDENTITY";
            using (SqlCommand cmd = new SqlCommand(sql, conn))
            {
                byte[] data = new byte[bitmapImage.StreamSource.Length];
                bitmapImage.StreamSource.Seek(0, SeekOrigin.Begin);
                bitmapImage.StreamSource.Read(data, 0, data.Length);

                cmd.Parameters.Add(imageParameterName, System.Data.SqlDbType.VarBinary, -1).Value = data;
                object obj = cmd.ExecuteScalar();
                return Int32.Parse(obj.ToString());
            }
        }
        finally
        {
            conn.Close();                
        }
    }

    public static BitmapImage RetrieveImage(string connectionString, string sql, string imageIDParameterName, int imageID)
    {
        BitmapImage bi = new BitmapImage();
        SqlConnection conn = new SqlConnection(connectionString);
        try
        {
            conn.Open();
            using (SqlCommand cmd = new SqlCommand(sql, conn))
            {
                cmd.Parameters.Add(imageIDParameterName, System.Data.SqlDbType.Int).Value = imageID;
                byte[] data = (byte[])cmd.ExecuteScalar();

                MemoryStream ms = new MemoryStream(data);
                ms.Seek(0, SeekOrigin.Begin);
                bi.BeginInit();
                bi.StreamSource = ms;
                bi.EndInit();
            }
        }
        finally
        {
            conn.Close();
        }

        return bi;
    }
}

Below is how this code is called. 以下是此代码的调用方式。 "_fileImage" and "_sqlImage" are Image controls on my test Window. “ _fileImage”和“ _sqlImage”是我的测试窗口上的图像控件。 At one point, I was using a stream to read the file from disk in "LoadImageFromFile" and think I was able to close that stream while still displaying the image in the Image control. 有一次,我使用流从“ LoadImageFromFile”中的磁盘读取文件,并认为我能够在仍然在Image控件中显示图像的同时关闭该流。 So, MemoryStream seems to be special somehow. 因此,MemoryStream在某种程度上似乎很特别。

        BitmapImage bi = ImageToSql.LoadImageFromFile("Select Image to Save");
        _fileImage.Source = bi;

        int imageID = ImageToSql.StoreImage(connString,
            "INSERT INTO PV_Image (Description, Image) VALUES ('Some Image', @pImage)",
            "@pImage", bi);

        _sqlImage.Source = ImageToSql.RetrieveImage(connString, 
            "SELECT Image FROM PV_Image WHERE ImageID = @pImageID", 
            "@pImageID", imageID);

You can dispose the memory stream once it is used using the using pattern: 您可以使用using模式在使用完内存流后对其进行处置:

using (Stream stream = new MemoryStream(data))
{
    BitmapImage image = new BitmapImage():
    stream.Position = 0;
    image.BeginInit();
    image.CacheOption = BitmapCacheOption.OnLoad;
    image.StreamSource = stream;
    image.EndInit();
    image.Freeze();
    return image;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM