控件开发笔记,鄙视写 LinkButton 那个傻蛋.
1. GridView 的 LinkButton 是如何生成 形如:href="javascript:__doPostBack('ctl00$Content$gridCorner','Upload$2')" 的??
E:\myapp\MS_Symbols\src\source\FXUpdate3074\1.1\DEVDIV\depot\DevDiv\releases\whidbey\QFE\ndp\fx\src\xsp\System\Web\UI\WebControls\GridView.cs\7\GridView.cs
if (buttonControl == null) {
throw new ArgumentNullException("buttonControl");
}
if (buttonControl.CausesValidation) {
throw new InvalidOperationException(SR.GetString(SR.CannotUseParentPostBackWhenValidating, this.GetType().Name, ID));
}
PostBackOptions options = new PostBackOptions(this, buttonControl.CommandName + "$" + buttonControl.CommandArgument);
options.RequiresJavaScriptProtocol = true;
return options;
}
它是从 E:\myapp\MS_Symbols\src\source\FXUpdate3074\1.1\DEVDIV\depot\DevDiv\releases\whidbey\QFE\ndp\fx\src\xsp\System\Web\UI\WebControls\DataControlLinkButton.cs\2\DataControlLinkButton.cs 而来。 注意这里是 DataControlLinkButton ,而不是 LinkButton,它继承了 LinkButton,所以在GridView上,可看作是 LinkButton。
if (_container != null) {
return _container.GetPostBackOptions(this);
}
return base.GetPostBackOptions();
}
继续倒推,它是从 E:\myapp\MS_Symbols\src\source\FXUpdate3074\1.1\DEVDIV\depot\DevDiv\releases\whidbey\QFE\ndp\fx\src\xsp\System\Web\UI\WebControls\LinkButton.cs\4\LinkButton.cs 发出的。
// Make sure we are in a form tag with runat=server.
if (Page != null) {
Page.VerifyRenderingInServerForm(this);
}
// Need to merge the onclick attribute with the OnClientClick
string onClick = Util.EnsureEndWithSemiColon(OnClientClick);
if (HasAttributes) {
string userOnClick = Attributes["onclick"];
if (userOnClick != null) {
// We don't use Util.MergeScript because OnClientClick or
// onclick attribute are set by page developer directly. We
// should preserve the value without adding javascript prefix.
onClick += Util.EnsureEndWithSemiColon(userOnClick);
Attributes.Remove("onclick");
}
}
if (onClick.Length > 0) {
writer.AddAttribute(HtmlTextWriterAttribute.Onclick, onClick);
}
bool effectiveEnabled = IsEnabled;
if (Enabled && !effectiveEnabled) {
// We need to do the cascade effect on the server, because the browser
// only renders as disabled, but doesn't disable the functionality.
writer.AddAttribute(HtmlTextWriterAttribute.Disabled, "disabled");
}
base.AddAttributesToRender(writer);
if (effectiveEnabled && Page != null) {
//
PostBackOptions options = GetPostBackOptions();
string postBackEventReference = null;
if (options != null) {
postBackEventReference = Page.ClientScript.GetPostBackEventReference(options, true);
}
// If the postBackEventReference is empty, use a javascript no-op instead, since
// <a href="" /> is a link to the root of the current directory.
if (String.IsNullOrEmpty(postBackEventReference)) {
postBackEventReference = "javascript:void(0)";
}
writer.AddAttribute(HtmlTextWriterAttribute.Href, postBackEventReference);
}
}
它是从 E:\myapp\MS_Symbols\src\source\FXUpdate3074\1.1\DEVDIV\depot\DevDiv\releases\whidbey\QFE\ndp\fx\src\xsp\System\Web\UI\WebControls\WebControl.cs\4\WebControl.cs
AddAttributesToRender(writer);
HtmlTextWriterTag tagKey = TagKey;
if (tagKey != HtmlTextWriterTag.Unknown) {
writer.RenderBeginTag(tagKey);
}
else {
writer.RenderBeginTag(this.TagName);
}
}
。。
如果想给GridView 中的 LinkButton 的 Hreft 添加 Javascript 代码.代码是不能包含 空格的, 否则,它会被解析成 %20, 很讨厌, 而且它会先执行 Href 再执行 onclick . 如果在不用 Href 属性,即不执行
javascript:__doPostBack('ctl00$Content$gvCon','YourCommand$0');
在 RowDataBound 里先设置 Href 属性: LinkButton.Attribute["href"]="" .再添加 onclick 属性.
如果是在命令按钮之前添加完自定义脚本,那么,就非常不好玩了.暂无好法.
1.LinkButton文字替换成 A 标签. 给 A标签添加 自定义脚本.
2.不用LinkButton.ImageButton就没有问题嘛.
3.重写LinkButton.阻止 Href 被Url编码.
为什么 Href 不能直接设置呢. 贴一下代码.就说明 写 LinkButton 的为什么是傻蛋了.
{
if (Page != null)
{
Page.VerifyRenderingInServerForm(this);
}
string str0 = Util.EnsureEndWithSemiColon(OnClientClick);
if (base.HasAttributes)
{
string value = base.Attributes["onclick"];
if (value != null)
{
str0 = str0 + Util.EnsureEndWithSemiColon(value);
base.Attributes.Remove("onclick");
}
}
if (str0.Length > 0)
{
writer.AddAttribute(HtmlTextWriterAttribute.Onclick, str0);
}
bool flag1 = base.IsEnabled;
if (Enabled && !flag1)
{
writer.AddAttribute(HtmlTextWriterAttribute.Disabled, "disabled");
}
base.AddAttributesToRender(writer);
if (flag1 && (Page != null))
{
PostBackOptions options = GetPostBackOptions();
string text3 = null;
if (options != null)
{
text3 = Page.ClientScript.GetPostBackEventReference(options, true);
}
if (string.IsNullOrEmpty(text3))
{
text3 = "javascript:void(0)";
}
writer.AddAttribute(HtmlTextWriterAttribute.Href, text3);
}
}
如果你提前给 LinkButton 设置了 Href 属性. 它会先在 base.AddAttributesToRender(writer) 里生成所有的属性.贴WebControl.AddAttributesToRender 的主要代码.
{
AttributeCollection collection1 = Attributes;
IEnumerator enumerator1 = collection1.Keys.GetEnumerator();
while (enumerator1.MoveNext())
{
string name = (string) enumerator1.Current;
writer.AddAttribute(name, collection1[name]);
}
}
LinkButton 的 AddAttributesToRender 会二次生成 Href , 所以,直接给 LinkButton 赋 Href 会生成两个 Href 标签 . 狂晕啊.我顶他个肺!
我在重写 LinkButton 时只能调用父类的 AddAttributesToRender ,但是,还需要爷类的 AddAttributesToRender , 如何在孙类调用爷类的 AddAttributesToRender 呢,我想了半天也想不出来. 谁能告诉我! 在孙类写 (this as WebControl).AddAttributesToRender(writer); 会出现死循环.因为它会一直往下调用,在孙类调用爷类的方法,在爷类执行的时候又去查找被Override 的子类的方法.导致死循环.
...故事似乎还没完...
作者:NewSea 出处:http://newsea.cnblogs.com/
QQ,MSN:iamnewsea@hotmail.com 如无特别标记说明,均为NewSea原创,版权私有,翻载必纠。欢迎交流,转载,但要在页面明显位置给出原文连接。谢谢。 |