asp.net DataGrid Create custom columns

Source: Internet
Author: User
Tags class definition empty integer microsoft sql server tostring visual studio
asp.net|datagrid| Create an Introduction

Have to admit, for Microsoft? asp.net writing the Datagrid code involves a lot of repetitive work. Although I am deeply troubled by the control, I continue to look for shortcuts to simplifying such tasks. No one wants to do repetitive work, right? To get rid of this annoying work, we want to encapsulate repetitive code from multiple projects into a reusable package. This is the problem of object-oriented programming, and using a Datagrid is no exception. For the Datagrid control, to do this, you need to place commonly used code in a built-in column type (which will be used in the first example), and then create a custom column type that you can reuse in multiple Datagrid objects.
This article describes the process of using a standard templatecolumn to use a DropDownList control in a DataGrid column, and then converts that logic to your custom DataGrid column type, which I call DropDownColumn. A number of free Datagrid columns have been created for you, and you can download the required types to metabuilders.com.

Repeated use of the situation

If your team, like many organizations, has divided business logic and/or data access logic into separate components or sets of components, the remaining asp.net files, ASPX, and their code contain only pure representation logic. ("pure" is a relative term.) However, even the logic of the presentation layer can sometimes be reused. So, the next time a user comes to your door and says, "I want my application to look like Susie in the financial aspect," You can reuse the part of the "financial" application to quickly build an application for it. You might also want to package some logic, sell it on the web, or distribute it on your Web site. ASP.net makes this easier than ever because it allows you to create your own server controls, or export column types from existing types, to get the functionality you need.

DropDownList programme

Suppose you are local to Microsoft SQL Server? To edit the Northwind database (or do other work), you want your users (we call Ed, the warehouse keeper) to edit the Orders table. One of the fields contains transport information (ShipVia), and Ed wants to be able to modify the field's information. In display mode, the shipping company should display as plain text. When Ed clicks on the Edit button, you will not only provide him with a TextBox to edit the shipping mode code (1, 2, or 3), but also provide him with a DropDownList that can select a different shipping company. (Because Ed can't remember which shipping company corresponds to which number, so the DropDownList scheme can help him solve the problem.) )



Built-in Datagrid columns

Once you understand the general situation of the problem, let's take a step back and look at the 5 Datagrid column types built in asp.net and their parent type DataGridColumn.

BoundColumn. This is the standard display for text fields. It appears as plain text, but when the Datagrid is in edit mode, it is converted to a TextBox. You can also select formatting options.

HyperLinkColumn. Used to display text data, and also to represent a Web address (URL). URLs can be the same as display text or different, and they can all be set individually. It appears as <a Href= ... > mark.

ButtonColumn. It enables users to interact with the grid in rows. It can be displayed as a hyperlink LinkButton (<a Href= ...). >) or pushbutton (<input type= "button"). Clicking the button triggers the postback and triggers the ItemCommand event on the Datagrid.

EditCommandColumn. It is similar to ButtonColumn, but it automatically creates buttons to edit the Datagrid, Cancel, or commit changes. Triggers the ItemCommand event and a specific event for the clicked button: EditCommand, CancelCommand, or UpdateCommand.

TemplateColumn. Controls that are displayed to users for full control are grouped into templates, such as ItemTemplate and EditItemTemplate. Any asp.net or HTML control or group of controls can be placed in these templates.

Note: Before you use these column types directly, close AutoGenerateColumns (the runtime automatically generates columns). You can then use these column types in the property builder or directly in the HTML code of the ASPX file.



Although these column types are useful, they are just the beginning of the contents of the Datagrid column.

Traditional methods: The DropDownList in TemplateColumn

Before studying how to create a new column type, let's take a look at how to solve the Drop-down list problem by using DropDownList directly within TemplateColumn instead of customizing the column. ItemTemplate will contain only a plain text representation of the current value, while EditItemTemplate contains a <asp:DropDownList> control that needs to be managed at run time.

