Monday, October 20, 2008

Master Detail Data Display using an asp.net GridView and asp.net DetailsView Controls


ObjectDataSource is one of the multifeatured datacontrol in asp.net. In many ways it is similar to the SqlDataSource. For instance both provides data source that is bindable to data displaying controls like Repeater, GridView, FormsView and DetailsView. Similarly, GridView has properties like SelectCommand, InsertCommand, UpdateCommand and DeleteCommand whereas DetailsView provides SelectMethod, InsertMethod, UpdateMethod and DeleteMethod for select, insert, update and delete operations.


Fig: Showing asp.net GridView and DetailsView master detail data display using ObjectDataSource


But here lies some interesting differences. Those command propeties of GridView can be assigned with direct SQL statements. This means we can directly specify select, insert, update and delete commands. In other side, the method properties of ObjectDataSource specify the corresponding methods in the Data Access Layer (DLL) or Business Layer (BLL). All we have to do is specify the class name (along with the namespace, if the class has) in the Type property of the ObjectDataSource. Remember that this class will contain the select, insert, update and delete methods that are directly used by the ObjectDataSource.


By this time you may be thinking about parameters that have to be passed to those methods. Yes, you can specify select, insert, update and delete parameters in the ObjectDataSouce. But all these stuffs are so easy if your are working with GridView, DetailsView, FormsView or Repeater. I have worked in a project using GridView and DetailsView master detail data display using two different ObjectDataSource, one for asp.net GridView and another for asp.net DetailsView.


Since I have well architected three tier architecture in my asp.net web application, I have used the Business Logic Layer (BLL) methods in the ObjectDataSource. I want to share this experiece with you in this article.


To perform the master detail data display in asp.net, we will use GridView as the master data control and DetailsView as the detail data control. First of all lets define a class Category with the public properties Category_ID, Category_Name, Active (if this item is actively displayed in user interfaces). This very class will contain the necessary methods required by the ObjectDataSources.




Category Business Layer and Data Access Layer classes


Category BLL Class


//redefine the public properties and call to classes of DAL


//I have left this part to you to make it short


Category DAL Class


namespace MyTest.DAL {
public class Category
{
public Category() { }

public Category(int id, string categoryName, bool isActive)
{
this.Category_ID = id;

this.Category_Name = categoryName;

this.Active = isActive;


}


private int _category_id = 0;
public int Category_ID
{
get { return _category_id;
}
set { _category_id = value; }
}

private string _category_Name = "";
public string Category_Name { get { return _category_Name; }
set { _category_Name = value; } }

private bool _active;


public bool Active {
get { return _active; }

private set { _active = value; }
}


//methods that work with Category
public abstract List<CategoryDetails> GetCategories(string sortExpression, int pageIndex, int pageSize);
public abstract CategoryDetails GetCategoryByID(int categoryID);
public abstract int GetCategoryCount();
public abstract bool DeleteCategory(int categoryID);
public abstract int InsertCategory(CategoryDetails category);
public abstract bool UpdateCategory(CategoryDetails category);
}
}


GridView, DetailsView and ObjectDataSources in asp.net page (ManageCategory.aspx)


<asp:GridView
ID="gvCategories"
runat="server"
AutoGenerateColumns="False"
DataSourceID="objAllCategories"
Width="80%"
DataKeyNames="Category_ID"
OnRowDeleted="gvCategories_RowDeleted"
OnRowCreated="gvCategories_RowCreated"
OnSelectedIndexChanged="gvCategories_SelectedIndexChanged"
AllowSorting="True"
AllowPaging="True"
PageSize="10">

<Columns>

<asp:BoundField
DataField="Category_Name"
HeaderText="Category"
SortExpression="Category_Name"
/>
<asp:CheckBoxField
DataField="Active"
HeaderText="Is Active"
>
<ControlStyle
Width="5px" />

<ItemStyle
Width="20px"
/>

</asp:CheckBoxField>

<asp:CommandField
ButtonType="Image"
SelectImageUrl="~/Images/Edit.gif"
SelectText="Edit category"
ShowSelectButton="True">
<ItemStyle
HorizontalAlign="Center"
Width="20px"
/>

</asp:CommandField>

<asp:CommandField
ButtonType="Image"
DeleteImageUrl="~/Images/Delete.gif"
DeleteText="Delete category"
ShowDeleteButton="True">
<ItemStyle
HorizontalAlign="Center"
Width="20px"
/>

</asp:CommandField>

</Columns>

<EmptyDataTemplate><b>No categories to show</b></EmptyDataTemplate>
</asp:GridView>
<asp:ObjectDataSource
ID="objAllCategories"
runat="server"
SelectMethod="GetCategories"

