Create a Picture Album using ListView in ASP.NET 3.5
In this article, we will see how to create a Picture Album using the ListView control. We will explore the GroupTemplate of ListView and explore how we can group multiple images together in the ListView, thereby creating an album effect.
We will learn how to upload an image and then display the uploaded image on the same page in an ‘album mode’ using the ListView. At the end of this article, you will also learn how to use the different templates of a ListView. If you are unfamiliar with the ListView control, I suggest you to read my article Exploring the ListView control in ASP.NET 3.5 to get an understanding of the same. To keep the article simple and easy to understand, I have not covered any validations associated with image control or other control. The article also does not suggest you best practices. In this article, we will only discuss how to read images from the database and display it in the ListView control, and that would be the focus for this article. I assume you have some knowledge of creating ASP.NET 3.5 websites. We will be using Visual Studio 2008.
Let us start off by first creating a sample database and adding a table to it. We will call the database ‘PictureAlbum’ and the table will be called ‘Album’. This table will contain an image column along with some other columns. Run the following script in your SQL 2005 Query window (or server explorer) to construct the database and the table.
CREATE DATABASE [PictureAlbum]
GO
USE [PictureAlbum]
GO
CREATE TABLE Album
(
pic_id int IDENTITY NOT NULL,
picture_tag varchar(50),
pic image
)
Step 1: Create a new ASP.NET website. In the code-behind, add the following namespace
C#
using System.Data.SqlClient;
VB.NET
Imports System.Data.SqlClient
Step 2: Drag and drop two label and one textbox control. Also drag drop a FileUpload control and a button control to upload the selected image on button click. As mentioned earlier, there are no validations performed. The source would look similar to the following:
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
Image
<asp:Label ID="lblTags" runat="server" Text="Tags"></asp:Label>
<asp:TextBox ID="txtTags" runat="server"></asp:TextBox>
<br />
<asp:Label ID="lblImage" runat="server" Text="Upload Picture"></asp:Label>
<asp:FileUpload ID="imgUpload" runat="server" />
<br />
<br />
<asp:Button ID="btnSubmit" runat="server" onclick="btnSubmit_Click"
Text="Submit" />
 <asp:Label ID="lblResult" runat="server" ForeColor="#0066FF"></asp:Label>
