Using Asp .Net TabContainer To Create Professional Entry Form/View


Asp .Net TabContainer is useful for multi view purpose via clicking its Tab Panels.
The idea is using two TabPanels as containers for Entry form and list view. The first Tab Panel contains Entry Form and second for List View as we can see at above screen shots.

I use simple Northwind Database and Products Table to create Entry and View to this table.

Asp .Net TabContainer Basic

We must add reference to Asp .Net Ajax Control Toolkit since TabContainer Control is inside it.

  • Add ToolkitScriptManager Control inside form tag
  • Add TabContainer Control after ToolkitScriptManager.
     <asp:ToolkitScriptManager ID="ToolkitScriptManager1" runat="server">
    	</asp:ToolkitScriptManager>   
    	<asp:TabContainer ID="TabContainer1" runat="server" >
    		 <asp:TabPanel ID="tabpanel1" runat="server" HeaderText="Entry">
    		 </asp:TabPanel>
    		 <asp:TabPanel ID="tabpanel2" runat="server" HeaderText="View">
    		 </asp:TabPanel>
    	</asp:TabContainer>
    

Basic TabContainer is already created with simple above Asp .Net Script. You can switch between TabPanels but these still contains nothing.

Products Entry Form

After basic TabContainer created then second step is we make the Entry Form. This additional codes has written inside first TabPanel. See below codes

<asp:TabPanel ID="tabpanel1" runat="server" HeaderText="Entry">
	<ContentTemplate>
		<asp:UpdatePanel ID="updpanel1" runat="server">
			<ContentTemplate>
				<asp:HiddenField ID="hidProductID" runat="server" />
				<table>
				<tr><td>Product Name</td><td><asp:TextBox ID="txtPrdName" runat="server"></asp:TextBox></td></tr>
				<tr><td>Supplier</td><td><asp:ComboBox ID="supplier" runat="server" DropDownStyle="DropDown" AutoCompleteMode="Suggest"></asp:ComboBox></td></tr>
				<tr><td>Category</td><td><asp:ComboBox ID="category" runat="server" DropDownStyle="DropDown" AutoCompleteMode="Suggest"></asp:ComboBox></td></tr>
				<tr><td>Qty / Unit</td><td><asp:TextBox ID="txtQtyUnit" runat="server"></asp:TextBox></td></tr>
				<tr><td>Discontinued</td><td>
			   
				<asp:RadioButtonList ID="rdodiscontinued" runat="server">
					<asp:ListItem Text="No" Value="0" Selected="True"></asp:ListItem>
					<asp:ListItem Text="Yes" Value="1"></asp:ListItem>
				</asp:RadioButtonList></td></tr>
				<tr><td colspan="2"><asp:Button ID="btnSave" runat="server" Text="Save" 
						onclick="btnSave_Click" /> &nbsp;<asp:Label ID="lblinfo" runat="server"></asp:Label></td></tr>
				</table>

			</ContentTemplate>
		</asp:UpdatePanel>
	</ContentTemplate>
</asp:TabPanel>

First TabPanel is already has Entry Form. There are two Asp .Net Ajax ComboBoxes which included in AjaxControlToolkit library.

Code to Populate supplier & category comboboxes inside Page_Load procedure.

conn = new SqlConnection(@"Data Source=.\SQLDEV;Initial Catalog=Northwind;Integrated Security=true");
conn.Open();
string sql;
DataTable dt = new DataTable();;
SqlDataAdapter da;
if (supplier.Items.Count == 0)
{
	sql = "select SupplierID, CompanyName from Suppliers order by CompanyName";
	da = new SqlDataAdapter(sql, conn);
	
	da.Fill(dt);
	supplier.Items.Add(new ListItem("", ""));
	foreach (DataRow dr in dt.Rows)
	{
		ListItem li = new ListItem(dr[1].ToString(), dr[0].ToString());
		supplier.Items.Add(li);

	}
	dt.Clear();
	da.Dispose();
}

if (category.Items.Count == 0)
{
	dt = new DataTable();
	sql = "select CategoryID, CategoryName from Categories order by CategoryName";
	da = new SqlDataAdapter(sql, conn);

	da.Fill(dt);
	category.Items.Add(new ListItem("", ""));
	foreach (DataRow dr in dt.Rows)
	{
		ListItem li = new ListItem(dr[1].ToString(), dr[0].ToString());
		category.Items.Add(li);

	}
	dt.Clear();
	da.Dispose();
}
conn.Close();

Saving Record
Code to save in Products Table. This happens if user clicks Save button.
There are two ways for saving which are inserting and/or updating. This depends on ProductID hidden field control.
If productid is empty then it will be add new record. Otherwise it will edit selected record

