web控件开发系列(六) 数据回传

控件在WEB开发时经常要用到,虽然有部分已经存在工具箱里,但有时总需要根据自己的要求,开发一些合适自己的控件。接上一节,已经说过了控件的事件。这节介绍一下数据回发机制,欢迎大家指正。

在ASP.NET技术的服务器编程中,服务器处理完客户端的每个请求就认为任务结束,当客户端再次请求时,服务器会作为新的一次请求处理,即使是相同的客户端也是如此。也就是说服务器不会保存我们两次请求之间的一些前后相接的数据,这就比较麻烦了,比如当我们输入一些信息到一个文本中,然后提交一个按钮,很多时候我们要在按钮提交的服务端事件中处理提交之前的数据和提交按钮时用户输入的最新数据,即想同时得到文本框的旧值和新值,而服务端不会保存前一个请求的任何信息,那怎样才能做到这一点呢?两次页面请求之间的数据关联性问题,ASP.NET是通过视图机制实现的。简单地讲,视图区域信息(ViewState)存储在页面上的一个隐藏字段,里面存储每次需要视图机制保存的一些信息,每次提交时,它都会以“客户端到ó服务端”的形式来回传递一次,当处理完成后,最后会以处理后的新结果作为新的视图信息存储到页面中的隐藏字段,并与页面内容一起返回到客户端。后面会有针对视图状态机制的专门讲解,这里仅了解其功能即可。有了视图机制,在其基础之上的数据回发机制就是完成处理视图信息的功能。具体过程是,服务端控件只要实现IPostBackDataHandler接口,则当客户端提交请求后,就会有机会利用IPostBackDataHandler接口的LoadPostData方法,在该方法内部处理子控件的新旧值逻辑,而视图信息数据这时以一个集合对象形式作为LoadPostData参数,并可以决定是否引发控件值变化后的事件。这就是要引入数据回发机制功能的原因。

IPostBackDataHandler接口定义如下:
Pulbic interface IPostBackDataHandler
{
    bool LoadPostData(string postDataKey, NameValueCollection postCollection);
    void RaisePostDataChangedEvent();
}

LoadPostData()  方法返回一个bool值,表示该控件的值是否发生改变(需要我们去判断),代码如下
public virtual bool LoadPostData(string postDataKey, NameValueCollection postCollection)
{
    return true;
}

参数postDataKey就是回传控件的UniqueID,在客户端表现为name属性。postCollection就是回传的数据值的结合。所以我们可以通过postCollection[postDataKey]来获取本控制回传的值,所以我们就可以来比较原来控件的值跟回传的值,从而来确定LoadPostData方法返回true还是false。
如果LoadPostData方法返回true,.NET框架将自动调用RaisePostDataChangedEvent方法。

RaisPostDataChangeEvent()  此方法是在LoadPostData方法返回true的时候去执行的。
public virtual void RaisePostDataChangedEvent()
{
}

注意下面二点:
第一、必须在控件呈现中将控件的name的属性值设置为UniqueID。这是由于发生回传后,页框架将在发送的内容中搜索与实现IPostBackDataHandler的服务器控件的UniqueID匹配的值,然后才能调用LoadPostData方法。
第二、控件类必须实现IPostBackDataHandler接口,并实现LoadPostData和RaisePostDataChangedEvent方法。LoadPostData方法用来检查提交给服务器的数据。该方法包含两个参数:postDataKey表示用于识别控件内数据的关键值,postData是提交数据的集合,其采用Key/Value结构便于使用索引名称访问。要访问集合中的控件数据,只要采用如下代码即可:"string nData = postData[postDataKey]; "。在LoadPostData方法中,通过新数据(客户端发送的数据值)与旧数据(先前提交给客户端的数据值)进行比较的结果来确定方法返回值。如果新旧数据相同,则说明数据没有被修改,方法返回值为false;如果新旧数据不同,则表明旧数据已经被客户端修改,方法返回值true。

