最近看到公司某个网站中用到了自定义控件,咋一眼看去,不明白什么玩意,

网上一搜,好像确实不是几句话就能写出强大的自定义控件。好吧,作为一个码农,我决定从基本学起,写一个关于自定义控件学习过程系列。

当然了,我只是学习这个系列,不是作为一个master来出书写教程了。

如果你觉得自己是个master,欢迎指出问题,一针见血的指出问题往往事半功倍。

如果你觉得自己是个大菜鸟,欢迎学习交流。

这个系列主要学习web服务器自定义控件。

而web 服务器控件又分为几种:

HTML服务器控件、<input type=’text’ id=’id1’ runat=’server’>

ASP.NET标准服务器控件  <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>

自定义服务器控件:这就是我想学习,想写的重点了。

我觉得吧,学习任何东西,都应该先从微软官方去学习,大概了解了知识后再去网上看其他的博客文章什么的,因为每个人的理解不一样,或者人家理解了,但是写出来的没有完全表达作者真正想表达的意思,要是被误导了不是表示很亏,所以吧,从微软学习后,再看其他文章,你会了解得更准确更多。

当然先从基础的学上,看看微软官方是怎么说的吧。

http://msdn.microsoft.com/zh-cn/library/yhzc935f(v=vs.100).aspx

看完之后,相信你应该会根据这个步骤创建简单的自定义控件了,至少改变一个Label的输出内容是没有问题了,如果我们想写一个登陆的自定义控件,看完第一篇后,是不是表示无从下手啦?是的,我看完之后,表示很是无奈,没事,一步一步来,后面我们将学到这部分知识。

看完微软官方实例之后啊,我觉得有几个东西非常重要,允许重复啰嗦来强调下:

我们看到代码中有几个特性:

     [
Bindable(true),
Category("Appearance"),
DefaultValue(""),
Description("The text to display when the user is not logged in."),
Localizable(true)
]
public virtual string DefaultUserName
{
get
{
string s = (string)ViewState["DefaultUserName"];
return (s == null) ? String.Empty : s;
}
set
{
ViewState["DefaultUserName"] = value;
}
}

  

BindableAttribute . 此特性指定将属性绑定到数据对可视化设计器是否有意义。 例如,在 Visual Studio 中,如果属性标记为 Bindable(true),则该属性可显示在“数据绑定”对话框中。 如果属性没有使用此特性标记,则属性浏览器会推断其值为 Bindable(false)。

CategoryAttribute . 此特性指定如何在可视化设计器的属性浏览器中对属性进行分类。 例如,当页开发人员使用属性浏览器的分类视图时,Category("Appearance") 将告知属性浏览器在“外观”类别中显示属性。 可以指定一个对应于属性浏览器中的现有类别的字符串参数,也可以创建自己的类别。

DescriptionAttribute . 此特性指定属性的简短描述。 在 Visual Studio 中,属性浏览器将在“属性”窗口底部显示选定的属性的描述。<这个我在控件属性中没有看到,不晓得是什么地方错了>

DefaultValueAttribute . 此特性指定属性的默认值。 此值应与从属性访问器 (getter) 返回的默认值相同。 在 Visual Studio 中,DefaultValueAttribute 特性允许页开发人员通过在“属性”窗口中显示快捷菜单,然后单击“重置”按钮将属性值重置为其默认值。

LocalizableAttribute . 此特性指定本地化属性对可视化设计器是否有意义。 当某属性标记为 Localizable(true) 时,可视化设计器会在将属性序列化为资源时包含该属性值。 对控件轮询可本地化的属性时,设计器会将此属性值保存到非特定于区域性的资源文件或另一个本地化源中。

ViewState:

用于两个属性的 Get 和 Set 方法都利用 ViewState 对象。ViewState 对象是一个内置到 WebControl 类中的帮助器对象。从开发角度讲,ViewState 可被视为一个集合类,用于存储在回发过程中我们想要保留的任意属性。实际上,ViewState 封装了确定如何执行持久性(使用 Cookie、会话等等)所需的所有代码和逻辑。

