Coping with a New Beta - Data Server Control Templates and Editing

server

The .NET Framework Beta 2 has many changes that will break applications written in Beta 1. Among these changes is the templates used in Data Server Controls, such as the DataGrid and DataList. These are simply syntax changes in how templates are used, not programmatic breaks. In this tutorial you will learn how to use Data Server Control templates. Heck, since its a Friday I'll also show you how to do DataGrid editing at the same time. The downloadable sample code for this article contains files in both Visual Basic.NET and C#.

What Good is a Template?

Templates can be used with the Data Server Controls to provide a custom layout of the data bound to the control. The DataGrid provides a basic grid, with one row for each record, and one table column for each field in the row. Templates can be used with a TemplateColumn to custom format the layout of the column. The DataList provides one row for each record in the data source, and templates are used to format the layout of each row. The Repeater control is entirely custom. Templates are used to provide the layout for the entire Repeater control.

Changing a Name is a Big Deal

In Beta 1 you would use a DataGrid, and set up templates using a TemplateColumn. This is the same in Beta 2, however there are some slight changes to the syntax. In Beta 1 a DataGrid using a TemplateColumn would look like the code in Listing 1.

Listing 1

<asp:DataGrid runat="server" id="myGrid"
  AutoGenerateColumns="False" >
  <property name="columns">
    <asp:TemplateColumn HeaderText="Info">
      <template name="ItemTemplate">
        <b><%# DataBinder.Eval(Container.DataItem,"CompanyName") %></b><br>
        <%# DataBinder.Eval(Container.DataItem, "ContactName")%>
        -
        <%# DataBinder.Eval(Container.DataItem, "ContactTitle")%><br>
        <%# DataBinder.Eval(Container.DataItem, "Address")%><br>
        <%# DataBinder.Eval(Container.DataItem, "City") %>,
        <%# DataBinder.Eval(Container.DataItem, "Region") %>
        <%# DataBinder.Eval(Container.DataItem, "PostalCode") %>
      </template>
    </asp:TemplateColumn>
  </property>
</asp:DataGrid>  

The majority of the syntax in Listing 1 remains the same. The changes are as follows:

The <property> element changes to <Columns>
The <template> element changes to one of the following:
<AlternatingItemTemplate>
<EditItemTemplate>
<FooterTempalte>
<HeaderTemplate>
<ItemTemplate>
<SeparatorTemplate> (Repeater and DataList)
The same DataGrid shown in Listing 1 can be updated to Beta 2 as shown in Listing 2.

Listing 2

Listing 1

<asp:DataGrid runat="server" id="myGrid"
  AutoGenerateColumns="False" >
  <Columns>
    <asp:TemplateColumn HeaderText="Info">
      <ItemTemplate>
        <b><%# DataBinder.Eval(Container.DataItem, "CompanyName") %></b><br>
        <%# DataBinder.Eval(Container.DataItem, "ContactName") %>
        -
        <%# DataBinder.Eval(Container.DataItem, "ContactTitle") %><br>
        <%# DataBinder.Eval(Container.DataItem, "Address") %><br>
        <%# DataBinder.Eval(Container.DataItem, "City") %>,
        <%# DataBinder.Eval(Container.DataItem, "Region") %>
        <%# DataBinder.Eval(Container.DataItem, "PostalCode") %>
      <ItemTemplate>
    </asp:TemplateColumn>
  </Columns>
</asp:DataGrid>  

While Listing 2 shows a DataGrid using templates, the same rules apply to the other Data Server Controls. For example, Listing 3 shows a DataList in Beta 2.

Listing 3

<asp:DataList runat="server" id="myList">
  <ItemTemplate>
    <b><%# DataBinder.Eval(Container.DataItem, "CompanyName") %></b><br>
    <%# DataBinder.Eval(Container.DataItem, "ContactName") %>
    -
    <%# DataBinder.Eval(Container.DataItem, "ContactTitle") %><br>
    <%# DataBinder.Eval(Container.DataItem, "Address") %><br>
    <%# DataBinder.Eval(Container.DataItem, "City") %>,
    <%# DataBinder.Eval(Container.DataItem, "Region") %>
    <%# DataBinder.Eval(Container.DataItem, "PostalCode") %>
  <ItemTemplate>