TypeName="MyTest.BLL.Category"
DeleteMethod="DeleteCategory"
SortParameterName="sortExpression"
EnablePaging="true"
SelectCountMethod="GetCategoryCount">

</asp:ObjectDataSource>
<p></p>
<asp:DetailsView
Width="80%"
ID="dvwCategory"
runat="server"
AutoGenerateRows="False"
DataSourceID="objCurrCategory"
Height="50px"
AutoGenerateEditButton="True"
AutoGenerateInsertButton="True"
HeaderText="Product Category Details"
OnItemInserted="dvwCategory_ItemInserted"
OnItemUpdated="dvwCategory_ItemUpdated"
OnItemCreated="dvwCategory_ItemCreated"
DefaultMode="Insert"
OnItemCommand="dvwCategory_ItemCommand"
DataKeyNames="Category_ID">
<FieldHeaderStyle
Width="40%"/>
<Fields>
<asp:BoundField
DataField="Category_ID"
HeaderText="ID"
InsertVisible="false"
ReadOnly="true"/>

<asp:TemplateField
HeaderText="Category">

<ItemTemplate>

<asp:Label
ID="lblCategoryName"
runat="server"
Text='<%# Eval("Category_Name") %>'></asp:Label>


</ItemTemplate>
<EditItemTemplate>

<asp:TextBox
ID="txtCategoryName"
runat="server"
Text='<%# Bind("Category_Name") %>'
MaxLength="256"
Width="98%"></asp:TextBox>

<asp:RequiredFieldValidator
ID="valRequireTitle"
runat="server"
ControlToValidate="txtCategoryName"
SetFocusOnError="true"

Text="The Category field is required."
ToolTip="The Category field is required."
Display="Dynamic"></asp:RequiredFieldValidator>


lt;/EditItemTemplate>
</asp:TemplateField>

<asp:CheckBoxField
DataField="Active"
HeaderText="Active"/>

</Fields>

</asp:DetailsView>

<asp:ObjectDataSource
ID="objCurrCategory"
runat="server"
InsertMethod="InsertCategory"
SelectMethod="GetCategoryByID"
UpdateMethod="UpdateCategory"
TypeName="MyTest.BLL.Category">

<SelectParameters>

<asp:ControlParameter
ControlID="gvCategories"
Name="Category_ID"
PropertyName="SelectedValue"

Type="Int32"
/>
</SelectParameters>
</asp:ObjectDataSource>


Presentation Layer Backend (ManageCategory.aspx.cs)


(only required events have been listed)


protected void gvCategories_SelectedIndexChanged(object sender, EventArgs e) { dvwCategory.ChangeMode(DetailsViewMode.Edit); }


protected void gvCategories_RowDeleted(object sender, GridViewDeletedEventArgs e)
{ gvCategories.SelectedIndex = -1; gvCategories.DataBind(); dvwCategory.ChangeMode(DetailsViewMode.Insert);


}


protected void gvCategories_RowCreated(object sender, GridViewRowEventArgs e) {
if (e.Row.RowType == DataControlRowType.DataRow)
{
ImageButton btn = e.Row.Cells[4].Controls[0] as ImageButton;
btn.OnClientClick = "if (confirm('Are you sure you want to delete this category?') == false) return false;";
}
}


protected void dvwCategory_ItemInserted(object sender, DetailsViewInsertedEventArgs e{
gvCategories.SelectedIndex = -1;
gvCategories.DataBind();
}


protected void dvwCategory_ItemUpdated(object sender, DetailsViewUpdatedEventArgs e) {
gvCategories.SelectedIndex = -1;
gvCategories.DataBind();
}


protected void dvwCategory_ItemCreated(object sender, EventArgs e){ //enforce logic to the items created
//before it can be stored to database
//or used anywhere.
}


protected void dvwCategory_ItemCommand(object sender, DetailsViewCommandEventArgs e) {
if (e.CommandName == "Cancel")
{
gvCategories.SelectedIndex = -1;
gvCategories.DataBind();
}
}


By this time, you have displayed the master detail data using asp.net GridView control and asp.net DetailsView control with the use of ObjectDatasource data control. More interestingly, we have also observed architected a three tier asp.net application structure.


Happy programming!

3 comments:

Anonymous said...

why is the "confirm delete"-dialog in the gvCategories_RowCreated section ?

souki said...

Hi,
your Code is very helpful.i m a beginner on ASP.NET.
And i really need it.if you can give me the last part on vb.

Sangam Uprety said...

The confirm delete dialog is put in the row created event of the gridview. At this time, controls are created for the row, and this is thte best place to bind any event to the control. In row data bound event you can manipulated the data in the cells of the row.

Post a Comment

Hope you liked this post. You can leave your message or you can put your valuable suggestions on this post here. Thanks for the sharing and cooperation!

Popular Posts

Recent Articles