<br />
<hr />
</div>
</form>
</body>
</html>
Also in the web.config, add a <connectionStrings> tag as displayed below:
<connectionStrings>
<add name="albumConnString" connectionString="Data Source=(local); Initial Catalog = PictureAlbum; Integrated Security=True;"providerName="System.Data.SqlClient" />
</connectionStrings>
Step 3: In the button click event, add the following code:
C#
protected void btnSubmit_Click(object sender, EventArgs e)
{
SqlConnection connection = null;
try
{
FileUpload img = (FileUpload)imgUpload;
Byte[] imgByte = null;
if (img.HasFile && img.PostedFile != null)
{
//To create a PostedFile
HttpPostedFile File = imgUpload.PostedFile;
//Create byte Array with file len
imgByte = new Byte[File.ContentLength];
//force the control to load data in array
File.InputStream.Read(imgByte, 0, File.ContentLength);
}
// Insert the picture tag and image into db
string conn = ConfigurationManager.ConnectionStrings["albumConnString"].ConnectionString;
connection = new SqlConnection(conn);
connection.Open();
string sql = "INSERT INTO Album(picture_tag,pic) VALUES(@tag,@pic) SELECT @@IDENTITY";
SqlCommand cmd = new SqlCommand(sql, connection);
cmd.Parameters.AddWithValue("@tag", txtTags.Text);
cmd.Parameters.AddWithValue("@pic", imgByte);
int id = Convert.ToInt32(cmd.ExecuteScalar());
lblResult.Text = String.Format("Picture ID is {0}", id);
}
catch
{
lblResult.Text = "There was an error";
}
finally
{
connection.Close();
}
}
VB.NET
Protected Sub btnSubmit_Click(ByVal sender As Object, ByVal e As EventArgs)
Dim connection As SqlConnection = Nothing
Try
Dim img As FileUpload = CType(imgUpload, FileUpload)
Dim imgByte As Byte() = Nothing
If img.HasFile AndAlso Not img.PostedFile Is Nothing Then
'To create a PostedFile
Dim File As HttpPostedFile = imgUpload.PostedFile
'Create byte Array with file len
imgByte = New Byte(File.ContentLength - 1){}
'force the control to load data in array
File.InputStream.Read(imgByte, 0, File.ContentLength)
End If
' Insert the picture tag and image into db
Dim conn As String = ConfigurationManager.ConnectionStrings("albumConnString").ConnectionString
connection = New SqlConnection(conn)
connection.Open()
Dim sql As String = "INSERT INTO Album(picture_tag,pic) VALUES(@tag,@pic) SELECT @@IDENTITY"
Dim cmd As SqlCommand = New SqlCommand(sql, connection)
cmd.Parameters.AddWithValue("@tag", txtTags.Text)
cmd.Parameters.AddWithValue("@pic", imgByte)
Dim id As Integer = Convert.ToInt32(cmd.ExecuteScalar())
lblResult.Text = String.Format("Picture ID is {0}", id)
Catch
lblResult.Text = "There was an error"
Finally
connection.Close()
End Try
End Sub
In the code above, we are creating a byte array equal to the length of the file. The byte array will store the image. We then load the image data into the array. The record containing the Picture Tags and Image is then inserted into the database using the ADO.NET code. The ID inserted is returned back using the @@Identity. We will shortly use this ID and pass it as a query string parameter to the ShowImage handler. The image will then be fetched against the Picture ID (pic_id). If you run the application as of now, you should be able to upload the images to the database.
Step 4: In order to display the image on the page, we will create an Http handler. To do so, right click project > Add New Item > Generic Handler > ShowImage.ashx. In the code shown below, we are using the Request.QueryString[“id”] to retrieve the PictureID(pic_id) from the handler url. The ID is then passed to the ‘ShowAlbumImage()’ method where the image is fetched from the database and returned in a MemoryStream object. We then read the stream into a byte array. Using the OutputStream.Write(), we write the sequence of bytes to the current stream and you get to see your image.
C#
<%@ WebHandler Language="C#" Class="ShowImage" %>
using System;
using System.Configuration;
using System.Web;
using System.IO;
using System.Data;
using System.Data.SqlClient;
public class ShowImage : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
Int32 picid;
if (context.Request.QueryString["id"] != null)
picid = Convert.ToInt32(context.Request.QueryString["id"]);
else
throw new ArgumentException("No parameter specified");
context.Response.ContentType = "image/jpeg";
Stream strm = ShowAlbumImage(picid);
byte[] buffer = new byte[4096];
int byteSeq = strm.Read(buffer, 0, 4096);
while (byteSeq > 0)
{
context.Response.OutputStream.Write(buffer, 0, byteSeq);
byteSeq = strm.Read(buffer, 0, 4096);
}
//context.Response.BinaryWrite(buffer);
}
public Stream ShowAlbumImage(int picid)
{
string conn = ConfigurationManager.ConnectionStrings["albumConnString"].ConnectionString;
SqlConnection connection = new SqlConnection(conn);
string sql = "SELECT pic FROM Album WHERE Pic_ID = @ID";
SqlCommand cmd = new SqlCommand(sql, connection);
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("@ID", picid);
connection.Open();
object img = cmd.ExecuteScalar();
try
{
return new MemoryStream((byte[])img);
}
catch
{
return null;
}
finally
{
connection.Close();
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
VB.NET
<%@ WebHandler Language="vb" Class="ShowImage" %>
Imports System
Imports System.Configuration
Imports System.Web
Imports System.IO
Imports System.Data
Imports System.Data.SqlClient
Public Class ShowImage
Implements IHttpHandler
Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
Dim picid As Int32
If Not context.Request.QueryString("id") Is Nothing Then
picid = Convert.ToInt32(context.Request.QueryString("id"))
Else
Throw New ArgumentException("No parameter specified")
End If
context.Response.ContentType = "image/jpeg"
Dim strm As Stream = ShowAlbumImage(picid)
Dim buffer As Byte() = New Byte(4095){}
Dim byteSeq As Integer = strm.Read(buffer, 0, 4096)
Do While byteSeq > 0
context.Response.OutputStream.Write(buffer, 0, byteSeq)
byteSeq = strm.Read(buffer, 0, 4096)
Loop
'context.Response.BinaryWrite(buffer);
End Sub
Public Function ShowAlbumImage(ByVal picid As Integer) As Stream
Dim conn As String = ConfigurationManager.ConnectionStrings("albumConnString").ConnectionString
Dim connection As SqlConnection = New SqlConnection(conn)
Dim sql As String = "SELECT pic FROM Album WHERE Pic_ID = @ID"
Dim cmd As SqlCommand = New SqlCommand(sql, connection)
cmd.CommandType = CommandType.Text
cmd.Parameters.AddWithValue("@ID", picid)
connection.Open()
Dim img As Object = cmd.ExecuteScalar()
Try
Return New MemoryStream(CType(img, Byte()))
Catch
Return Nothing
Finally
connection.Close()
End Try
End Function
Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property
End Class
Step 5: We will now add the ListView to our page. We will see how to use the ‘GroupTemplate’ to display images in multiple columns (in our case 4 images). Add a SQLDataSource control to the page. After configuring it with the database, the code will look similar to the following
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:albumConnString %>"
ProviderName="System.Data.SqlClient"
SelectCommand="SELECT [pic_id],picture_tag, [pic] FROM [Album]"></asp:SqlDataSource>
Now add a ListView Control to the page and set its DataSource property to ‘SqlDataSource1’. After adding the LayoutTemplate, ItemTemplate and GroupTemplate the code will look similar to the following:
<asp:ListView ID="ListView1" GroupItemCount="4" runat="server" DataKeyNames="pic_id"
DataSourceID="SqlDataSource1">
<LayoutTemplate>
<asp:Placeholder
id="groupPlaceholder"
runat="server" />
</LayoutTemplate>
<GroupTemplate>
<div>
<asp:Placeholder
id="itemPlaceholder"
runat="server" />
</div>
</GroupTemplate>
<ItemTemplate>
<asp:Image
id="picAlbum" runat="server" AlternateText='<% #Eval("picture_tag") %>'
ImageUrl='<%# "ShowImage.ashx?id=" + Eval("pic_id") %>' />
</ItemTemplate>
<EmptyItemTemplate>
</EmptyItemTemplate>
</asp:ListView>
If you observe, the <LayoutTemplate> contains a placeholder called ‘groupPlaceholder’. When the page is rendered, the groupPlaceholder is replaced with the contents of GroupTemplate. Similarly, the <GroupTemplate> includes the ‘itemPlaceholder’ placeholder. The itemPlaceholder is replaced with the contents of the ItemTemplate, which is an image. As you know, the <ItemTemplate> renders each time there is an item from the source. The ‘GroupItemCount’ attribute decides the number of items displayed in a <GroupTemplate> before a new row is created. Here we have set the ImageUrl to an expression which makes a call to the handler and displays the images from the database. In the code below, we pass the pic_id as a query string parameter to the Http Handler. Similarly the tags entered by you are shown as alternate text on the images. To see the text, hover your mouse over the image, when the application is run.
Note: One last thing. In order to display images as they are added, just add this line of code (ListView1.DataBind()) in the btnSubmit_Click, just before the try block ends.
...
lblResult.Text = String.Format("Picture ID is {0}", id);
ListView1.DataBind();
We are all set. It’s time to you run the application!! Start uploading images and you will observe that as you upload the images, the gallery gets updated and the image is displayed in an album mode using the ListView control as shown below:
The source code for this article in C# and VB.NET can be downloaded from here. I hope you liked the article and I thank you for viewing it.
This article has been editorially reviewed by Suprotim Agarwal.
C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.
We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).
Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.
Click here to Explore the Table of Contents or Download Sample Chapters!
Was this article worth reading? Share it with fellow developers too. Thanks!
Suprotim Agarwal, MCSD, MCAD, MCDBA, MCSE, is the founder of
DotNetCurry,
DNC Magazine for Developers,
SQLServerCurry and
DevCurry. He has also authored a couple of books
51 Recipes using jQuery with ASP.NET Controls and
The Absolutely Awesome jQuery CookBook.
Suprotim has received the prestigious Microsoft MVP award for Sixteen consecutive years. In a professional capacity, he is the CEO of A2Z Knowledge Visuals Pvt Ltd, a digital group that offers Digital Marketing and Branding services to businesses, both in a start-up and enterprise environment.
Get in touch with him on Twitter @suprotimagarwal or at LinkedIn