</asp:DataList>  

I Get the Template Thing, Get to the Good Stuff

The DataGrid and DataList control have built in functionality to enable editing. When the control is put into edit mode, usually by a user clicking an Edit link, the selected record is rendered differently than the others. If the column containing the data is a BoundColumn, then the data is rendered in a TextBox control. Using templates you can control how the record is rendered. The EditItemTemplate is used to specify how a table cell is rendered when the record is being edited.

In Listing 4 is the code for a Web Form containing one DataGrid that has both an <ItemTemplate> and an <EditItemTemplate>. The ItemTemplate is used to control the format of data when it is rendered in its normal state. The EditItemTemplate is used to control the formatting of the data when the record is being edited. In this case, the data is rendered in TextBoxes, although it could be done with DropDownLists, RadioButtons, or any other server control.

Listing 4 - 20010622T0101.aspx

<%@ Page language="C#" SRC="20010622T0101.cs" Inherits="TestApp.C20010622T0101" %>
<html>
<body>
<form method="post" runat="server">
<asp:DataGrid runat="server" id="myGrid"
  AutoGenerateColumns="False"
  BorderColor="Black"
  BorderWidth="1" GridLines="Horizontal"
  HeaderStyle-BackColor="Maroon"
  HeaderStyle-Font-Bold="True"
  HeaderStyle-Font-Name="Verdana"
  HeaderStyle-Font-Size="9pt"
  HeaderStyle-ForeColor="White"
  ItemStyle-Font-Name="Verdana"
  ItemStyle-Font-Size="8pt"
  AlternatingItemStyle-BackColor="Tan" >
  <Columns>
    <asp:EditCommandColumn ButtonType="LinkButton"
      ItemStyle-VerticalAlign="Top"
      EditText="Edit"
      CancelText="Cancel"
      UpdateText="Update" />
    <asp:BoundColumn ReadOnly="True" DataField="CustomerID"
      HeaderText="ID" ItemStyle-VerticalAlign="Top" />
    <asp:TemplateColumn HeaderText="Info">
      <ItemTemplate>
        <b><%# DataBinder.Eval(Container.DataItem, "CompanyName") %></b><br>
        <%# DataBinder.Eval(Container.DataItem, "ContactName") %>
        -
        <%# DataBinder.Eval(Container.DataItem, "ContactTitle") %><br>
        <%# DataBinder.Eval(Container.DataItem, "Address") %><br>
        <%# DataBinder.Eval(Container.DataItem, "City") %>,
        <%# DataBinder.Eval(Container.DataItem, "Region") %>
        <%# DataBinder.Eval(Container.DataItem, "PostalCode") %>
      </ItemTemplate>
      <EditItemTemplate>
        <b><%# DataBinder.Eval(Container.DataItem, "CompanyName") %></b><br>
        <b>Contact Name:</b><br>
        <asp:TextBox Runat="server" id="ContactName"
          Text='<%# DataBinder.Eval(Container.DataItem, "ContactName") %>' /><br>
        <b>Contact Title:</b><br>
        <asp:TextBox Runat="server" ID="ContactTitle"
          Text='<%# DataBinder.Eval(Container.DataItem, "ContactTitle") %>' /><br>
        <asp:TextBox Runat="server" ID="Address"
          Text='<%# DataBinder.Eval(Container.DataItem, "Address") %>' /><br>
        <asp:TextBox Runat="server" ID="City"
          Text='<%# DataBinder.Eval(Container.DataItem, "City") %>' />,
        <asp:TextBox Runat="server" ID="Region"
          Text='<%# DataBinder.Eval(Container.DataItem, "Region") %>' />
        <asp:TextBox Runat="server" ID="PostalCode"
          Text='<%# DataBinder.Eval(Container.DataItem, "PostalCode") %>' />
      </EditItemTemplate>
    </asp:TemplateColumn>
  </Columns>