protected override void RenderContents(HtmlTextWriter writer),

这里就是设计到控件的生命周期了。控件生命周期的Render阶段, 主要将控件标记和字符文本输出到 服务器控件输出流 中. 可以直接写Html标记, 也可以调用每个控件都有的RenderControl方法到输出流. 在WebControl基类中, 以Render开头的呈现方法有如下几个:

RenderControl(HtmlTextWriter writer)

Render(HtmlTextWriter writer)

RenderBeginTag(HtmlTextWriter writer)

RenderContents(HtmlTextWriter output)

RenderEndTag(HtmlTextWriter writer)

  

以上几Render方法中, 并不是毫无联系的, 它们的执行顺序是从上往下, 且有嵌套的调用关系. 其中在RenderControl方法内部会调用Render方法, 在Render方法内部会依次调用RenderBeginTag, RenderContents和RenderEndTag.

其中RenderControl和Render是Control基类中的方法, 因为WebControl本身也是继承Control的. 一般在开发基本控件时, 我们只需求重写RenderContents方法即可, 在此方法中可以把控件Html文本标记和其它内容写到输出流中.

另外, 还有两个可以重载的方法 RenderBeginTag和RenderEndTag, 这两个方法执行时刻点是分别在Render控件内容之前和之后. 可以重写这两个方法自已定义控件的起始和结束标记. 默认情况下控件是以<Span></Span>作为控件起始和结束标记的, 下面是没有重写标记的一个例子的默认显示

这里先看到这个理论知识,后面我们来实践下。

通过这个章节的学习,知道了如何创建与部署到web的整个流程,那么剩下的,就是怎么样做更好更强大的自定义控件了。

我把网页中的Label,通过反射找到源代码,供我们参考了,我们自己编写控件,其实是差不多的