<asp:datagrid id= "DATAGRID1" runat= "Server" cssclass= "grid" autogeneratecolumns= "False"
<Columns>
<asp:editcommandcolumn edittext= "Edit" canceltext= "Cancel" updatetext= "Update"/>
<asp:boundcolumn datafield= "OrderID" readonly= "True" headertext= "Order ID"/>
<asp:boundcolumn datafield= "ShipName" headertext= "Ship to" readonly= "True"/>
<asp:boundcolumn datafield= "ShipCountry" headertext= "Country" readonly= "True"/>
<asp:templatecolumn headertext= "Ship method" >
<ItemTemplate>
<% #Container. DataItem ("ShipVia")%>
</ItemTemplate>
<EditItemTemplate>
<asp:dropdownlist runat= "Server" id= "Dropdownlist1"/>
</EditItemTemplate>
</asp:TemplateColumn>
</Columns>
</asp:DataGrid>
Code that binds the Datagrid:

Sub Bindgrid ()
Dim SQL as String = "Select OrderID,
ShipName, ShipCountry, ShipVia from Orders "
Dim DA As SqlDataAdapter = New SqlDataAdapter (SQL, ConnStr)
Dim DS as New DataSet
DA. Fill (DS, "Orders")
DataGrid1.DataSource = DS. Tables ("Orders"). DefaultView
Datagrid1.databind ()
End Sub
The currently edited item is bound to DropDownList when the ItemDataBound event of the Datagrid is triggered. When using the ItemDataBound event, check the ListItemType of the current project, or you may find that you are using HeaderItem or other project types that do not apply. Reference the DropDownList control for EditItem. In the following code, I use the cell control set directly to illustrate (in order to be consistent with the following example), but you can use the simple method of assigning an ID directly to the DropDownList control and positioning the control reference using the FindControl method of the Datagrid project. Because the Datagrid is bound to the default view of the DataTable, and the elements of the view belong to the DataRowView type, you can convert the DataItem property of the current project to a DataRowView instance. This allows you to refer directly to fields in DataItem by field names. Use this method to save the current value of "ShipVia" to the record and use it to select the appropriate Drop-down list item.

Private Sub Datagrid1_itemdatabound (ByVal sender as Object, _
ByVal e as System.Web.UI.WebControls.DataGridItemEventArgs) _
Handles Datagrid1.itemdatabound
If E.item.itemtype = ListItemType.EditItem Then
Dim DRV as DataRowView = CType (e.Item.DataItem, DataRowView)
Dim currentship as String = DRV ("ShipVia")
Dim DDL as DropDownList = CType (E.item.cells (4). Controls (1), DropDownList)
Dim SQL as String = "Select ShipperID, CompanyName from Shippers order by ShipperID"
Dim DA As SqlDataAdapter = New SqlDataAdapter (SQL, ConnStr)
Dim DS as New DataSet
Dim Item as ListItem
DA. Fill (DS, "shippers")
Ddl. DataSource = DS. Tables ("Shippers"). DefaultView
Ddl. DataTextField = "CompanyName"
Ddl. DataValueField = "ShipperID"
Ddl. DataBind ()
item = DDL. Items.findbyvalue (currentship)
If not item are nothing Then item. Selected = True
End If
End Sub
Finally, write code to retrieve the currently selected value from DropDownList and perform a database update:

Private Sub Datagrid1_updatecommand (ByVal source as Object, _
ByVal e as System.Web.UI.WebControls.DataGridCommandEventArgs) _
Handles Datagrid1.updatecommand
Dim DDL as DropDownList = CType (E.item.cells (4). Controls (1), DropDownList)
Dim newship as Integer = DDL. SelectedValue
Dim OrderID as Integer = Int32.Parse (E.item.cells (1). Text)
Dim SQL as String = "UPDATE Orders SET shipvia= @Ship WHERE orderid= @ID"
Dim Conn As SqlConnection = New SqlConnection (connstr)
Dim CMD as New SqlCommand (SQL, Conn)
CMD.PARAMETERS.ADD (New SqlParameter ("@Ship", Newship))
CMD.PARAMETERS.ADD (New SqlParameter ("@ID", OrderID))
Conn.Open ()
Cmd.executenonquery ()
Conn.close ()
Datagrid1.edititemindex =-1
Bindgrid ()
End Sub

Base of all columns: DataGridColumn

Let's review the parent type DataGridColumn of all the built-in column types. (see Figure 1.) It contains the properties and methods that are commonly used in all Datagrid columns. A type with an asterisk indicates the type you want to use when you create a custom column type.

