创建ASP.NET WEB自定义控件——例程3
下面作者通过实例向大家讲述这种自写控件的编程方法。
(例程使用C#)
本例程实现一个TextBox,该TextBox对于输入的字符串进行检验,将半角单引号替换为全角单引号(半角单引号导致数据库错误)。
控件首先要继承所有控件的基类:System.Web.UI.Control,实现两个接口:IStateManager(实现ViewState),IPostBackDataHandler(处理回发数据),然后可以仿照System.Web.UI.WebControls.TextBox编写一些常用的属性和方法。因篇幅限制,本例只实现Text属性。
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
namespace Demo
{
/// <summary>
/// WebCustomControl1 的摘要说明。
/// </summary>
像前两个例子一样,先处理一下控件设计时属性。
[DefaultProperty("Text"),
ToolboxData("<{0}:DemoTextBox runat=server></{0}:DemoTextBox>")]
public class DemoTextBox : System.Web.UI.Control,IStateManager,IPostBackDataHandler
{
private StateBag _state;
private bool _marked;
下面就是我们要实现的属性:Text
[Bindable(true),
Category("Appearance"),
DefaultValue("")]
public string Text
{
get
{
string _text = (string) ViewState["Text"];
return _text==null?"":_text;
}
set
{
string text = "";
text = value;
text = text.Replace("'","’");
ViewState["Text"] = text;
}
}
为了能实现视图状态就必须实现IStateManager接口
object IStateManager.SaveViewState()
{
object _stateState = null;
if( _state != null )
_stateState = ((IStateManager)_state).SaveViewState();
if ( _stateState == null )
return null;
return _stateState;
}
void IStateManager.TrackViewState()
{
_marked = true;
if( _state != null )
((IStateManager)_state).TrackViewState();
}
void IStateManager.LoadViewState( object state )
{
if( state != null )
{
object _newState = (object)state;
((IStateManager)ViewState).LoadViewState( _newState );
}
}
bool IStateManager.IsTrackingViewState
{
get
{
return _marked;
}
}
internal new StateBag ViewState //注意,这里覆盖基类的ViewState属性
{
get
{
if( _state == null )
{
_state = new StateBag( true );
if( ((IStateManager)this).IsTrackingViewState )
((IStateManager)_state).TrackViewState();
}
return _state;
}
}
下面把控件的表现输出到页面,其实System.Web.UI.WebControls.TextBox也是重新包装了Input而已。
protected override void Render(HtmlTextWriter output)
{
string strOutput = "<Input name=\""+this.ClientID+"\" type=\"text\" value=\""+this.Text+"\">";
output.Write(strOutput);
}
#region IPostBackDataHandler 成员
public void RaisePostDataChangedEvent()
{
// TODO: 添加 DemoTextBox.RaisePostDataChangedEvent 实现
}
下面的方法很重要,把回发的数据保存。
public bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection)
{
// TODO: 添加 DemoTextBox.LoadPostData 实现
string presentValue = this.Text;
string postedValue = postCollection[postDataKey];
if (!presentValue.Equals(postedValue))//如果回发数据不等于原有数据
{
this.Text = postedValue;
return true;
}
return false;
}
#endregion
}
}
好了,一个自己写的TextBox控件完成了,现在把编译好的dll文件找到并添加到工具箱中就可以拖放到页面上了。本例实现的ViewState处理是一个演示,帮助大家了解自己实现ViewState的方法,继承的Control类已经实现了该处理,实际中只需要实现IPostBackDataHandler就可以了,ViewState的问题控件自己就解决了。
控件生成,但是当拖放到页面上的时候它的设计时的显示不太友好,只是一串文字。那么如何像System.Web.UI.WebControls.TextBox那样拖上去后显示为一个输入框呢?
下面我为读者介绍改变显示的方法。
首先在控件项目中添加一个类文件,命名为:Designer.cs。然后修改为如下代码:
using System;
using System.Web.UI.Design;
using System.ComponentModel;
namespace Demo
{
/// <summary>
/// Designer 的摘要说明。
/// </summary>
public class DemoDesigner : ControlDesigner//继承ControlDesigner类
{
private DemoTextBox demoTextBox;//声明一个控件类对象
public override void Initialize(IComponent component)
{
this.demoTextBox = (DemoTextBox)component;
base.Initialize(component);
}
//重载函数GetDesignTimeHtml()
public override string GetDesignTimeHtml()
{
string _html = "";
_html = "<Input type=\"text\" value="+this.demoTextBox.Text+">";
return _html;
}
}
}
设计器完成了,但是还不能使控件拥有设计时显示,还要在控件类的属性代码中添加Designer("Demo.DemoDesigner"),使控件和设计器关联。属性代码如下所示:
[DefaultProperty("Text"),
Designer("Demo.DemoDesigner"),
ToolboxData("<{0}:DemoTextBox runat=server></{0}:DemoTextBox>")]
现在这个控件基本完成了,编译后再拖到页面上你会发现显示的样子与TextBox一样了。
以这个代码为框架,读者可以按自己的需要扩展控件的属性。