hi,
Follow The following steps:
Step 1: Open Visual Studio 2008 > File > New Project > Select the language (C# or VB) > Select ‘Silverlight’ in the Project Types > from the templates, select ‘Silverlight Application’. Type a name ‘AccessImagesInDatabase’ and location for the project and click ok.
Note: If you are unable to view the templates, you do not have Microsoft Silverlight Tools for Visual Studio 2008. Check out this
link to see how to obtain it.
Step 2: You will observe that a default page called ‘Page.xaml’ gets created. Remove the <Grid> and replace it with <Canvas> and set its background to Gray. Now add a few controls like the Image, TextBlock, TextBox and Buttons inside the Canvas. After setting a few layout properties, the markup will look similar to the following:
<UserControl x:Class="AccessImagesInDatabase.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/
presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Canvas x:Name="LayoutRoot" Background="Gray">
<Image x:Name="img1" Width="300" Height="230" Visibility="Visible" HorizontalAlignment="Center"></Image>
<TextBlock x:Name="lblEmployee" Text="EmployeeID" Canvas.Top="244" Canvas.Left="10"/>
<TextBox x:Name="txtEmpID" Canvas.Top="240" Canvas.Left="110" Width="40" Text="1"/>
<Button x:Name="btnImage" Canvas.Top="270" Canvas.Left="110" Content="Fetch" Click="btnImage_Click"></Button>
</Canvas>
</UserControl>
The ‘btnImage’ is for fetching the image. ‘txtEmpId’ is the textbox where we will enter the EmployeeId whose image is to be retrieved from the database.
Step 3: Since we are retrieving the images from the database, we would need a connection string. Add the following connection string to your web.config
<connectionStrings>
<add name="NorthwindConnectionString" connectionString="Data Source=(local);Initial Catalog=Northwind;Integrated Security=True"
providerName="System.Data.SqlClient" />
</connectionStrings>
Step 4: We will be using an HttpHandler to pull images from the database. Handlers provide a lot of flexibility while accessing server-side resources. To create an Http handler, right click project AccessImagesInDatabase.Web > Add New Item > Generic Handler > DisplayImage.ashx. Add the following code to the handler.
C#
using System;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Drawing.Imaging;
using System.Web;
using System.Web.Services;
namespace AccessImagesInDatabase.Web
{
///<summary>
/// Summary description for $codebehindclassname$
///</summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class DisplayImage : IHttpHandler
{
byte[] empPic = null;
long seq = 0;
public void ProcessRequest(HttpContext context)
{
Int32 empno;
if (context.Request.QueryString["id"] != null)
empno = Convert.ToInt32(context.Request.QueryString["id"]);
else
throw new ArgumentException("No parameter specified");
// Convert Byte[] to Bitmap
Bitmap newBmp = ConvertToBitmap(ShowEmpImage(empno));
if (newBmp != null)
{
newBmp.Save(context.Response.OutputStream, ImageFormat.Jpeg);
newBmp.Dispose();
}
}
// Convert byte array to Bitmap (byte[] to Bitmap)
protected Bitmap ConvertToBitmap(byte[] bmp)
{
if (bmp != null)
{
TypeConverter tc = TypeDescriptor.GetConverter(typeof(Bitmap));
Bitmap b = (Bitmap)tc.ConvertFrom(bmp);
return b;
}
return null;
}
public byte[] ShowEmpImage(int empno)
{
string conn = ConfigurationManager.ConnectionStrings["NorthwindConnectionString"].ConnectionString;
SqlConnection connection = new SqlConnection(conn);
string sql = "SELECT photo FROM Employees WHERE EmployeeID = @ID";
SqlCommand cmd = new SqlCommand(sql, connection);
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("@ID", empno);
connection.Open();
SqlDataReader dr = cmd.ExecuteReader();
if (dr.Read())
{
seq = dr.GetBytes(0, 0, null, 0, int.MaxValue) - 1;
empPic = new byte[seq + 1];
dr.GetBytes(0, 0, empPic, 0, Convert.ToInt32(seq));
connection.Close();
}
return empPic;
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
The steps for retrieving images from database, using the handler are as follows:
1. The EmployeeID whose image is to be retrieved, is passed to the handler via query string. We use the Request.QueryString[“id”] to retrieve the EmployeeID(emp_id) from the handler url. The ID is then passed to the ‘ShowEmpImage()’ method where the image is fetched from the database using SqlDataReader and returned in a byte[] object.
2. We pass this byte[] to the ConvertToBitmap() function where we use the TypeConverter class to convert a byte array to bitmap.
3. The last step is to save the image to the page's output stream and indicate the image format as shown here convBmp.Save(context.Response.OutputStream, ImageFormat.Jpeg)
Note: Silverlight does not support .bmp images. For this reason, we set the ImageFormat to Jpeg while saving the image to the OutputStream.
Step 5: The next step is to call this handler from our Silverlight application.
C#
using System.Windows.Media.Imaging;
public partial class Page : UserControl
{
public Page()
{
InitializeComponent();
}
private void btnImage_Click(object sender, RoutedEventArgs e)
{
string imgUri = "http://localhost:57711/DisplayImage.ashx?id=" + Convert.ToInt32(txtEmpID.Text).ToString();
img1.Source = new BitmapImage(new Uri(imgUri, UriKind.Absolute));
}
}
Fetching Images on Demand using the WebClient class
The WebClient class provides functionality for initiating the download request, monitoring the progress of the download, and then finally retrieving the content requested. You can also cancel a download in progress. Let us modify our sample to see how we can use the WebClient class to download images
You need to import the System.Net and System.Windows.Media.Imaging namespaces. Also we will be using event-handlers while using the WebClient, since all requests are asynchronous.
The event-handler we will use is the OpenReadCompleted event handler which occurs when an asynchronous resource-read operation is completed. To request the image as a stream, we will use the OpenReadAsync method of the WebClient. Let us see some code:
First, add a button and a label control to the Page.Xaml. The ‘btnCancel’ is for cancelling the image fetch operation. The ‘txtProgress’ is for displaying status messages at the time of fetching the image and cancelling the operation.
<TextBlock x:Name="txtProgress" Canvas.Top ="240" Canvas.Left="160" Text="" FontSize="10" />
<Button x:Name="btnCancel" Canvas.Top="270" Canvas.Left="150" Content="Cancel" Click="btnCancel_Click"></Button>
C#
public partial class Page : UserControl
{
WebClient wc = null;
public Page()
{
InitializeComponent();
}
private void btnImage_Click(object sender, RoutedEventArgs e)
{
string imgUri = "http://localhost:57711/DisplayImage.ashx?id=" + Convert.ToInt32(txtEmpID.Text).ToString();
txtProgress.Text = String.Empty;
wc = new WebClient();
wc.OpenReadCompleted += new OpenReadCompletedEventHandler(wc_OpenReadCompleted);
wc.OpenReadAsync(new Uri(imgUri, UriKind.Absolute));
txtProgress.Text = "Fetching Image...";
//img1.Source = new BitmapImage(new Uri(s, UriKind.Absolute));
}
void wc_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
if (e.Error == null)
{
try
{
BitmapImage image = new BitmapImage();
image.SetSource(e.Result);
img1.Source = image;
txtProgress.Text = String.Empty;
}
catch(Exception ex)
{
txtProgress.Text = "Error while fetching image";
}
}
}
private void btnCancel_Click(object sender, RoutedEventArgs e)
{
if (wc.IsBusy)
{
wc.CancelAsync();
txtProgress.Text = "Image fetch cancelled! ";
}
}
}