</asp:DataGrid>
</form>
</body>
</html>

The Web Form shown in Listing 4 uses the code behind class TestApp.C20010622T0101. The beginning of the code for the Web Form is shown in Listing 5. This is only the code to get the data for the first request of the page.

Listing 5 - 20010622T0101.cs

using System;
using System.Data;
using System.Data.SqlClient;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

namespace TestApp
{

  public class C20010622T0101 : System.Web.UI.Page
  {
    protected DataGrid myGrid;

    protected void Page_Load(object sender, System.EventArgs e)
    {
      if(!Page.IsPostBack)
      {
        BindData();
      }
    }

    protected void BindData()
    {
      SqlConnection con = new SqlConnection("server=localhost;database=Northwind;uid=sa;pwd=;");
      SqlCommand cmd = new SqlCommand("SELECT TOP 10 * FROM Customers", con);
      con.Open();
      myGrid.DataSource = cmd.ExecuteReader(CommandBehavior.CloseConnection);
      myGrid.DataBind();
      ((SqlDataReader)myGrid.DataSource).Close();
    }

  }

}

In Listing 5 you use a BindData() method to encapsulate your data access and DataGrid binding. This is important for how the editing will work. You want to be able to call the BindData() method at the right time, rather than relying on the Page_Load() event to handle it for you. In the Page_Load() event handler you make a call to BindData() only when the Web request is not the result of a form post.

You can view the page in the browser now, but the edit functionality will not work. To enable editing there are four steps we have to take:

Write an OnEditCommand() event handler
Write and OnCancelCommand() event handler
Write an OnUpdateCommand() event handler
Add pointers to the event handlers in the DataGrid
Lets start by writing an OnEditCommand() event handler. Listing 6 shows the code you need to add to the code behind class for the event handler.

Listing 6

protected void myGrid_OnEditCommand(object sender, DataGridCommandEventArgs e)
{
  myGrid.EditItemIndex = e.Item.ItemIndex;
  BindData();
}

The OnEditCommand() event handler does two things, it sets the EditItemIndex of the DataGrid to the value passed in the DataGridCommandEventArgs, and calls BindData(). The DataGridCommandEventArgs.Item.ItemIndex is the index of the row where the Edit links was clicked. This tells the .NET Framework that this row should be rendered using the <EditItemTemplate>. With the EditItemIndex set, calling BindData() will rebind the data to the DataGrid.

Before you test this page, add the following line to the <asp:DataGrid> tag:

  OnEditCommand="myGrid_OnEditCommand"  

The OnCancelCommand() event handler works in the same way as the OnEditCommand() event handler. You set the EditItemIndex to -1 (indicating that no rows are being edited), and call BindData(). This is shown in Listing 7.

Listing 7

protected void myGrid_OnCancelCommand(object sender, DataGridCommandEventArgs e)
{
  myGrid.EditItemIndex = -1;
  BindData();
}

To tie the DataGrid to the OnCancelCommand() event handler, add the following code to the <asp:DataGrid> tag:

  OnCancelCommand="myGrid_OnCancelCommand"  

At this point you can view the Web Form in the browser, and test the Edit link and the Cancel link, but the Update link is still not functional.

Make Seven-Up(date) yours!

The OnUpdateCommand() event handler needs to do a few things. It needs to grab the new data from the controls in the <EditItemTemplate>, connect to the database, execute an UPDATE statement, set the EditItemIndex to -1, and call BindData().

To make life easier, I have created a new stored procedure in the Northwind database, for updating Customer information. This is shown in Listing 8.

Listing 8

