ajax模仿Excel,实现双击GridView单元格保存编辑

news/2024/7/21 5:29:41 标签: excel, ajax, server, action, asp, javascript
原贴为英文:http://www.codeproject.com/KB/ajax/Inline_Edit_Controller.aspx
使用了webserivce
  • Download source code - 3.65 KB
  • Download demo - 71.4 KB

Screenshot - grid.gifajax/Inline_Edit_Controller/grid.gif" height="353" width="565" />

  • Light Speed Inline Editing Using ASP.NET AJAX and Web Services (Architecture and Customization) - Part II

Introduction

If you ask people what the most important thing that they want for web based application UIs, most of them will answer "I want to edit data really fast, like in Excel!" That is a tough request. It means that the person wants to click on a row, edit some data, then click on another row, and have all the data saved into a database. We've found a solution for this during TargetProcess v.2.6 development. TargetProcess is a great agile project management software (if you are not aware ;)

Problem

The ASP.NET framework provides inline editing functionality in GridView. But sometimes, you get into situations when you cannot use this functionality:

  • You cannot use it with a disabled View State.
  • Performance is really bad. When you click a button to switch the row into edit state, a post back to the server will be initiated. The post back will happen when you save or cancel the edit mode as well. Even if you put your grid into an UpdatePanel, AJAX.NET still will update the whole grid instead of just one row, and the size of the date in the post back remains almost the same (and large).

With bad performance, it will not be like Excel, right? So, we have to look for a solution that:

  • Will not initiate post back to the server
  • Will work with a disabled view state
  • Will be as fast as Excel (at least, less than a second to do an action)

Solution

The Inline Edit Controller (IEC) is JavaScript solution that resolves all our problems (you will see it really soon). It has the following advantages:

  • It's a cross-platform solution, you can use it in any environment: ASP, ASP.NET, PHP, JSP etc.
  • It's a cross-browser solution.
  • It's a very extensible solution; it's pretty simple to extend the basic behavior by adding your custom handlers.
  • It can be easily integrated into existing applications without almost any rework. You can define custom saving methods to put edited values into a database.

Basic principles

IEC is a plain JavaScript solution that allows editing rows in a grid. In order to have an editable row, you should mark the row in some specific manner. Let's call this stuff "Inline Edit Panel". It contains a button that enables inline editing as well as buttons that save changes and cancels editing. In fact, the better way to go is to enable editing on double click, and cancel it on Escape key. That will be shown in more advanced examples. So far, we have simple buttons:

aspnet"><asp:GridView CellPadding="0" CellSpacing="0" Width="1px" 
GridLines="none" runat="server" AllowSorting="false"
AutoGenerateColumns="false" ID="uxOrders">
<asp:TemplateField>
<ItemTemplate>
<span runat="server" style="white-space: nowrap"
class="inlineEditIcon" inlineeditattribute="true"
rowid='<%# Eval("OrderID")%>'>
<img runat="server" action="edit"
title="Inline Edit" src="~/img/edit.gif" />
<img runat="server" style="display: none"
action="save" title="Save" src="~/img/save.gif" />
<img runat="server" style="display: none"
action="cancel" title="Cancel" src="~/img/cancel.gif" />
</span>

</ItemTemplate>
</asp:TemplateField>
...

Cells that are going to be editable must be located in a specific place holder as well. Let's call this stuff "Edit Area".

<asp:TemplateField HeaderText="Freight">
<ItemTemplate>
<span id="FreightIdPrefix<%# Eval("OrderID")%>">
<asp:Label ID="Label1" runat="server"
Text='<%#Eval("Freight")%>'></asp:Label>
</span>
</ItemTemplate>
</asp:TemplateField>

As you can see, the "Inline Edit Panel" has three buttons, with an extra "action" attribute. Each action attribute fires the corresponding event. The IEC handles all these events and makes the corresponding changes in the DOM. Let's review the editing process now.

1. User clicks the Edit button

  • At this stage, the row switches to an editable state, and input and select boxes are appended to "Edit Areas".
  • The usual text labels become invisible. It means that the Freight label in the code above becomes invisible, and the input text field is added to the span with id="FreightIdPrefix777".

2. User changes some values and clicks the Save button

  • At this stage, IEC extracts all the values from editable fields (input, select, other if any).
  • Replace the label texts with new values from the editable fields.
  • Create a JavaScript object that holds the edited (new) values.
  • It's time to save changes into the database. IEC has no idea how to save new data, so it just passes the JavaScript object that holds the new values into the saving method.

3. User pushes the Cancel button

  • At this stage, IEC removes editable fields ("input", "select").
  • Labels become visible again.

Usage example

The idea looks really simple. But maybe, the solution is hard to use, who knows… Only a real example can help us judge the solution.