.NET框架处理回传数据的过程:
1、首先在发送的内容中搜索与实现IPostBackDataHandler的服务器控件的UniqueID匹配的值。
2、调用LoadPostData方法,并返回bool值。
3、如果LoadPostData方法返回true,那么调用RaisePostDataChangedEvent方法。
4、执行RaisePostDataChangedEvent方法中定义的OnEvent方法。

下面看一下完整的代码: 

ContractedBlock.gif ExpandedBlockStart.gif Code
using System;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace ServerControl
{
    [ToolboxData(
"<{0}:PostBackData runat=server></{0}:PostBackData>")]    
    
public class PostBackData : WebControl, IPostBackDataHandler
    {
        [PersistenceMode(PersistenceMode.EncodedInnerDefaultProperty), DefaultValue(
""), Category("Behavior"), Description("文本内容")]
        
public string Text
        {
            
get
            {
                
return (this.ViewState["Text"== null ? string.Empty : (String)this.ViewState["Text"]);
            }
            
set
            {
                
this.ViewState["Text"= value;
            }
        }

        
protected override HtmlTextWriterTag TagKey
        {
            
get
            {
                
return HtmlTextWriterTag.Input;
            }
        }

        
protected override void AddAttributesToRender(HtmlTextWriter writer)
        {
            
base.AddAttributesToRender(writer);
            
if (Page != null)
            {
                Page.VerifyRenderingInServerForm(
this);
            }
            writer.AddAttribute(HtmlTextWriterAttribute.Type, 
"text");
            writer.AddAttribute(HtmlTextWriterAttribute.Name, 
this.UniqueID);
            
if (!Enabled)
            {
                writer.AddAttribute(HtmlTextWriterAttribute.Disabled, 
"disabled");
            }
            writer.AddAttribute(HtmlTextWriterAttribute.Value, 
this.Text);
        }

        
protected override void AddParsedSubObject(object obj)
        {
            
if (!(obj is Literal))
            {
                
return;
            }
            
base.AddParsedSubObject(obj);
        }

        
public bool LoadPostData(string postKey, System.Collections.Specialized.NameValueCollection valueCollection)
        {
            
string strPostData = valueCollection[postKey].ToString();
            
string StrText = this.Text;
            
if (StrText.Equals(strPostData, StringComparison.Ordinal))
            {
                
return false;
            }
            
this.Text = strPostData;
            
return true;
        }
        
public void RaisePostDataChangedEvent()
        {
            OnTextChanged(EventArgs.Empty); ;           
        }

        
private static readonly object EventTextChanged = new object();

        
private void OnTextChanged(EventArgs eventArgs)
        {
            EventHandler textChangedHandler 
= (EventHandler)Events[EventTextChanged];
            
if (textChangedHandler != null)
            {
                textChangedHandler(
this, eventArgs);
            }
        }

        
public event EventHandler TextChanged
        {
            add
            {
                Events.AddHandler(EventTextChanged, value);
            }
            remove
            {
                Events.RemoveHandler(EventTextChanged, value);
            }
        }
    }
}

页面前台代码:

ContractedBlock.gif ExpandedBlockStart.gif Code
<%@ Page Language="C#" AutoEventWireup="true" EnableViewState="false" CodeBehind="Default.aspx.cs" Inherits="WebApp._Default" Debug="true" %>

<%@ Register assembly="ServerControl" namespace="ServerControl" tagprefix="cc1" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    
<title></title>
</head>
<body>    
    
<form id="form1" runat="server">
    
<div>
        
<cc1:PostBackData ID="PostBackData1" runat="server" ontextchanged="PostBackData1_TextChanged"></cc1:PostBackData>
        
<asp:Button ID="Button1" runat="server" Text="Button" />
    
</div>
    
</form>
</body>
</html>


页面后台代码:

         protected   void  PostBackData1_TextChanged( object  sender, EventArgs e)
        {
            Response.Write(PostBackData1.Text);
        }

示例图:


这节已经完成.有需要的朋友再深理解与研究吧! 下节继续

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值