// Generated by .NET Reflector from C:\windows\Microsoft.Net\assembly\GAC_64\System.Web\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Web.dll
namespace System.Web.UI.WebControls
{
using System;
using System.ComponentModel;
using System.Runtime;
using System.Web;
using System.Web.UI;
using System.Web.Util; [Designer("System.Web.UI.Design.WebControls.LabelDesigner, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"), ToolboxData("<{0}:Label runat=\"server\" Text=\"Label\"></{0}:Label>"), DataBindingHandler("System.Web.UI.Design.TextDataBindingHandler, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"), ParseChildren(false), ControlValueProperty("Text"), ControlBuilder(typeof(LabelControlBuilder)), DefaultProperty("Text")]
public class Label : WebControl, ITextControl
{
private bool _textSetByAddParsedSubObject; [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public Label()
{
} [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
internal Label(HtmlTextWriterTag tag) : base(tag)
{
} protected override void AddAttributesToRender(HtmlTextWriter writer)
{
string associatedControlID = this.AssociatedControlID;
if (associatedControlID.Length != 0)
{
if (this.AssociatedControlInControlTree)
{
Control control = this.FindControl(associatedControlID);
if (control == null)
{
if (!base.DesignMode)
{
throw new HttpException(SR.GetString("LabelForNotFound", new object[] { associatedControlID, this.ID }));
}
}
else
{
writer.AddAttribute(HtmlTextWriterAttribute.For, control.ClientID);
}
}
else
{
writer.AddAttribute(HtmlTextWriterAttribute.For, associatedControlID);
}
}
base.AddAttributesToRender(writer);
} protected override void AddParsedSubObject(object obj)
{
if (this.HasControls())
{
base.AddParsedSubObject(obj);
}
else if (obj is LiteralControl)
{
if (this._textSetByAddParsedSubObject)
{
this.Text = this.Text + ((LiteralControl) obj).Text;
}
else
{
this.Text = ((LiteralControl) obj).Text;
}
this._textSetByAddParsedSubObject = true;
}
else
{
string text = this.Text;
if (text.Length != 0)
{
this.Text = string.Empty;
base.AddParsedSubObject(new LiteralControl(text));
}
base.AddParsedSubObject(obj);
}
} protected override void LoadViewState(object savedState)
{
if (savedState != null)
{
base.LoadViewState(savedState);
if ((((string) this.ViewState["Text"]) != null) && this.HasControls())
{
this.Controls.Clear();
}
}
} protected internal override void RenderContents(HtmlTextWriter writer)
{
if (base.HasRenderingData())
{
base.RenderContents(writer);
}
else
{
writer.Write(this.Text);
}
} [Themeable(false), WebSysDescription("Label_AssociatedControlID"), DefaultValue(""), IDReferenceProperty, TypeConverter(typeof(AssociatedControlConverter)), WebCategory("Accessibility")]
public virtual string AssociatedControlID
{
get
{
string str = (string) this.ViewState["AssociatedControlID"];
if (str != null)
{
return str;
}
return string.Empty;
}
set
{
this.ViewState["AssociatedControlID"] = value;
}
} internal bool AssociatedControlInControlTree
{
get
{
object obj2 = this.ViewState["AssociatedControlNotInControlTree"];
if (obj2 != null)
{
return (bool) obj2;
}
return true;
}
set
{
this.ViewState["AssociatedControlNotInControlTree"] = value;
}
} internal override bool RequiresLegacyRendering
{
get
{
return true;
}
} public override bool SupportsDisabledAttribute
{
get
{
return (this.RenderingCompatibility < VersionUtil.Framework40);
}
} protected override HtmlTextWriterTag TagKey
{
get
{
if (this.AssociatedControlID.Length != 0)
{
return HtmlTextWriterTag.Label;
}
return base.TagKey;
}
} [Localizable(true), PersistenceMode(PersistenceMode.InnerDefaultProperty), Bindable(true), WebCategory("Appearance"), DefaultValue(""), WebSysDescription("Label_Text")]
public virtual string Text
{
get
{
object obj2 = this.ViewState["Text"];
if (obj2 != null)
{
return (string) obj2;
}
return string.Empty;
}
set
{
if (this.HasControls())
{
this.Controls.Clear();
}
this.ViewState["Text"] = value;
}
}
}
}

这里有个网页写得不错,看完后,希望你能收获更多.

http://blog.csdn.net/huang7914/article/details/2329261

Asp.net自定义控件系列(一)的更多相关文章

  1. ASP.NET自定义控件组件开发 第五章 模板控件开发

    原文:ASP.NET自定义控件组件开发 第五章 模板控件开发 第五章 模板控件开发 系列文章链接: ASP.NET自定义控件组件开发 第一章 待续 ASP.NET自定义控件组件开发 第一章 第二篇 接 ...

  2. ASP.NET自定义控件组件开发 第四章 组合控件开发CompositeControl

    原文:ASP.NET自定义控件组件开发 第四章 组合控件开发CompositeControl 第四章 组合控件开发CompositeControl 大家好,今天我们来实现一个自定义的控件,之前我们已经 ...

  3. ASP.NET自定义控件组件开发 第四章 组合控件开发CompositeControl 后篇 --事件冒泡

    原文:ASP.NET自定义控件组件开发 第四章 组合控件开发CompositeControl 后篇 --事件冒泡 CompositeControl  后篇 --事件冒泡 系列文章链接: ASP.NET ...

  4. ASP.NET自定义控件组件开发 第三章 为控件添加事件 前篇

    原文:ASP.NET自定义控件组件开发 第三章 为控件添加事件 前篇 第三章 为控件添加事件 好了,我们之前以前开发一个控件.而且也添加了属性,开发也很规范,但是那个控件还差最后一点:添加事件. 系列 ...

  5. ASP.NET自定义控件组件开发 第三章 为控件添加事件 后篇

    原文:ASP.NET自定义控件组件开发 第三章 为控件添加事件 后篇 第三章 为控件添加事件 后篇 前一篇文章只是简单的说了下事件,但是大家应该方法,在ASP.NET自定义控件中只是简单那么定义事件是 ...