Let's take an ASP.NET example with:

  • A GridView control to present the data.
  • A Web Service to retrieve the data and save the modified data.
  • AJAX.NET to generate web methods that can be used from JavaScript.
  1. For example, we have a pretty simple Order class. We want to show all the orders in a grid.

    Screenshot - orderCRC.jpgajax/Inline_Edit_Controller/orderCRC.jpg" height="228" width="155" />

  2. The GridView initialization is a no-brainer as well. OrderService is a class that can retrieve orders from the database (we don't care how; maybe the GetAllOrders method uses NHibernate, or maybe plain old SQL).
    protected override void OnLoad(EventArgs e)
    {
    if (!IsPostBack)
    {
    OrderService orderService = new OrderService();
    Order[] orders = orderService.GetAllOrders();
    uxOrders.DataSource = orders;
    uxOrders.DataBind();
    ...
  3. IEC mapping. As mentioned above, we should add columns with inline editing controls (Inline Edit Panel).
    aspnet"><asp:TemplateField>
    <ItemTemplate>
    <span id="Span1" runat="server" style="white-space:
    nowrap"
    class="inlineEditIcon" inlineeditattribute="true"
    rowid='<%# Eval("OrderID")%>'>
    <img id="Img1" runat="server" action="edit"
    title="Inline Edit" src="~/img/edit.gif" />
    <img id="Img2" runat="server" style="display: none"
    action="save" title="Save" src="~/img/save.gif" />
    <img id="Img3" runat="server" style="display: none"
    action="cancel" title="Cancel"
    src="~/img/cancel.gif" />
    </span>
    </ItemTemplate>
    </asp:TemplateField>

    And insert all the required "Edit Areas".

    Collapse
    <asp:GridView CellPadding="0" CellSpacing="0" Width="1px" 
    GridLines="none" runat="server" AllowSorting="false"
    AutoGenerateColumns="false" ID="uxOrders">
    <Columns>
    <asp:TemplateField>
    <ItemTemplate>
    <span priorityname='<%#Eval("Priority")%>'
    id="PriorityIdPrefix<%# Eval("OrderID")%>">

    <span>
    <%#GetPriorityHTML(Container.DataItem)%>
    </span
    </span>
    </ItemTemplate>
    </asp:TemplateField>
    <asp:TemplateField HeaderText="Freight">
    <ItemTemplate>
    <span id="FreightIdPrefix<%# Eval("OrderID")%>">
    <asp:Label ID="Label1" runat="server"
    Text='<%#Eval("Freight")%>'></asp:Label>
    </span>
    </ItemTemplate>
    </asp:TemplateField>
    <asp:TemplateField HeaderText="Ship Name">
    <ItemTemplate>
    <span id="ShipNameIdPrefix<%# Eval("OrderID")%>">
    <asp:Label ID="Label1" runat="server"
    Text='<%#Eval("ShipName")%>'></asp:Label>
    </span>
    </ItemTemplate>
    </asp:TemplateField>
    ...

    As you can see, the "Edit Areas" have a composite ID that consists of two parts: "Edit Area prefix + itemID". Such an ID is required to make each row unique.

  4. Now, we should create an IEC instance, and the EditAreaSettings instances (see below) for each "Edit Area".
    var editAreasSettings = new Array();
    //ShipName is a property of Order class
    //ShipNameIdPrefix is an id of span element
    //(EditArea of ShipName property)
    var shipNameEditAreaSettings = new EditAreaSettings("ShipName",
    "ShipNameIdPrefix",null, true);
    editAreasSettings.push(shipNameEditAreaSettings);

    var freightSettings = new EditAreaSettings("Freight","FreightIdPrefix");
    freightSettings.onSelectValue = onSelectFreightValueHandler;
    editAreasSettings.push(freightSettings);

    var prioritySettings = new EditAreaSettings("Priority",
    "PriorityIdPrefix","uxPriorities");
    prioritySettings.onRenderEditedValue = onRenderPriorityValue;
    prioritySettings.onSelectValue = onSelectPriorityValue;
    editAreasSettings.push(prioritySettings);

    var inlineEditController = new InlineEditController('<%=uxOrders.ClientID%>',
    editAreasSettings, onSaveEventHandler, true);

    EditAreaSettings( areaName, areaPrefix , dataSourceControlID, isFocused)

    Arguments:

    • areaName – used by IEC to map the edited values to the retObj that is passed into onSaveEventHandler.
    • areaPrefix – used by IEC to find the edit area.
    • dataSourceControlID – data source control ID that has a collection of predefined values.
    • isFocused - boolean value that specifies whether the edit area will have a focus.

    onRenderPriorityValue and onSelectPriorityValue are custom handlers that are implemented outside of IEC. It is impossible to implement all the cases of editing, and for specific situations, you have to create custom handlers. For example, the Priority column is an image. When the row is in the usual state, it shows the priority icon, but when the row is in an editable state, it should show the select box.

    Screenshot - priority.jpgajax/Inline_Edit_Controller/priority.jpg" height="160" width="428" />

    The code of onRenderPriorityValue and onSelectPriorityValue are out of the scope for this article; it will be described in Part II (architecture, extensibility, and stuff like that).

  5. We are getting closer to the final. Let's add the saving handler. IEC is quite agnostic to data saving, and does not care how you will implement that. All it needs is a method call that does all the job.
    function onSaveEventHandler(retOb)
    {
    retObj.OrderID = retObj.itemID;
    TargetProcess.DaoTraining.BusinessLogicLayer.OrderService.UpdateOrder(retObj,
    onRequestComplete,
    onErrorRequest);

    }

    The UpdateOrder method will be fired on the save event. It has only one input parameter, retObj, which holds all the edited values. IEC maps the edited values into retObj using the keys from EditAreaSettings (for example, shipName, Freight). Fortunately, I mapped the "Edit Areas" for IEC to be consistent with the Order class, except retObj.itemID that is created by IEC. As a result, retObj can be casted to the Order class. I had to do one extra assignment to make retObj completely consistent with Order.

    retObj.OrderID = retObj.ItemID

    The onSaveEventHandler handler is completely consistent with the web method.

    [ScriptService]
    public class OrderService : WebService
    {

    [WebMethod]
    public string UpdateOrder(Order order)
    {
    OrderDao OrderDao = DaoFactory.GetDaoFactory().GetOrderDao();
    bool isUpdated = OrderDao.UpdateOrder(order);
    if (isUpdated)
    return "The order '" + order.OrderID + "' is successfully updated.";
    else
    return "Unable to find order '" + order.OrderID + "'.";
    }

I'm using the web service to save the order, but it's not necessary. It's a pretty flexible approach that allows other mechanisms to save the data.



http://www.niftyadmin.cn/n/1412679.html

相关文章

lesson006 汇编 可执行代码

汇编汇编 约等于 机器码源代码 进化 到 机器码 引申出编译器什么是编译器&#xff1f;编译器也是一个软件&#xff0c;以后就不强调汇编和机器码的区别的&#xff0c;以后统一用汇编代替机器码编译器具有翻译的功能举例 printf(); 它要与显卡交互上节课我们有讲&#xff0c;操作…

暗物质 和 暗能量 是什么?

暗物质 和 暗能量 是什么&#xff1f; 这是一个 不容回避 的 问题 。 也许 我们 永远 不能和 暗物质 发生 引力 外的 关系&#xff0c; 但 需要 正视 暗物质 和 暗能量 。 转载于:https://www.cnblogs.com/KSongKing/p/11157735.html

Atitit.提升 升级类库框架后的api代码兼容性设计指南

Atitit.提升 升级类库框架后的api代码兼容性设计指南 1. 增加api直接增加&#xff0c;版本号在注释上面增加1 2. 废弃api&#xff0c;使用主见dep1 3. 修改api&#xff0c;1 4. 修改依赖import&#xff0c;雅瑶增加文件模式。保持兼容性。。1 5. 优先选择同一个文件内的修改&am…

DataList编辑、更新、取消、删除、分页

DataList编辑、更新、取消、删除、分页&#xff0c;分页用的是 AspNetPager.dll4.3控件&#xff0c;功能挺强大的&#xff0c;自己可以到网上下个1.aspx程序代码<% Page Language"C#" AutoEventWireup"true" CodeFile"DataList_DeleteUpdate1.aspx…

day55 IO模型(多路复用IO)

目录 IO模型网络IO经历的步骤和过程阻塞IO模型非阻塞IO模型报错的类型多路复用IO模型&#xff08;重要&#xff09;多路复用对比非阻塞异步IO模型信号驱动IO模型IO模型 I/O&#xff08;input/output&#xff09;&#xff1a;输入输出 IO所存在的问题&#xff1a;当我们要输入数…

OC NSURL本地存储和读取plist文件

为什么80%的码农都做不了架构师&#xff1f;>>> 首先我们来介绍一下&#xff0c;读取本地文件的步骤。 那么如何获取到本地文件路径地址呢&#xff1f;首先打开终端。将你要读取的文件拖到终端上。 注意&#xff1a;①复制地址时要将Users前面的 / 加上&#xff01…

Asp.net中防止用户多次登录的方法

在web开发时&#xff0c;有的系统要求同一个用户在同一时间只能登录一次&#xff0c;也就是如果一个用户已经登录了&#xff0c;在退出之前如果再次登录的话需要报错。常见的处理方法是&#xff0c;在用户登录时&#xff0c;判断此用户是否已经在Application中存在&#xff0c;…

C#可用的日出日落时间类

一个现成代码的公共类库&#xff0c;复制下来作为一个类文件就可以调用了。一般不需要了解实现过程&#xff0c;各种数学公式太麻烦。 调用方法&#xff1a; SunTimeResult result SunTimes.GetSunTime(DateTime.Now, double.Parse(Longitude), double.Parse(Latitude)); Mess…