Library tutorials & articles

Creating a Master-detail page

Page 3 of 3
  1. Introduction
  2. Getting Started
  3. The Master Detail Code

The Master Detail Code

Now that we are finished with the front-end of our page let's start on the codebehind(back-end).
The following are things we need to create in the codebehind
  • An event handler for Page_Init event.
  • An event handler for Page_Load event.
  • An event handler for the 'Categories' repeater's ItemDataBound event.

using System;
using System.Data;
using System.Data.SqlClient;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace MasterDetail
{
    /// <summary>
    /// Summary description for MasterDetail.
    /// </summary>
    public class MasterDetail : Page
    {
        public Repeater Categories;
        public Repeater Products;
        private void Page_Init(object sender, EventArgs e)
        {
            Categories.ItemDataBound += new RepeaterItemEventHandler(Categories_OnItemDataBound);
        }

Nothing magic here, just setting up the base and defining the Page_Init event handler. We don't have to subscribe to the ItemDataBound event in the codebehind, we could have done it in the .aspx file by adding the event handler to the 'Categories' repeater's OnItemDataBound property.

The next thing on the agenda now is to add an event handler for Page_Init event. This method will contain the meat of the page, as that is where we fill our dataset, databind our 'Categories' repeater control and add a relationship between our two tables:

private void Page_Load(object sender, EventArgs e)
{
    SqlConnection connection = new SqlConnection("Server=localhost; User Id=sa; Password=; Initial Catalog=Northwind");
    SqlDataAdapter da = new SqlDataAdapter();
    DataSet ds = new DataSet();           
    // Fill dataset
    da.SelectCommand = new SqlCommand("SELECT CategoryID, CategoryName FROM Categories", connection);
    da.Fill(ds, "Categories");
    da.SelectCommand = new SqlCommand("SELECT CategoryID, ProductName, QuantityPerUnit, UnitPrice, UnitsInStock FROM Products", connection);
    da.Fill(ds, "Products");
    // We need to define a relationship between the two tables in the dataset
    DataRelation relation = new DataRelation("categoryId", ds.Tables["Categories"].Columns["CategoryID"], ds.Tables["Products"].Columns["CategoryID"]);
    ds.Relations.Add(relation);
    Categories.DataSource = ds.Tables["Categories"].DefaultView;
    Categories.DataBind();
}

Briefly all we do here is fill up our dataset with the two tables, and add a relationship between the two tables. The way you define a relationship between two tables is by creating an instance of the DataRelation class, and then you add it to the dataset's Relations collection by using the collection's Add method. Instead of doing like I did above you could have done the following instead:

ds.Relations.Add( new DataRelation("categoryId", ds.Tables["Categories"].Columns["CategoryID"], ds.Tables["Products"].Columns["CategoryID"]) );

Although I prefer the first version as it looks nicer ;) All that is left now is to add the event handler for Categories_ItemDataBound event:

        private void Categories_OnItemDataBound(object sender, RepeaterItemEventArgs e)
        {
            if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
            {
                ((Repeater) e.Item.FindControl("Products")).DataSource = ((DataRowView) e.Item.DataItem).CreateChildView("categoryId");
                ((Repeater) e.Item.FindControl("Products")).DataBind();
            }
        }
    }
}

In the method we check to see if the item that is databound is actually either an Item or an AlternatingItem . We have to do this because the objects we want to toy around with are only contained inside the ItemTemplate (in this case we could actually remove the AlternatingItem check, but I added it to make a point). Through the usage of the FindControl method and type casting we can dynamically alter the 'Products' repeater control's datasource for each category iteration.

Well that's it, compile it and have fun!

Comments

  1. 01 Sep 2008 at 08:06
    hi, i am trying to transfer Invoice type,Invoice no and Invoice Date as per given below code But unable to access the value on the second page pls help me how it is possible ' runat="server" > ' runat="server" > ' runat="server" >--%> Example ' runat="server">--%> ">' runat="server">--%> ' runat="server" > ' runat="server" > ' runat="server" > ' runat="server" > ' runat="server" > ' runat="server" > ' runat="server" > ' runat="server" > ' runat="server" >
  2. 22 Apr 2004 at 23:33

    I am trying to test your code, so i found this below error:


    First all:I only put the Code into a web application folder,not user the vs.net to do,but when i try to browse the page,the application error tell me on't load the Masterdetail.masterdeatil,error line's Code is:inherits=Masterdetail.masterdetail.


    Second:I created a solution in vs.net,above the error is losed,but the .aspx page not display the result,why?


    My sql server connection string is right!

  3. 01 Jan 1999 at 00:00

    This thread is for discussions of Creating a Master-detail page.

Leave a comment

Sign in or Join us (it's free).

Thomas Johansen

Related podcasts

Events coming up

  • Mar 15

    DevWeek 2010

    London, United Kingdom

    DevWeek is Europe’s leading independent conference for software developers, database professionals and IT architects, and features expert speakers on a wide range of topics, including .NET 4.0, Silverlight 3, WCF 4, Visual Studio 2010, REST, Windows Workflow 4, Thread Synchronization, ASP.NET 4.0, SQL Server 2008 R2, LINQ, Unit Testing, CLR & C# 4.0, .NET Patterns, WPF 4, F#, Windows Azure, ADO.NET, Entity Framework, Debugging, T-SQL Tips & Tricks, and more.

Want to stay in touch with what's going on? Follow us on twitter!