当呈现ASP.NET控件时,它们的ID有时会发生变化,就像它们位于命名容器中一样。例如,Button1
在呈现时实际上可能具有ctl00_ContentMain_Button1
的ID。
我知道您可以在.cs文件中将JavaScript编写为字符串,获取控件的clientID并使用clientscript将脚本注入到页面中,但是有一种方法可以使用ASP直接从JavaScript引用控件。 NET Ajax?
我发现编写一个函数来递归地解析dom并找到一个控制来保存我想要的id是不可靠的,所以我一直在寻找最佳实践而不是解决方法。
答案 0 :(得分:69)
戴夫沃德的这篇文章可能有你想要的东西:
http://encosia.com/2007/08/08/robust-aspnet-control-referencing-in-javascript/
摘自文章:
确实有。更好的解决方案 是使用内联ASP.NET代码 注入控件的ClientID 属性:$get('<%= TextBox1.ClientID %>')
现在正确的客户端元素ID是 引用,不管是什么 页面结构和嵌套 控制水平。在我看来, 非常轻微的性能成本 这种方法非常值得 您的客户端脚本更具弹性 改变。
Dave的一些示例代码来自该帖子的评论帖:
<script>
alert('TextBox1 has a value of: ' + $get('<%= TextBox1.ClientID %>').value);
</script>
我上面链接的文章的评论主题也有一些很好的讨论。
答案 1 :(得分:16)
您可以将控件的ClienIDMode
属性更改为'Static'
,这将导致您在.NET代码中为控件提供相同的ID。
<asp:TextBox ID="TextBox1" ClientIDMode="Static" runat="server"></asp:TextBox>
将导致:
<input name="ctl00$MainContent$TextBox1" type="text" id="TextBox1">
所以你有相同的身份证。
答案 2 :(得分:12)
对此有几点想法:
1)我有很多运气通过css类而不是id来获取元素,因为asp.net id并不像你所说的那样可靠。我使用这个功能,它的表现相当不错:
function getElementsByClass(searchClass,node,tag) {
var classElements = new Array();
if ( node == null )
{
node = document;
}
if ( tag == null )
{
tag = '*';
}
var els = node.getElementsByTagName(tag);
var elsLen = els.length;
var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
for (i = 0, j = 0; i < elsLen; i++)
{
if ( pattern.test(els[i].className) )
{
classElements[j] = els[i];
j++;
}
}
return classElements;
}
2)jQuery在这里有很多帮助。使用jQuery,您可以可靠地获取id以某个字符串结尾的元素。虽然这不是使用jQuery的“理由”,但它绝对是一个加分。
3)这将在asp.net 4.0中修复,所以挂在那里:-) http://weblogs.asp.net/asptest/archive/2009/01/06/asp-net-4-0-clientid-overview.aspx
答案 3 :(得分:1)
哦,我也找到了这个,以防其他人遇到这个问题。
为asp.net控件使用自定义jQuery选择器: http://john-sheehan.com/blog/custom-jquery-selector-for-aspnet-webforms/
答案 4 :(得分:0)
我不认为这样做有一个“最佳实践”。有很多不同的非常好的做法。这是我们的:
每个具有客户端功能的控件都会在控件的标记正下方呈现内联脚本块:
<span id="something_crazy_long">
control markup
</span>
<script type="text/javascript">new CustomControl('something_crazy_long');</script>
每个控件都附带一个JS:
var CustomControl = function(id) {
this.control = document.getElementByID(id);
this.init();
};
CustomControl.prototype.init = function() {
//do stuff to wire up relevant events
};
在代码隐藏中,我们执行以下操作:
class CustomControl : Control
override void Render(HtmlTextWriter writer)
{
writer.WriteBeginTag("span");
writer.WriteAttribute("id", this.ClientID);
writer.Write(HtmlTextWriter.TagRightChar);
//write control markup
writer.WriteEndTag("span");
writer.WriteBeginTag("script");
writer.WriteAttribute("type", "text/javascript");
writer.Write(HtmlTextWriter.TagRightChar);
writer.Write(
string.Format("new CustomControl('{0}');", this.ClientID)
);
writer.WriteEndTag("script");
}
答案 5 :(得分:0)
我做类似于Rex M的事情,除了避免多个脚本标签我在我的页面基类中使用一个函数来注册我将使用客户端的控件,然后将它们吐出到1个脚本标记内的html。
您甚至可以将控件子类化为自动注册函数,或使用布尔属性来设置是否要在客户端使用它们。
答案 6 :(得分:0)
您也可以使用document.getElementById
方法获取ID。
答案 7 :(得分:0)
对于'ctl00_ContentMain_Button1' - 在asp.net中,当浏览器中的页面呈现时,第一部分保持相同的'ctl00'。第二部分是使用'ContentMain'的ContentPlaceHolder的ID。第三个是控件'Button1'的ID
我喜欢这个http://codedotnets.blogspot.in/2012/01/how-get-id-server-control-javascript.html
答案 8 :(得分:0)
我更喜欢标记document.getElementById('&lt;%#TextBox1.ClientID%&gt;')。value中的数据绑定标记,而不是使用服务器端标记实现&lt;%= TextBox1.ClientID%&gt; 。
服务器端标记禁止您在后面的代码中向dom添加控件。这种需求通常在您构建应用程序时出现,数据绑定方法可以帮助您避免重大改写。
使用服务器端标签时,也称为执行此常用操作的“代码块”
this.Form.Controls.Add(myContorl);
在运行时生成此错误:
由于控件无法修改Controls集合 包含代码块(即&lt;%...%&gt;)。
不幸的是,在您构建完网站后,这通常只会变得非常明显。
实现数据绑定控件'&lt;%#TextBox1.ClientID%&gt;'时解决标记中引用的控件属性的值,在适当的位置,如Page_Load数据绑定结束,如下所示:
的Page.DataBind()
请记住,Page.DataBind()会导致页面上的子控件也为DataBind,如果页面单独处理某些子控件的数据绑定,这可能会产生不必要的副作用。如果是这种情况,可以对单个控件执行数据绑定,如下所示:
TextBox1.DataBind()
应用程序的发展最终导致某种基本站点范围的功能,你可能想要添加基本控件,一旦你用服务器端标签填充你的网站应用程序,用数据库替换它们就会出现问题,特别是当页面被编码时自己处理数据绑定。