CREATE PROCEDURE [sp_UpdateCustomer]
@customerID nchar (5),
@contactName nvarchar (30),
@contactTitle nvarchar (30),
@address nvarchar (60),
@city nvarchar (15),
@region nvarchar (15),
@postalCode nvarchar(10)
AS
UPDATE Customers
SET
  ContactName = @contactName,
  ContactTitle = @contactTitle,
  Address = @address,
  City = @city,
  Region = @region,
  PostalCode = @postalCode
WHERE
  CustomerID = @customerID
GO

Once you have created the stored procedure you can use a parameterized SqlCommand to update the customer data. Lets look at the code, then Ill explain how it works. Listing 9 shows the OnUpdateCommand() event handler.

Listing 9

protected void myGrid_OnUpdateCommand(object sender, DataGridCommandEventArgs e)
{
  SqlConnection con = new SqlConnection("server=localhost;database=Northwind;uid=sa;pwd=;");
  SqlCommand cmd = new SqlCommand("sp_UpdateCustomer", con);
  cmd.CommandType = CommandType.StoredProcedure;
  cmd.Parameters.Add(new SqlParameter("@customerID", SqlDbType.NChar, 5));
  cmd.Parameters.Add(new SqlParameter("@contactName", SqlDbType.NVarChar, 30));
  cmd.Parameters.Add(new SqlParameter("@contactTitle", SqlDbType.NVarChar, 30));
  cmd.Parameters.Add(new SqlParameter("@address", SqlDbType.NVarChar, 60));
  cmd.Parameters.Add(new SqlParameter("@city", SqlDbType.NVarChar, 15));
  cmd.Parameters.Add(new SqlParameter("@region", SqlDbType.NVarChar, 15));
  cmd.Parameters.Add(new SqlParameter("@postalCode", SqlDbType.NVarChar, 10));

  cmd.Parameters["@customerID"].Value = e.Item.Cells[1].Text;
  cmd.Parameters["@contactName"].Value = ((TextBox)e.Item.FindControl("ContactName")).Text;
  cmd.Parameters["@contactTitle"].Value = ((TextBox)e.Item.FindControl("ContactTitle")).Text;
  cmd.Parameters["@address"].Value = ((TextBox)e.Item.FindControl("Address")).Text;
  cmd.Parameters["@city"].Value = ((TextBox)e.Item.FindControl("City")).Text;
  cmd.Parameters["@region"].Value = ((TextBox)e.Item.FindControl("Region")).Text;
  cmd.Parameters["@postalCode"].Value = ((TextBox)e.Item.FindControl("PostalCode")).Text;

  con.Open();
  cmd.ExecuteNonQuery();
  con.Close();

  myGrid.EditItemIndex = -1;
  BindData();
}

In Listing 9 you create the OnUpdateCommand() event handler. In the event handler you create a SqlCommand and add six SqlParameters to the ParameterCollection. These parameters are mapped directly to the input parameters expected by the stored procedure in Listing 8.

To set the value of the parameters you use the DataGridEditItemEventArgs.Item.FindControl() method to find the control you want the value for. Since FindControl() returns an instance of the Control class, you have to cast the control as a TextBox before you can retrieve the Text property. Once you have set all the parameters you can open the connection and execute the command. Since the stored procedure does not return anything to you, you can use the ExecuteNonQuery() method. This will execute a command and return the number of rows affected. In this example we are not concerned with that information, so we do not capture it.

After the update is executed, you set the EditItemIndex of the DataGrid to -1, and call BindData().

All you need to do is tie the DataGrid to the OnUpdateCommand() by adding the following code to the <asp:DataGrid> tag:

  OnUpdateCommand="myGrid_OnUpdateCommand"  

Figure 1 shows the page when you click the Edit link on a row.

[ Run Sample ]

Summary

In Beta 2 the templates used in the Data Server Controls have changed a bit. Nothing too drastic, mostly a syntax change. You no longer use the <property> and <template> tags. Instead you use the <Columns> and <ItemTemplate> (or similar template) tags.

时间: 2024-10-29 22:28:51

Coping with a New Beta - Data Server Control Templates and Editing的相关文章

Coping with a New Beta - Data Server Control Templ

