FindControl实现原理
public virtual Control FindControl(string id)
{
return this.FindControl(id, 0);
}
protected virtual Control FindControl(string id, int pathOffset)
{
string text;
this.EnsureChildControls();//确定当前控件是否包含子控件,如果不包含,则创建子控件。
if (!this.flags[0x80])//如果当前控件没有实现INamingContainer接口.
{
Control namingContainer = this.NamingContainer;//根据控件树,获取当前控件的父控件
if (namingContainer != null)//有父控件
{
return namingContainer.FindControl(id, pathOffset);//从父控件开始FindControl
}
return null;//没有父控件,返回null
}
if (this.HasControls() && (this._occasionalFields.NamedControls == null))//有子控件
{
this.EnsureNamedControlsTable();//确保所有子控件都被正确加载完成
}
if ((this._occasionalFields == null) || (this._occasionalFields.NamedControls == null))//没有子控件
{
return null;//返回null
}
//开始匹配
char[] anyOf = new char[] { '$', ':' };
int num = id.IndexOfAny(anyOf, pathOffset);
if (num == -1)//未找到
{
text = id.Substring(pathOffset);
return (this._occasionalFields.NamedControls[text] as Control);
}
text = id.Substring(pathOffset, num - pathOffset);
Control control2 = this._occasionalFields.NamedControls[text] as Control;
if (control2 == null)
{
return null;
}
return control2.FindControl(id, num + 1);
}
FindControl只在实现了INamingContainer接口的类中查找控件.
见这个例子("http://www.latter.cn/asp/show/20050422/18/3959375.html")
INamingContainer 接口
任何实现该接口的控件都创建一个新的命名空间,在这个新的命名空间中,所有子控件ID属性在整个应用程序内保证是唯一的.
由该接口提供的标记允许在支持数据绑定的Web服务器控件内唯一命名动态生成的服务器控件实例.
这些控件包括Repeater,DataGrid,DataList,CheckBoxList,ChangePassword,LoginView,Menu,SiteMapNodeItem及RadioButtonList控件.
在开发模板化控件时,应实现该接口以避免同一页上的命名冲突.