无法在嵌套网格中找到 'ControlToValidate' 引用的控件 ID <ControlID>
Unable to find control id <ControlID> referenced by 'ControlToValidate' in Nested Grid
我有一个嵌套网格,可以在 FooterControl 中添加一行。我希望能够在用户单击“添加”按钮时验证数据。
我在后面的代码中的 RowDataBound 方法中添加了 RequiredFieldValidation。
如果此验证不在此方法中,则一切正常。但是添加验证会产生错误 - 它无法找到 ControlToValidate 引用的 ControlId。
如果有人可以看一下我哪里出错了,我将不胜感激...
这是嵌套的网格标记:
<div id="div<%# Eval("GroupID") %>" style="display:none">
<asp:GridView ID="GroupMemberGridView" runat="server" AutoGenerateColumns="false" OnRowDeleting="GroupMemberGridView_RowDeleting"
OnRowCommand="GroupMemberGridView_RowCommand" CssClass="grid" ShowFooter="true">
<Columns>
<asp:TemplateField HeaderText="MemberID">
<ItemTemplate>
<asp:Label ID="mggvLblMemberID" runat="server" Text='<%# Bind("MemberID") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Member Name" ItemStyle-Wrap="false">
<ItemTemplate>
<asp:Label ID="mggvLblMemberName" runat="server" Text='<%# Bind("MemberName") %>'></asp:Label>
</ItemTemplate>
<FooterTemplate>
<asp:DropDownList ID="mggvDDLMemberName" runat="server"
class="chosen-single" data-placeholder="Choose member…">
</asp:DropDownList>
</FooterTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Active Device(s)">
<ItemTemplate>
<asp:Label ID="mggvLblActiveDevice" runat="server" Text='<%# (Boolean.Parse(Eval("ActiveDevice").ToString())) ? "Yes" : "No" %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Action" ItemStyle-Wrap="false" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:Button ID="mggvDeleteButton" runat="server" CausesValidation="False" CommandName="Delete"
Text="Delete" CssClass="gridActionbutton" OnClientClick="return confirm('Are you sure you want to delete this Group Member?')" >
</asp:Button>
</ItemTemplate>
<FooterTemplate>
<asp:Button ID="mggvAddButton" runat="server" CommandName="Add" Text="Add Member" Width="90%" ClientIDMode="Static"
CssClass="gridActionbutton" CausesValidation="true" OnClientClick="return Validate(this);" >
</asp:Button>
</FooterTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
这是创建验证的 RowDataBound 事件
if (e.Row.RowType == DataControlRowType.DataRow)
{
int tiGroupID = Convert.ToInt32(UserGroupGridView.DataKeys[e.Row.RowIndex].Value.ToString());
GridView tgvGroupMember = (GridView)e.Row.FindControl("GroupMemberGridView");
populateGroupMemberGrid(tgvGroupMember, tiGroupID);
//Get the Footer controls that have the new entry data
Control tFooterControls = CommonMethods.getFooterControls(tgvGroupMember);
DropDownList tddlRecipientNames = tFooterControls.FindControl("mggvDDLMemberName") as DropDownList;
m_strXmlTableData = m_pagingClient.GetAllPossibleGroupMembers(m_strUserID, tiGroupID);
DataTable tdtAllGroupMembers = CommonMethods.ParseXML(m_strXmlTableData);
tddlRecipientNames.DataSource = tdtAllGroupMembers;
tddlRecipientNames.DataTextField = tdtAllGroupMembers.Columns["MemberName"].ToString();
tddlRecipientNames.DataValueField = tdtAllGroupMembers.Columns["MemberID"].ToString();
tddlRecipientNames.DataBind();
tddlRecipientNames.Items.Insert(0, new ListItem("", "0"));
RequiredFieldValidator validator = new RequiredFieldValidator();
validator.ID = "ReqValueDDLMember_" + tiGroupID.ToString();
string id = ((DropDownList)tFooterControls.FindControl("mggvDDLMemberName")).UniqueID;
validator.ControlToValidate = ((DropDownList) tFooterControls.FindControl("mggvDDLMemberName")).UniqueID;
validator.EnableClientScript = true;
validator.ErrorMessage = "Selection required.";
validator.CssClass = "message-error-dropdown";
validator.ValidationGroup = "DDLVal_" + tiGroupID.ToString();
tgvGroupMember.Controls.Add(validator);
Button tbtnAdd = tFooterControls.FindControl("mggvAddButton") as Button;
tbtnAdd.ValidationGroup = "DDLVal_" + tiGroupID.ToString();
}
谢谢。
更新
这是一个使用 Master.Pages 的 ASP.NET 网络应用程序。最初,我使用 .ID 并得到了同样的错误。我认为这是因为 ID 不是唯一的,因为有几个嵌套的网格。但是,使用 UniqueId 标识父网格中的特定嵌套网格。但是我得到了同样的错误。
如果我在标记中创建验证器,则验证仅适用于第一个嵌套网格。
为什么找不到该死的控件?
似乎我已经尝试了所有方法来将 ControlToValidate 设置为特定于 DropDown 控件的唯一 ID。
我认为我的问题是控件 ID 必须是唯一的。这是一个带有 Master.Pages 的嵌套网格 在标记中,将 ID 分配给嵌套网格中的 FooterControl,如 'mggvDDLMember' 会生成 'ct100$MainContent$UserGroupGridView$GroupMemberGridView$.....$mggvDDLMemberName'.
的 ID
像这样在后面的代码中设置 ID:
ControlToValidate = 'mggvDDLMemberName'
抛出找不到控件的错误。
使用控件的 uniqueID,mggvDDLMemberName 是 'ct100$MainContent$UserGroupGridView$GroupMemberGridView$..$mggvDDLMemberName 这会产生 ControlToValidate 在表单标签之外的错误,因为 MainContent 是 PlaceContentHolder:
ControlToValidate = ((DropDownList)tFooterControls.FindControl("mggvDDLMemberName")).UniqueID;
试图消除 'ct100' 以便控件位于占位符内。我试试这个:
ControlToValidate = ((Dropdown) this.Form.FindControl("MainContent").FindControl("UserGroupGridView").FindControl("ct102").FindControl("GroupMemberGridView").FindControl("ctl13").FindControl("mggvDDLMemberName")).ID;
它抛出找不到控件的错误。
我真的不知道如何做到这一点,或者是否可以做到......:(
我尝试了客户端解决方案无济于事。我可能需要再调查一下。
更新
我回到了验证器的原始设计,而不是动态添加它们。这是带有验证器的 FooterTemplate 标记:
<FooterTemplate>
<asp:DropDownList ID="mggvDDLMemberName" runat="server" class="chosen-single" data-placeholder="Choose member…">
</asp:DropDownList>
<asp:RequiredFieldValidator ID="ReqValueDDLMemberInsert" runat="server" InitialValue="0" ControlToValidate="mggvDDLMemberName" ValidationGroup="InsertGroupMemberValidation" ErrorMessage="Selection required." CssClass="message-error-dropdown">
</asp:RequiredFieldValidator>
</FooterTemplate>
这是开始验证的添加按钮:
<FooterTemplate>
<asp:Button ID="mggvAddButton" runat="server" CommandName="Add" Text="Add Member" Width="90%" CssClass="gridActionbutton" CausesValidation="true" ValidationGroup="InsertGroupMemberValidation" >
</asp:Button>
</FooterTemplate>
我自己也在处理这样的事情。据我了解(例如http://forums.asp.net/t/952691.aspx?Problem+in+Custom+Control+Unable+to+find+Control+To+Validate+Property+),验证器的 ControlToValidate
必须 或者 设置为控件的 ID
provided和控件放在同一个NamingContaineror可以设置为控件的UniqueID
提供验证器放在实际的页面.
[编辑:这一段和链接的解释是inadequate/incomplete;请参阅下面我的新单独 post 以获得正确的讨论和解决方案。]
我认为 grids/repeaters 中的每一行都是它自己的 NamingContainer。无论如何,如果您尝试(坚持 UniqueID
)将验证器添加到 Page 级别(注意 validator.ID
本身必须是唯一的,或者不设置它?),这现在使您的情况可行吗?我很想知道....
P.S。
或者,要将控件的 ID
用于 ControlToValidate
,您必须在控件旁边添加验证器,即将其添加到 DropDownList 的 Parent 的控件集合中,而不是你要把它放在哪里?
我正在添加一个新答案,以一劳永逸地阐明在 所有 情况下 BaseValidator.ControlToValidate
需要设置的内容,包括 descendent/nested 控件,因为有很多关于这个的问题。我希望这可能对其他人以及当前的提问者将来有用。
我在上面找到的参考资料是 incorrect/insufficient,其他地方的帖子也说明它应该设置为 Control.ID
或 Control.UniqueID
。在 all 情况下有效的代码使用了 .NET 4 中添加的方法:Control.GetUniqueIDRelativeTo(Control control)
。我在网络上的任何地方都找不到使用示例(包括 Whosebug 中的此处)。给定一个 BaseValidator validator
和一个 Control control
,一旦它们都被添加到页面的控件层次结构中,需要以下内容:
validator.ControlToValidate = control.GetUniqueIDRelativeTo(validator);
GetUniqueIDRelativeTo
的文档是 incorrect/misleading。它表示 returns "The prefixed portion of the UniqueID property of the specified control";事实上它 returns "suffixed" 部分,即前缀 右边 的部分,这就是方法名称所暗示的。实际上,returns control.UniqueID
的右侧部分在从左侧移除 validator.NamingContainer.UniqueID
后仍然存在。这会正确处理 descendent/nested 控件。
将BaseValidator.ControlToValidate
设置为Control.ID
或Control.UniqueID
只是上述的退化情况,在特殊情况下有效(和GetUniqueIDRelativeTo()
returns相同无论如何结果)。如果(且仅当)验证器和控件在 same NamingContainer 中,那么 Control.ID
有效;如果(且仅当)验证器的 NamingContainer 是 Page,则 Control.UniqueID
有效。在其他 nested/descendent 情况下均无效。
重要的是,如果控件的 NamingContainer 不 与验证器的 NamingContainer[=59 相同或不是其后代=] 然后 control.GetUniqueIDRelativeTo(validator)
变为 throw new InvalidOperationException("This control is not a descendent of the NamingContainer of '<validator>'")
。当 ASP.NET 生成有关无法定位要验证的控件的错误时,这就是导致错误的原因。在这种情况下,您需要在页面正常工作之前将其解决,方法是将验证器移动到控件所在的位置或移动到首页级别。
对于最初的提问者:ID
和 UniqueID
对于她的原始代码都不正确,如上所述。我认为她最后通过将验证器从单独的 location/NamingContainer 移动到与 DropDownList 控件相同的 location/NamingContainer 中解决了这个问题,因此现在能够摆脱 ID
退化情况.
这对我有用...
需要唯一的不是 ID,而是 ValidationGroup 名称。
因此,我在 FooterTemplate 的标记中创建了所有控件。但是我没有命名 ValidationGroup 属性。我在代码隐藏中这样做了。
这是下拉菜单、验证器和按钮的标记:
<FooterTemplate>
<asp:DropDownList runat="server"
ID="mggvDDLMemberName"
class="chosen-single"
data-placeholder="Choose member…">
</asp:DropDownList>
<asp:RequiredFieldValidator runat="server"
ID="ReqValueDDLMemberInsert"
InitialValue="0"
ControlToValidate="mggvDDLMemberName"
ErrorMessage="Selection required."
CssClass="message-error-dropdown">
</asp:RequiredFieldValidator>
</FooterTemplate>
<FooterTemplate>
<asp:Button runat="server"
ID="mggvAddButton"
CommandName="Add"
Text="Add Member"
Width="90%"
CssClass="gridActionbutton"/>
</FooterTemplate>
在 RowDataBound 事件中,当我将数据绑定到下拉列表时,我为每个控件命名了 ValidationGroup。
protected void UserGroupGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
try
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
int tiGroupID = Convert.ToInt32(UserGroupGridView.DataKeys[e.Row.RowIndex].Value.ToString());
GridView tgvGroupMember = (GridView)e.Row.FindControl("GroupMemberGridView");
populateGroupMemberGrid(tgvGroupMember, tiGroupID);
//Get the Footer controls
Control tFooterControls = CommonMethods.getFooterControls(tgvGroupMember);
DropDownList tddlRecipientNames = tFooterControls.FindControl("mggvDDLMemberName") as DropDownList;
m_strXmlTableData = m_pagingClient.GetAllPossibleGroupMembers(m_strUserID, tiGroupID);
DataTable tdtAllGroupMembers = CommonMethods.ParseXML(m_strXmlTableData);
tddlRecipientNames.DataSource = tdtAllGroupMembers;
tddlRecipientNames.DataTextField = tdtAllGroupMembers.Columns["MemberName"].ToString();
tddlRecipientNames.DataValueField = tdtAllGroupMembers.Columns["MemberID"].ToString();
tddlRecipientNames.ValidationGroup = "InsertMember" + tiGroupID.ToString();
tddlRecipientNames.DataBind();
tddlRecipientNames.Items.Insert(0, new ListItem("", "0"));//This is needed for the jquery-chosen dropdown to add data-holder text
RequiredFieldValidator validator = (RequiredFieldValidator)tFooterControls.FindControl("ReqValueDDLMemberInsert");
validator.ControlToValidate = ((DropDownList)tFooterControls.FindControl("mggvDDLMemberName")).GetUniqueIDRelativeTo(validator);
validator.ErrorMessage = "Selection required.";
validator.CssClass = "message-error-dropdown";
validator.ValidationGroup = "InsertMember" + tiGroupID.ToString();
Button tbtnAdd = tFooterControls.FindControl("mggvAddButton") as Button;
tbtnAdd.ValidationGroup = "InsertMember" + tiGroupID.ToString();
tbtnAdd.CausesValidation = true;
}
}
catch (Exception ex)
{
logger.ErrorException(ex.Message, ex);
Response.Redirect("~/Error.aspx?use=" + m_strUserType);
}
}
我希望这对其他人有所帮助并为他们节省一点时间。
我有一个嵌套网格,可以在 FooterControl 中添加一行。我希望能够在用户单击“添加”按钮时验证数据。 我在后面的代码中的 RowDataBound 方法中添加了 RequiredFieldValidation。 如果此验证不在此方法中,则一切正常。但是添加验证会产生错误 - 它无法找到 ControlToValidate 引用的 ControlId。
如果有人可以看一下我哪里出错了,我将不胜感激... 这是嵌套的网格标记:
<div id="div<%# Eval("GroupID") %>" style="display:none">
<asp:GridView ID="GroupMemberGridView" runat="server" AutoGenerateColumns="false" OnRowDeleting="GroupMemberGridView_RowDeleting"
OnRowCommand="GroupMemberGridView_RowCommand" CssClass="grid" ShowFooter="true">
<Columns>
<asp:TemplateField HeaderText="MemberID">
<ItemTemplate>
<asp:Label ID="mggvLblMemberID" runat="server" Text='<%# Bind("MemberID") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Member Name" ItemStyle-Wrap="false">
<ItemTemplate>
<asp:Label ID="mggvLblMemberName" runat="server" Text='<%# Bind("MemberName") %>'></asp:Label>
</ItemTemplate>
<FooterTemplate>
<asp:DropDownList ID="mggvDDLMemberName" runat="server"
class="chosen-single" data-placeholder="Choose member…">
</asp:DropDownList>
</FooterTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Active Device(s)">
<ItemTemplate>
<asp:Label ID="mggvLblActiveDevice" runat="server" Text='<%# (Boolean.Parse(Eval("ActiveDevice").ToString())) ? "Yes" : "No" %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Action" ItemStyle-Wrap="false" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:Button ID="mggvDeleteButton" runat="server" CausesValidation="False" CommandName="Delete"
Text="Delete" CssClass="gridActionbutton" OnClientClick="return confirm('Are you sure you want to delete this Group Member?')" >
</asp:Button>
</ItemTemplate>
<FooterTemplate>
<asp:Button ID="mggvAddButton" runat="server" CommandName="Add" Text="Add Member" Width="90%" ClientIDMode="Static"
CssClass="gridActionbutton" CausesValidation="true" OnClientClick="return Validate(this);" >
</asp:Button>
</FooterTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
这是创建验证的 RowDataBound 事件
if (e.Row.RowType == DataControlRowType.DataRow)
{
int tiGroupID = Convert.ToInt32(UserGroupGridView.DataKeys[e.Row.RowIndex].Value.ToString());
GridView tgvGroupMember = (GridView)e.Row.FindControl("GroupMemberGridView");
populateGroupMemberGrid(tgvGroupMember, tiGroupID);
//Get the Footer controls that have the new entry data
Control tFooterControls = CommonMethods.getFooterControls(tgvGroupMember);
DropDownList tddlRecipientNames = tFooterControls.FindControl("mggvDDLMemberName") as DropDownList;
m_strXmlTableData = m_pagingClient.GetAllPossibleGroupMembers(m_strUserID, tiGroupID);
DataTable tdtAllGroupMembers = CommonMethods.ParseXML(m_strXmlTableData);
tddlRecipientNames.DataSource = tdtAllGroupMembers;
tddlRecipientNames.DataTextField = tdtAllGroupMembers.Columns["MemberName"].ToString();
tddlRecipientNames.DataValueField = tdtAllGroupMembers.Columns["MemberID"].ToString();
tddlRecipientNames.DataBind();
tddlRecipientNames.Items.Insert(0, new ListItem("", "0"));
RequiredFieldValidator validator = new RequiredFieldValidator();
validator.ID = "ReqValueDDLMember_" + tiGroupID.ToString();
string id = ((DropDownList)tFooterControls.FindControl("mggvDDLMemberName")).UniqueID;
validator.ControlToValidate = ((DropDownList) tFooterControls.FindControl("mggvDDLMemberName")).UniqueID;
validator.EnableClientScript = true;
validator.ErrorMessage = "Selection required.";
validator.CssClass = "message-error-dropdown";
validator.ValidationGroup = "DDLVal_" + tiGroupID.ToString();
tgvGroupMember.Controls.Add(validator);
Button tbtnAdd = tFooterControls.FindControl("mggvAddButton") as Button;
tbtnAdd.ValidationGroup = "DDLVal_" + tiGroupID.ToString();
}
谢谢。
更新 这是一个使用 Master.Pages 的 ASP.NET 网络应用程序。最初,我使用 .ID 并得到了同样的错误。我认为这是因为 ID 不是唯一的,因为有几个嵌套的网格。但是,使用 UniqueId 标识父网格中的特定嵌套网格。但是我得到了同样的错误。
如果我在标记中创建验证器,则验证仅适用于第一个嵌套网格。
为什么找不到该死的控件?
似乎我已经尝试了所有方法来将 ControlToValidate 设置为特定于 DropDown 控件的唯一 ID。
我认为我的问题是控件 ID 必须是唯一的。这是一个带有 Master.Pages 的嵌套网格 在标记中,将 ID 分配给嵌套网格中的 FooterControl,如 'mggvDDLMember' 会生成 'ct100$MainContent$UserGroupGridView$GroupMemberGridView$.....$mggvDDLMemberName'.
像这样在后面的代码中设置 ID:
ControlToValidate = 'mggvDDLMemberName'
抛出找不到控件的错误。
使用控件的 uniqueID,mggvDDLMemberName 是 'ct100$MainContent$UserGroupGridView$GroupMemberGridView$..$mggvDDLMemberName 这会产生 ControlToValidate 在表单标签之外的错误,因为 MainContent 是 PlaceContentHolder:
ControlToValidate = ((DropDownList)tFooterControls.FindControl("mggvDDLMemberName")).UniqueID;
试图消除 'ct100' 以便控件位于占位符内。我试试这个:
ControlToValidate = ((Dropdown) this.Form.FindControl("MainContent").FindControl("UserGroupGridView").FindControl("ct102").FindControl("GroupMemberGridView").FindControl("ctl13").FindControl("mggvDDLMemberName")).ID;
它抛出找不到控件的错误。 我真的不知道如何做到这一点,或者是否可以做到......:( 我尝试了客户端解决方案无济于事。我可能需要再调查一下。
更新 我回到了验证器的原始设计,而不是动态添加它们。这是带有验证器的 FooterTemplate 标记:
<FooterTemplate>
<asp:DropDownList ID="mggvDDLMemberName" runat="server" class="chosen-single" data-placeholder="Choose member…">
</asp:DropDownList>
<asp:RequiredFieldValidator ID="ReqValueDDLMemberInsert" runat="server" InitialValue="0" ControlToValidate="mggvDDLMemberName" ValidationGroup="InsertGroupMemberValidation" ErrorMessage="Selection required." CssClass="message-error-dropdown">
</asp:RequiredFieldValidator>
</FooterTemplate>
这是开始验证的添加按钮:
<FooterTemplate>
<asp:Button ID="mggvAddButton" runat="server" CommandName="Add" Text="Add Member" Width="90%" CssClass="gridActionbutton" CausesValidation="true" ValidationGroup="InsertGroupMemberValidation" >
</asp:Button>
</FooterTemplate>
我自己也在处理这样的事情。据我了解(例如http://forums.asp.net/t/952691.aspx?Problem+in+Custom+Control+Unable+to+find+Control+To+Validate+Property+),验证器的 ControlToValidate
必须 或者 设置为控件的 ID
provided和控件放在同一个NamingContaineror可以设置为控件的UniqueID
提供验证器放在实际的页面.
[编辑:这一段和链接的解释是inadequate/incomplete;请参阅下面我的新单独 post 以获得正确的讨论和解决方案。]
我认为 grids/repeaters 中的每一行都是它自己的 NamingContainer。无论如何,如果您尝试(坚持 UniqueID
)将验证器添加到 Page 级别(注意 validator.ID
本身必须是唯一的,或者不设置它?),这现在使您的情况可行吗?我很想知道....
P.S。
或者,要将控件的 ID
用于 ControlToValidate
,您必须在控件旁边添加验证器,即将其添加到 DropDownList 的 Parent 的控件集合中,而不是你要把它放在哪里?
我正在添加一个新答案,以一劳永逸地阐明在 所有 情况下 BaseValidator.ControlToValidate
需要设置的内容,包括 descendent/nested 控件,因为有很多关于这个的问题。我希望这可能对其他人以及当前的提问者将来有用。
我在上面找到的参考资料是 incorrect/insufficient,其他地方的帖子也说明它应该设置为 Control.ID
或 Control.UniqueID
。在 all 情况下有效的代码使用了 .NET 4 中添加的方法:Control.GetUniqueIDRelativeTo(Control control)
。我在网络上的任何地方都找不到使用示例(包括 Whosebug 中的此处)。给定一个 BaseValidator validator
和一个 Control control
,一旦它们都被添加到页面的控件层次结构中,需要以下内容:
validator.ControlToValidate = control.GetUniqueIDRelativeTo(validator);
GetUniqueIDRelativeTo
的文档是 incorrect/misleading。它表示 returns "The prefixed portion of the UniqueID property of the specified control";事实上它 returns "suffixed" 部分,即前缀 右边 的部分,这就是方法名称所暗示的。实际上,returns control.UniqueID
的右侧部分在从左侧移除 validator.NamingContainer.UniqueID
后仍然存在。这会正确处理 descendent/nested 控件。
将BaseValidator.ControlToValidate
设置为Control.ID
或Control.UniqueID
只是上述的退化情况,在特殊情况下有效(和GetUniqueIDRelativeTo()
returns相同无论如何结果)。如果(且仅当)验证器和控件在 same NamingContainer 中,那么 Control.ID
有效;如果(且仅当)验证器的 NamingContainer 是 Page,则 Control.UniqueID
有效。在其他 nested/descendent 情况下均无效。
重要的是,如果控件的 NamingContainer 不 与验证器的 NamingContainer[=59 相同或不是其后代=] 然后 control.GetUniqueIDRelativeTo(validator)
变为 throw new InvalidOperationException("This control is not a descendent of the NamingContainer of '<validator>'")
。当 ASP.NET 生成有关无法定位要验证的控件的错误时,这就是导致错误的原因。在这种情况下,您需要在页面正常工作之前将其解决,方法是将验证器移动到控件所在的位置或移动到首页级别。
对于最初的提问者:ID
和 UniqueID
对于她的原始代码都不正确,如上所述。我认为她最后通过将验证器从单独的 location/NamingContainer 移动到与 DropDownList 控件相同的 location/NamingContainer 中解决了这个问题,因此现在能够摆脱 ID
退化情况.
这对我有用... 需要唯一的不是 ID,而是 ValidationGroup 名称。 因此,我在 FooterTemplate 的标记中创建了所有控件。但是我没有命名 ValidationGroup 属性。我在代码隐藏中这样做了。 这是下拉菜单、验证器和按钮的标记:
<FooterTemplate>
<asp:DropDownList runat="server"
ID="mggvDDLMemberName"
class="chosen-single"
data-placeholder="Choose member…">
</asp:DropDownList>
<asp:RequiredFieldValidator runat="server"
ID="ReqValueDDLMemberInsert"
InitialValue="0"
ControlToValidate="mggvDDLMemberName"
ErrorMessage="Selection required."
CssClass="message-error-dropdown">
</asp:RequiredFieldValidator>
</FooterTemplate>
<FooterTemplate>
<asp:Button runat="server"
ID="mggvAddButton"
CommandName="Add"
Text="Add Member"
Width="90%"
CssClass="gridActionbutton"/>
</FooterTemplate>
在 RowDataBound 事件中,当我将数据绑定到下拉列表时,我为每个控件命名了 ValidationGroup。
protected void UserGroupGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
try
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
int tiGroupID = Convert.ToInt32(UserGroupGridView.DataKeys[e.Row.RowIndex].Value.ToString());
GridView tgvGroupMember = (GridView)e.Row.FindControl("GroupMemberGridView");
populateGroupMemberGrid(tgvGroupMember, tiGroupID);
//Get the Footer controls
Control tFooterControls = CommonMethods.getFooterControls(tgvGroupMember);
DropDownList tddlRecipientNames = tFooterControls.FindControl("mggvDDLMemberName") as DropDownList;
m_strXmlTableData = m_pagingClient.GetAllPossibleGroupMembers(m_strUserID, tiGroupID);
DataTable tdtAllGroupMembers = CommonMethods.ParseXML(m_strXmlTableData);
tddlRecipientNames.DataSource = tdtAllGroupMembers;
tddlRecipientNames.DataTextField = tdtAllGroupMembers.Columns["MemberName"].ToString();
tddlRecipientNames.DataValueField = tdtAllGroupMembers.Columns["MemberID"].ToString();
tddlRecipientNames.ValidationGroup = "InsertMember" + tiGroupID.ToString();
tddlRecipientNames.DataBind();
tddlRecipientNames.Items.Insert(0, new ListItem("", "0"));//This is needed for the jquery-chosen dropdown to add data-holder text
RequiredFieldValidator validator = (RequiredFieldValidator)tFooterControls.FindControl("ReqValueDDLMemberInsert");
validator.ControlToValidate = ((DropDownList)tFooterControls.FindControl("mggvDDLMemberName")).GetUniqueIDRelativeTo(validator);
validator.ErrorMessage = "Selection required.";
validator.CssClass = "message-error-dropdown";
validator.ValidationGroup = "InsertMember" + tiGroupID.ToString();
Button tbtnAdd = tFooterControls.FindControl("mggvAddButton") as Button;
tbtnAdd.ValidationGroup = "InsertMember" + tiGroupID.ToString();
tbtnAdd.CausesValidation = true;
}
}
catch (Exception ex)
{
logger.ErrorException(ex.Message, ex);
Response.Redirect("~/Error.aspx?use=" + m_strUserType);
}
}
我希望这对其他人有所帮助并为他们节省一点时间。