65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 jQuery 实现 ASP.NET Web Form 页面修改提示

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.15/5 (8投票s)

2011年1月19日

CPOL

4分钟阅读

viewsIcon

44059

downloadIcon

517

当用户修改了 ASP.NET 网页表单中的字段但未保存就离开时,我们应该通知用户数据已修改。

引言

在 Web 应用的世界里,确保数据的完整性对应用程序来说非常重要。在本文的上下文中,这意味着当用户修改表单数据但未保存就离开时,应用程序会提示用户:“表单已修改,是否要保存?”。这对 Web 开发人员来说是一个非常常见的需求。但是,表单上可能包含不同的控件,为每种类型的控件处理其逻辑将导致代码与应用程序紧密耦合。如果表单明天发生变化,增加一些字段或删除现有字段怎么办?每次都会导致额外的维护工作。

背景

在我们的一项项目中,有人要求我在用户修改 Web 表单但未保存就离开时,创建用户提示,以保存表单数据的完整性。现在的问题是,我们应该在服务器端编写代码还是在客户端编写代码?如果我们写服务器端代码,用户每次离开 Web 表单时,都应该将数据发布到服务器并验证表单数据是否被修改,然后根据验证结果创建用户提示。

这里的想法是,我们首先需要捕获表单加载时的初始值,还需要在用户离开表单之前捕获最终值的快照,然后比较初始值和最终值;如果有任何差异,就提示用户说:“表单已修改,是否要保存?”,否则让用户转到下一页。

如果我们仔细观察 ASP.NET 页面的生命周期,ViewState(视图状态)可以做到这一点。我们可以将回发数据与 ViewState 值进行比较。如果两者之间存在任何差异,我们就可以在客户端提示用户:“表单已修改。是否要保存?”。但这会产生一些副作用。如果 Web 表单包含 AJAX UpdatePanel,它们会为负责的操作进行部分回发。在这种情况下,ViewState 将与首次加载时的 ViewState 不同。ViewState 会随着每次操作而增量更新,我们将无法比较初始值和最终值。因为 ViewState 始终使用表单上的当前值进行更新。

现在,另一个选择是客户端脚本,使用 JavaScript。如果我们为表单上的每个控件编写 JavaScript 代码来比较初始值和最终值,最终将导致代码量过大,这在表单字段是动态的情况下会导致维护上的麻烦。

我们可以始终通过 DOM 遍历浏览每个表单控件,并将它们加载到初始字典和最终字典中,然后比较差异,这始终是一种有效的方法,无论表单是否包含 UpdatePanel 或进行部分回发等。但在这里,我们需要验证每个控件的类型才能获取控件的值。所以一个更好的方法是使用 jQuery。jQuery 选择器擅长根据指定的控件类型选择控件。

Using the Code

此示例使用 Visual Studio 2008 SP1。建议使用相同版本的 Visual Studio;如果您没有相同版本,请下载源代码,使用您拥有的版本创建 Web 应用程序,然后手动将文件添加到项目中。预期的最低版本是 Visual Studio 2005。

为了非常简单地解释,我用了一个简单的员工网站,它包含两个页面:default.aspxRoles.aspx,以及一个包含这两个页面导航的 site1.master 母版页。

下图显示了代码结构

FormCheckModified.JPG

以下是 ItemValueDictionary.js 中的代码

//Load Current values for all
//the text boxes, radio buttons, checkboxes, select buttons,
//adding another text box will be automatically
//picked up by the code as the Jquery selectors are 
//used for each control type. 


function LoadCurrentValues(dictionary) {
    $("input:text").each(function() {
    AddElementToDictionary(dictionary,this.id, this.value);
    });
    //alert(this.value )});
    $("input:radio").each(function() {
    AddElementToDictionary(dictionary,this.id, this.checked);
    });
    $("input:checkbox").each(function() {
    AddElementToDictionary(dictionary,this.id, this.checked);

    });
    $("select").each(function() {
    AddElementToDictionary(dictionary,this.id, $("#" + this.id).val());
    }
    )
}


// to compare the initial form values and current form
//values and returns true if they are same or false if they are different.

function CompareDictionaries(InitialDictionary) {
    CurrentDictionary = new Array();
   
    //At any point while the application is runing
    //it will load the current values, for each control in the form. 
    LoadCurrentValues();
    // Initially check for the number of controls in the
    // Initial Dictionary and in the final dictionary.
    // If the number of controls don't match then
    // form is changed in such a way that some of the controls
    // are hidden or some of the controls loaded as part of the page actions.
    // In these cases, Form save dailogue should trigger
    
    if (InitialDictionary.length != CurrentDictionary.length) {
        return false;
    }
    //number of controls are same, next check if there
    //is any change in the values of each controls
    else {
    
     for(i=0;i<InitialDictionary.length;i++)
     {
       if((InitialDictionary[i].name==CurrentDictionary[i].name) && 
          (InitialDictionary[i].value != CurrentDictionary[i].value))
       {
           return false;
       }
     }
     return true;
    }
}

在上面的代码中,LoadCurrentValues(dictionary) 在调用方法时加载每个控件的快照,然后字典将包含加载的值。页面 DOM 渲染后,将调用 LoadCurrentValues(dictionary) 方法来加载控件的初始值。它将准备一个包含初始值的 ID 和值字典。

同样,LoadCurrentValues(InitialDictionary) 将在用户离开表单页面时加载当前值,并准备一个包含当前值的 ID 和值字典。CompareDictionaries() 方法比较初始字典和当前字典。如果它们不同,它将返回 false,否则返回 true

下面的代码是调用 LoadInitialValues() 方法的地方。这是两个页面的母版页。

$().ready(function() {
           //To capture form initial values
           InitialDictionary = new Array();
            LoadCurrentValues(InitialDictionary);
            $("a[id*=hl]").click(function() {
                if (!CompareDictionaries(InitialDictionary)) {
                     return confirm('Form is modified, Do you want to continue');
                }
            }
        )
     }
)

关注点

使用 jQuery 解决上述问题,就我们编写的代码量而言是很好的。此外,如果我们将来更改表单,例如添加一些文本框或复选框,预置代码应该会自动拾取这些控件,而无需更改代码。

免责声明

本文提供的示例仅用于让读者了解如何解决上述问题。可能需要根据您的需求调整解决方案。此示例不能用于直接生产部署。

© . All rights reserved.