The .NET Framework Beta 2 has many changes that will break applications written in Beta 1. Among these changes is the templates used in Data Server Controls, such as the DataGrid and DataList. These are simply syntax changes in how templates are used

ASP.NET Server Control Design Time Support

asp.net|server ASP.NET Server Control Design Time Support 做过自己的 asp.net server control 了吗?有没有象 ASP.NET DataGrid 控件那样:1.从 Toolbox 一拽出来,自动产生一堆代码2.right click 看属性时,有一大堆 custom attribute3.还能进入 template edit 模式把 toolbox 里的 textbox 之类的东东拽到你的控件中4.甚至还能弹出一个自己

在自定义Server Control中捆绑JS文件 Step by Step

js|server 注:本文基于.NET 2.0 和 VS2005 我们在编写 Server Control 的时候难免要用到一些客户端脚本(javascript),如何把脚本和编译好的dll一起发布就成了一个问题.把一段一段的javascript block写在cs文件里是一件很"丑陋"的事情,javascript就应呆在*.js文件里.js文件怎样才能"打包"到dll里呢?查了很多文档,最后实践下来发现有很多细节是需要注意的.整理出来,免得大家走弯路.废话无多,

Media Server Control Panel 0.12发布 Icecast2 管理界面

MSCP(Media Server Control Panel 媒体服务器控制面板)是一款具有广泛功能的Icecast2 管理界面.管理员可以通过它创建用户,编辑访问权限,设置监听器插槽数量,启用或禁用AutoDJ,等等.用户可以通过一个基于Web的界面,进行更改Icecast2服务器的一些参数和AutoDJ.AutoDJ支持音频压缩格式,包括:MP3.Ogg Vorbis 和 FLAC格式.MSCP无需SQL服务器和运行在一个独立的http://www.aliyun.com/zixun/agg

Media Server Control Panel 0.10发布

Media Server Control Panel 0.10该版本增加音频流的转码支持.输入格式可以是MP3,OGG或AAC+.输出格式可以是MP3或OGG(立体声/单声道).立体声工具音频处理器添加到音频流转码器.(这需要SSE2支持).在"管理员"页面有较小的改动. Media Server Control Panel是一个具有综合功能的Icecast2管理接口.管理员可以创建用户,然后编辑访问权限,设置监听器插槽的数量,启用或禁用AutoDJ等,用户可以通过一个基于Web的界面

Media Server Control Panel 0.7发布

Media Server Control Panel是一个具有综合功能的Icecast2管理接口.管理员可以创建用户,然后编辑访问权限,设置监听器插槽的数量,启用或禁用AutoDJ等,用户可以通过一个基于Web的界面更改Icecast2服务器和AutoDJ的几个参数. AutoDJ支持的音频压缩格式包括MP3,Ogg Vorbis和FLAC. MSCP不需要一个独立的http://www.aliyun.com/zixun/aggregation/17117.html">Web服务器和SQL

Server Control Utility (SRVCTL) in clustered Oracle ASM environments

srvctl命令在rac环境中,经常的使用,我们可以用它来完成很多rac管理的任务,下面来看下一般用srvctl在asm实例中能干啥呢? perform the following Oracle ASM administration tasks:■ Add and remove the Oracle ASM CRS resource in Oracle Cluster Registry (OCR)(添加删除crs资源)■ Enable, disable, start, and stop Orac

回答讨饭猫之asp.net优化(一)

asp.net|优化 Performance Tuning Tips Any programming model has its common performance pitfalls, and ASP.NET is no exception. This section describes some of the ways in which you can avoid performance bottlenecks in your code. Disable Session State when

如何在SQL Server中保存和输出图片

server 建表 为了试验这个例子你需要一个含有数据的table(你可以在现在的库中创建它,也可以创建一个新的数据库),下面是它的结构: Column Name Datatype Purpose ID Integer identity column Primary key IMGTITLE Varchar(50) Stores some user friendly title to identity the image IMGTYPE Varchar(50) Stores image cont