DataGridColumn Property
FooterStyle (TableItemStyle)
Footertext (String)
Headerimageurl (String)
HeaderStyle (TableItemStyle)
HeaderText (String)
ItemStyle (TableItemStyle)
SortExpression (String)
Visible (boolean value)
DataGridColumn method
Initialize
InitializeCell
LoadViewState
Oncolumnchanged
SaveViewState
TrackViewState
Reusable methods: Creating DropDownColumn

You first create a new class library in Microsoft Visual Studio. NET and name it mycustomcolumn. Add a new class DropDownColumn and make sure to add namespaces to your class definition so that your initial code should look like this:

Namespace Mycustomcolumn
Public Class DropDownColumn
Inherits DataGridColumn

Public DataSource as ICollection
Public DataField as String
Public DataTextField as String
Public DataValueField as String

End Class
End Namespace
I also declared 4 public properties, as follows:
 
DataSource. It is used to populate the DropDownList dataset. Can be any content that implements the ICollection interface. In the example in this article, I use ArrayList and DataView.

DataField. It is the field in the parent Datagrid data source that corresponds to the data selected from the Drop-down list. For example, if DataSource contains a state set, DataField will resemble "Statecode", or you can use the state to optionally name the field in the table.

DataTextField. This is the text that you want to appear in the Drop-down list, either the following value or not.

DataValueField. This is the value that represents the Special dropdown option. DataValueField is usually an integer value or other code, and DataTextField is a more meaningful text description for the user.

Next, overwrite InitializeCell, which is an intrinsic event in the Datagrid column. All cells in the column will occur InitializeCell, which is very similar to the ItemCreated event when you use the Datagrid directly. You can use it to manage cell content, such as setting HeaderText, and adding DropDownList controls to which you will add data. I've added handlers for the cell's DataBinding event, and I need to take a different approach depending on whether the row is currently being edited. Each System.Web.UI.Control has a DataBinding event, where you can access the underlying data, in this case, the TableCell object in the Datagrid, when the data is bound to the control.

Public Overrides Sub InitializeCell (ByVal cell as TableCell, _
ByVal ColumnIndex as Integer, _
ByVal ItemType as ListItemType)
Mybase.initializecell (cell, columnindex, ItemType)
Select Case ItemType
Case Listitemtype.header
Cell. Text = HeaderText
Case ListItemType.Item, ListItemType.AlternatingItem
AddHandler cell. DataBinding, AddressOf itemdatabinding
Case ListItemType.EditItem
AddHandler cell. DataBinding, AddressOf edititemdatabinding
Dim DDL as New DropDownList
Cell. Controls.Add (DDL)
End Select
End Sub
Next is the itemdatabinding routine, which is triggered when data is made on Item or AlternatingItem in the Datagrid. You need to refer back to the TableCell you are binding, you can directly convert the sender object that is passed to the event, and then use the TableCell NamingContainer property to refer to the current DataGridItem. The DataField content can only be displayed in plain text format, as shown in BoundColumn. Finally, if the user-specified field does not exist, I will display a more user-friendly error message for the user, rather than just displaying general information such as "Index out of range".

Private Sub itemdatabinding (ByVal sender as Object, ByVal e as EventArgs)
Dim cell as TableCell = CType (sender, TableCell)
Dim Dgi as DataGridItem = CType (cell. NamingContainer, DataGridItem)
Try
Cell. Text = Dgi. DataItem (DataField)
Catch Rangeex as IndexOutOfRangeException
Throw New Exception ("Specified DataField is not found.")
Catch Otherex as Exception
Throw New Exception (OtherEx.InnerException.ToString)
End Try
End Sub
Next, write the code for the Edititemdatabinding event, which triggers the event on our custom column cell when a row enters edit mode. References the current cell again and inserts the DropDownList control when the InitializeCell method is invoked. Add an empty item to DropDownList as the first option, select this option if the current data in the column does not match any of the items you selected from the DataSource collection and placed in the list.

Then, you need to determine the type of the incoming collection. In this case, I'll deal with two things: passing a set of strings by ArrayList, or DataView in a datasheet, which is made up of datarowview items. For string data, I will enter a new ListItem and set the value and text of the Drop-down item. Because the two situations are the same, only text is required here. But I will select the item to make a choice based on the value to be consistent with the next example, and the next example will set a separate Value property. For the DataRowView project, as indicated in the previous example, Datarowviewinstance ("FieldName") returns an object that represents the data in that field. You can use the same method to retrieve the values that DataTextField and datavaluefields need.