  6. ASP.NET自定义控件组件开发 第一章 第三篇

    原文:ASP.NET自定义控件组件开发 第一章 第三篇 第三篇:第一章的完结篇 系列文章链接: ASP.NET自定义控件组件开发 第一章 待续 ASP.NET自定义控件组件开发 第一章 第二篇 接着待 ...

  7. ASP.NET自定义控件组件开发 第二章 继承WebControl的自定义控件

    原文:ASP.NET自定义控件组件开发 第二章 继承WebControl的自定义控件 第二章 继承于WebControl的自定义控件 到现在为止,我已经写了三篇关于自定义控件开发的文章,很感谢大家的支 ...

  8. ASP.NET自定义控件组件开发 第一章 第二篇 接着待续

    原文:ASP.NET自定义控件组件开发 第一章 第二篇 接着待续 ASP.NET自定义控件组件开发 第一章 第二篇 接着待续 很感谢大家给我的第一篇ASP.NET控件开发的支持!在写这些之前,我也看了 ...

  9. ASP.NET自定义控件组件开发 第一章 待续

    原文:ASP.NET自定义控件组件开发 第一章 待续 第一章:从一个简单的控件谈起 系列文章链接: ASP.NET自定义控件组件开发 第一章 待续 ASP.NET自定义控件组件开发 第一章 第二篇 接 ...

随机推荐

  1. 29 Socketserver和 ftp

    一.Socketserver #服务端 import socketserver class KnightServer(socketserver.BaseRequestHandler): def han ...

  2. [HEOI2012]采花

    第一眼以为是树套树qwq 然而n,m<=1e6 记上一个与i颜色相同的位置为nxt[i] 考虑i和nxt[i]会对那些询问产生贡献. 发现当右端点R>=i时, 左端点只要满足nxt[nxt ...

  3. Jenkins install

    Linux CentOS 7.1 x64 Java 1.8 x64 apache-maven-3.3.9 Installation sudo wget -O /etc/yum.repos.d/jenk ...

  4. yarn的淘宝镜像

    现在有很多人使用npm但是很多人也开始使用了更快的更方便额的yarn,可是yarn也有下载速度慢,容易被墙的担忧~又不能像npm那样直接安装淘宝镜像,所以就有了更改yarn的yarn源~ yarn c ...

  5. nyoj 1237 简单dfs

    最大岛屿 时间限制:1000 ms  |  内存限制:65535 KB 难度:2   描述 神秘的海洋,惊险的探险之路,打捞海底宝藏,激烈的海战,海盗劫富等等.加勒比海盗,你知道吧?杰克船长驾驶着自己 ...

  6. POJ-2689 Prime Distance (两重筛素数,区间平移)

    Prime Distance Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 13961   Accepted: 3725 D ...

  7. android升级adt和sdk之后无法识别SDK Location的一个解决方式

    我把android的adt和sdk从4.0升级到4.2,发现eclipse的android设置里面原来列出的各种api level的platform消失了,而且无法新建android工程.而且检查过了 ...

  8. C#窗体控件简介ListBox(需整理)

    ListBox 控件 ListBox 控件又称列表框,它显示一个项目列表供用户选择.在列表框中,用户 一次可以选择一项,也可以选择多项. 1.常用属性: (1) Items属性: 用于存放列表框中的列 ...

  9. IDEA秒退或者一直让填写激活码问题

    IDEA秒退或者一直让填写激活码 1)复制  0.0.0.0 account.jetbrains.com 2)找到你本地的这个路径,我的电脑是windows,所以路径为: 3)点击hosts,添加刚刚 ...

  10. vEthernet(默认交换机) 无法访问网络

    VMware 开启虚拟机 最近公司由无线网转为有线时,我用VMware Workstation Pro装的几个系统,其中一个 ubuntu无法访问网页,在ubuntu运行ifconfig -a ,直接 ...