protected void btnSave_Click(object sender, EventArgs e)
    {
string productid = hidProductID.Value;
string productname = txtPrdName.Text.Trim();
string qtyUnit = txtQtyUnit.Text.Trim();        
string supplr = supplier.SelectedValue;
string categ = category.SelectedValue;
string discontinued = rdodiscontinued.SelectedValue;

if (productname != "" && supplr != "" && categ != "")
{
conn.Open();
string sql;
if (productid == "")
{
	sql = "insert into Products (ProductName, SupplierID, CategoryID, QuantityPerUnit, Discontinued) " +
		"Values ('" + productname + "'," + supplr + "," + categ + ",'" + qtyUnit + "'," + discontinued + ")";
}
else
{
	sql = "update Products set ProductName='" + productname + "', SupplierID=" + supplr + ", CategoryID=" + categ + ", " +
		"QuantityPerUnit='" + qtyUnit + "', Discontinued=" + discontinued + " where ProductID='" + productid + "'";
}

SqlCommand cmd = new SqlCommand(sql, conn);
cmd.ExecuteNonQuery();

cmd.Dispose();
conn.Close();

lblinfo.Text = "Save Success";
lblinfo.BackColor = System.Drawing.Color.YellowGreen;
hidProductID.Value = "";
txtPrdName.Text = "";
txtQtyUnit.Text = "";
supplier.SelectedIndex = 0;
category.SelectedIndex = 0;
}

User already can insert new Product record with above codes.

View Panel With ListView

Second TabPanel contains existing Product records showing inside ListView control. See below codes

<asp:TabPanel ID="tabpanel2" runat="server" HeaderText="View">
	<ContentTemplate>
		<asp:UpdatePanel ID="updpanel2" runat="server">
			<ContentTemplate>
			<asp:Panel ID="panelFind" runat="server" DefaultButton="btnFind">
					<b>Find Products:</b> &nbsp;<asp:TextBox ID="txtFindProducts" runat="server"></asp:TextBox> &nbsp;
					<asp:Button ID="btnFind" runat="server" Text="Find" />
					</asp:Panel>
				<asp:ListView ID="lstview1" runat="server" >
					<LayoutTemplate>					
					 <table border="1">
					<thead>
						<tr>
							<th>&nbsp;</th>
							<th>Product Name</th>
							<th>Supplier</th>
							<th>Category</th>
							<th>Qty / Unit</th>
							<th>Discontinued</th>
							
						</tr>
					</thead>
					 <asp:PlaceHolder ID="itemplaceholder" runat="server"></asp:PlaceHolder>
					 </table>
					</LayoutTemplate>
					<ItemTemplate>
						<tr>
						<td><a href="Default.aspx?opt=edit&id=<%# Eval("ProductID")%>">Edit</a> &nbsp;
						<a href="javascript:deleteID('<%# Eval("ProductID")%>')">Del</a></td>
						<td><%# Eval("ProductName")%></td><td><%# Eval("Supplier")%></td>
						<td><%# Eval("Category")%></td><td><%# Eval("QtyUnit")%></td>
						<td><%# Eval("Discontinued")%></td>
						</tr>
					</ItemTemplate>
				</asp:ListView>
			</ContentTemplate>
		</asp:UpdatePanel>
	</ContentTemplate>
</asp:TabPanel>

There is one Panel with textbox and ‘Find’ button. This to do search for specific records based on entered text in textbox.
Also there are two links to facilitate Edit and Delete record.

To populate the ListView, see below codes

void loadListView()
{
	conn.Open();
	string sql = "select ProductID, ProductName, CompanyName as Supplier, CategoryName as Category, QuantityPerUnit as QtyUnit, Discontinued " +
		"From Products, Suppliers, Categories where Products.SupplierID=Suppliers.SupplierID and Products.CategoryID=Categories.CategoryID ";
	string strFindProducts = txtFindProducts.Text.Trim();
	if (strFindProducts != "")
	{
		sql = sql + "And (ProductName like '%" + strFindProducts + "%' OR CategoryName Like '%" + strFindProducts + "%' OR CompanyName Like '%" + strFindProducts + "%' " +
			"OR CategoryName like '%" + strFindProducts + "%') ";
	}
		
	sql = sql + "Order by ProductName";
	SqlDataAdapter da = new SqlDataAdapter(sql, conn);
	DataTable dt = new DataTable();
	da.Fill(dt);

	lstview1.DataSource = dt;
	lstview1.DataBind();

	da.Dispose();
	conn.Close();
	txtFindProducts.Focus();
}

However if user click second TabPanel it still will not populate the ListView with data. We must add AutoPostBack="true" to TabContainer and also add ActiveTabChanged event.
TabContainer tag will look like below

<asp:TabContainer ID="TabContainer1" runat="server" 
    onactivetabchanged="TabContainer1_ActiveTabChanged" AutoPostBack="true">
	...
	...
</asp:TabContainer>

Event Handler TabContainer1_ActiveTabChanged codes

protected void TabContainer1_ActiveTabChanged(object sender, EventArgs e)
{
	if (TabContainer1.ActiveTabIndex == 1)
	{
		loadListView();
	}
}

Those changes will makes ListView able to automatically populate when user clicks second TabPanel.

Editing Record
ListView has Edit link Edit. Link redirects to Default.aspx with QueryString opt equals to edit and a ProductID.
Form will be filled in with related record value.

Code to handle Edit in Page_load procedure

string opt = Request.QueryString["opt"];
if (!Page.IsPostBack && opt == "edit")
{
	string id = Request.QueryString["id"];            
	showEdit(id);
	
}

showEdit procedure.

TabContainer1.ActiveTab.TabIndex = 0;
conn.Open();
string sql = "select * from Products where ProductID='" + productid + "'";
SqlCommand cmd = new SqlCommand(sql, conn);
SqlDataReader dr = cmd.ExecuteReader();
if (dr.Read())
{
	hidProductID.Value = dr["ProductID"].ToString();
	txtPrdName.Text = dr["ProductName"].ToString();
	txtQtyUnit.Text = dr["QuantityPerUnit"].ToString();
	supplier.SelectedValue = dr["SupplierID"].ToString();
	category.SelectedValue = dr["categoryID"].ToString();
	if (Convert.ToBoolean(dr["Discontinued"]))
	{
		rdodiscontinued.Items[1].Selected = true;
	}
	else
	{
		rdodiscontinued.Items[0].Selected = true;
	}
}
dr.Close();
conn.Close();

Saving is already shown above in btnSave_click.

Delete Record
ListView has Edit link Del.

Delete Javascript:

function deleteID(id) {
	if (confirm("Are you sure to Delete ?")) {
		var request = new Sys.Net.WebRequest();
		request.set_url("deleteID_Handler.ashx");
		request.set_httpVerb("POST");                
		request.set_body("id=" + id);
		request.add_completed(deleteID_completed);
		request.invoke();
	}
}

function deleteID_completed(executor, eventargs) {
	if (executor.get_responseAvailable()) {
		//alert(executor.get_responseData());
		if (executor.get_responseData() == "success") {
			__doPostBack("", "loadListView");
		}
	}
}

deleteID_Handler.ashx is used for delete operation.

using System;
using System.Web;
using System.Data.SqlClient;
using System.Data;

public class deleteID_Handler : IHttpHandler {
    
    public void ProcessRequest (HttpContext context) {
        context.Response.ContentType = "text/html";
        string productid = context.Request.Form["id"];
        delete(productid);
        context.Response.Write("success");
    }
 
    public bool IsReusable {
        get {
            return false;
        }
    }

    void delete(string productid)
    {
        SqlConnection conn = new SqlConnection(@"Data Source=.\SQLDEV;Initial Catalog=Northwind;Integrated Security=true");
        conn.Open();
        string sql = "delete from Products where ProductID='" + productid + "'";
        SqlCommand cmd = new SqlCommand(sql, conn);
        cmd.ExecuteNonQuery();
        cmd.Dispose();

        conn.Close();
    }

}

After deletion operation completed Form do postback to refresh ListView.

Page_Load procedure

 protected void Page_Load(object sender, EventArgs e)
    {
conn = new SqlConnection(@"Data Source=.\SQLDEV;Initial Catalog=Northwind;Integrated Security=true");
conn.Open();
string sql;
DataTable dt = new DataTable();;
SqlDataAdapter da;
if (supplier.Items.Count == 0)
{
	sql = "select SupplierID, CompanyName from Suppliers order by CompanyName";
	da = new SqlDataAdapter(sql, conn);
	
	da.Fill(dt);
	supplier.Items.Add(new ListItem("", ""));
	foreach (DataRow dr in dt.Rows)
	{
		ListItem li = new ListItem(dr[1].ToString(), dr[0].ToString());
		supplier.Items.Add(li);

	}
	dt.Clear();
	da.Dispose();
}

if (category.Items.Count == 0)
{
	dt = new DataTable();
	sql = "select CategoryID, CategoryName from Categories order by CategoryName";
	da = new SqlDataAdapter(sql, conn);

	da.Fill(dt);
	category.Items.Add(new ListItem("", ""));
	foreach (DataRow dr in dt.Rows)
	{
		ListItem li = new ListItem(dr[1].ToString(), dr[0].ToString());
		category.Items.Add(li);

	}
	dt.Clear();
	da.Dispose();
}
conn.Close();
btnFind.Click += new EventHandler(btnFind_Click);
if (!Page.IsPostBack)
{
	lblinfo.Text = "";
	lblinfo.BackColor = System.Drawing.Color.White;
}  
string opt = Request.QueryString["opt"];
if (!Page.IsPostBack && opt == "edit")
{
	string id = Request.QueryString["id"];            
	showEdit(id);
	
}
string eventArg = Request.Form["__EVENTARGUMENT"];
if (eventArg == "loadListView")
{
	loadListView();
}
   }
void btnFind_Click(object sender, EventArgs e)
    {
        loadListView();
    }

Regards,
Agung Gugiaji

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s