Finally, throw some exceptions to handle common errors that developers encounter when using columns, such as sending invalid field names to the DataField property, or passing in incompatible DataSource types. I've hard-coded the exception messages that are going to pop up, but I want you to save these messages to a more easily configurable location in your actual application. For example, if you want to use your application globally, you can save it to your Web.config file or resource file. Again, you do not have to throw the "DataField not found" exception again because the exception may have been caught in the Itemdatabinding event before the Datagrid is placed in edit mode.

Private Sub edititemdatabinding (ByVal sender as Object, _
ByVal e as EventArgs)
Dim cell as TableCell = CType (sender, TableCell)
Dim DDL as DropDownList = _
CType (cell. Controls (0), DropDownList)
Dim Datasourceitem as Object
Dim Item as ListItem
Dim Dgi as DataGridItem

' Add an empty option first
Ddl. Items.Add (New ListItem (""))
For each datasourceitem in DataSource
Select Case DataSourceItem.GetType.ToString
Case "System.String" applied to ArrayList sample
item = New ListItem (datasourceitem, Datasourceitem)
Ddl. Items.Add (item)
Case "System.Data.DataRowView"
Dim DRV as DataRowView = _
CType (Datasourceitem, DataRowView)
item = New_
ListItem (DRV (DataTextField), DRV (DataValueField))
Ddl. Items.Add (item)
Case Else
Throw New Exception ("Invalid DataSource type.")
End Select
Next

Try
DGI = CType (cell. NamingContainer, DataGridItem)
item = DDL. Items.findbyvalue (DGI. DataItem (DataField))
Catch Rangeex as IndexOutOfRangeException
Throw New Exception ("Specified DataField is not found.")
Catch Otherex as Exception
Throw New Exception (OtherEx.InnerException.ToString)
End Try

If not item are nothing Then item. Selected = True
End Sub

Using DropDownColumn

That's all the code you need to create the DropDownColumn class, so let's look at how to use the control in your application. If you are learning at home and have not started, compile the namespaces created above into MyCustomColumn.dll and copy them to the/bin folder of the application you want to experiment with. In this case, I create a new Web application Usecustomcolumn and add a reference to the MyCustomColumn.dll in my/bin directory. At the top of the ASPX file, add the @Register directive:

<%@ Register tagprefix= "DGG"
Namespace= "Mycustomcolumn"
Assembly= "Mycustomcolumn"%>
Note that the new DataGrid column type does not appear in the Visual Studio. NET Property Builder for the DataGrid, so you need to go into HTML view and add a column declaration to it. Make sure the Datagrid declaration is in a set of <form runat= "Servers" ... </form> tags, which are used to process postback. The remainder of the ASPX file should look like the following:

<%@ Page language= "VB"
Autoeventwireup= "false"
Codebehind= "WebForm1.aspx.vb"
Inherits= "Usecustomcolumn.webform1"
Trace= "False" debug= "True"%>
! DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 transitional//en"
<HTML>
<HEAD>
<title> WebForm1 </title>
<link rel= "stylesheet" type= "Text/css" href= "Styles.css"
<meta name= "generator" content= "Microsoft Visual Studio.NET 7.0"
<meta name= "Code_language" content= "Visual Basic 7.0"
<meta name= "vs_defaultClientScript" content= "JavaScript"
<meta name= "Vs_targetschema"
Content= "HTTP://SCHEMAS.MICROSOFT.COM/INTELLISENSE/IE5" >
</HEAD>
<body>
<form id= "Form1" method= "POST" runat= "Server"
<asp:datagrid id= "DataGrid1"
runat= "Server" cssclass= "grid"
Autogeneratecolumns= "False" >
<Columns>
<asp:editcommandcolumn
edittext= "Edit" canceltext= "Cancel"
updatetext= "Update"/>
<asp:boundcolumn
Datafield= "OrderID"
Readonly= "True"
headertext= "Order ID"/>
<asp:boundcolumn
Datafield= "ShipName"
Headertext= "Ship To"
readonly= "True"/>
<asp:boundcolumn
Datafield= "ShipCountry"
headertext= "Country"
readonly= "True"/>
<dgg:dropdowncolumn datafield= "ShipVia" headertext= "Ship Method"/>
</Columns>
</asp:DataGrid>
</form>
</body>
</HTML>
The Datagrid is bound to the Orders table of the Northwind sample, and the custom DropDownColumn is bound to the ShipVia column. Now I just set the DataField property because I just bound to a simple ArrayList and don't need the DataTextField and DataValueField properties. The ArrayList option is easiest if you have a predefined list of constants or if you need a quick way to set options. DropDownColumn's DataSource is set in code, first referencing DropDownColumn:

Dim DDC as Mycustomcolumn.dropdowncolumn
DDC = CType (Datagrid1.columns (4), Mycustomcolumn.dropdowncolumn)
Dim AL as New ArrayList
AL. ADD ("Shipping company A")
AL. ADD ("Shipping company B")
AL. ADD ("Shipping company C")
Ddc. DataSource = AL
The following is the result of running this code:



Next, I need to convert the sample to use the active table in the database. ShipVia is a foreign key that finds the table shippers, which I specify as DropDownColumn DataSource in my Code. I also need to change the DropDownColumn declaration to include the DataTextField and DataValueField names that match the corresponding fields in the Shippers table:

<dgg:dropdowncolumn datafield= "ShipVia" datatextfield= "CompanyName"
Datavaluefield= "ShipperID" headertext= "Ship Method"/>
The two Orders table is then bound to the Datagrid, and the Shippers table is bound to a custom column:

Dim SQL as String =
"Select OrderID, ShipName, ShipCountry, ShipVia from Orders"
Dim DA As SqlDataAdapter = New SqlDataAdapter (SQL, ConnStr)
Dim DS as New DataSet
DA. Fill (DS, "Orders")
' Dim Cmd as SqlCommand = New SqlCommand (SQL, Conn)
' Conn.Open ()
' DataGrid1.DataSource = _
Cmd.executereader (commandbehavior.closeconnection)
DataGrid1.DataSource = DS. Tables ("Orders"). DefaultView
SQL = "Select ShipperID, CompanyName" & _
"From Shippers order by ShipperID"
DA.SelectCommand.CommandText = SQL
DA. Fill (DS, "shippers")
Ddc. DataSource = DS. Tables ("Shippers"). DefaultView
Datagrid1.databind ()
DataGridColumn uses the active data to automatically select the correct item based on the values in the Orders table (1, 2, or 3), as follows:




The last step in using DropDownColumn is to retrieve the selected values to pass back to the database update. To do this, simply reference the DropDownList control within the cell and determine its SelectedValue property:

Private Sub Datagrid1_updatecommand (ByVal source as Object, _
ByVal e as System.Web.UI.WebControls.DataGridCommandEventArgs) _
Handles Datagrid1.updatecommand
Dim Customddl as DropDownList = _
CType (E.item.cells (4). Controls (0), DropDownList)
Dim newship as Integer = Customddl.selectedvalue
Dim OrderID as Integer = Int32.Parse (E.item.cells (1). Text)
Dim SQL as String = "UPDATE Orders SET shipvia= @Ship WHERE orderid= @ID"
Dim Conn As SqlConnection = New SqlConnection (connstr)
Dim CMD as New SqlCommand (SQL, Conn)
CMD.PARAMETERS.ADD (New SqlParameter ("@Ship", Newship))
CMD.PARAMETERS.ADD (New SqlParameter ("@ID", OrderID))
Conn.Open ()
Cmd.executenonquery ()
Conn.close ()
Datagrid1.edititemindex =-1
Bindgrid ()
End Sub
Summary

The above outlines how to create a new type for the parent type, how to bind data, and how to apply it to the actual application in DataGridColumn. This is just one example of a reusable DataGrid column, so you need to examine your own application to determine which duplicate functionality can be encapsulated in its own custom DataGrid column. You can develop your own columns to address common problems (for example, displaying DropDownList in columns), or to meet your company's special needs. Nor do you have to stick to the example in this article, which contains only one ASP.net control in a custom column, and you can write more complex structures, such as nesting a series of controls, Third-party content, or the entire Datagrid control into columns to represent multi-tier information. In short, you can give full play to your imagination.

5 built-in column types are useful to meet the needs of most scenarios that are displayed using the Datagrid control. You're not developing your own controls, just putting some meaningful content into TemplateColumn. Creating custom columns allows you to break through these limitations and add rich functionality to your Datagrid application.



Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.