如何从嵌套内部控件查找外部控件
我有以下嵌套结构。我需要的是根据RadioButtonList选项的值从后面的CustomControl1代码中过滤一个DB Linq查询。如何从嵌套内部控件查找外部控件
x MainPage1
x---- Panel1 (modal popup)
x--------- UpdatePanel (upMailOrStatusAction, on Panel1)
x-------------- RadioButtonList (rblActionLevel, on UpdatePanel)
x-------------- SubForm1 (on Panel1)
x------------------- CustomControl1 (on Subform1)
x------------------------ DropDownList (on CustomControl1)
我想类似下面找到了控制,但它说:“‘upMailOrStatusAction’这个名字不会在目前情况下存在。
RadioButtonList rbl = upMailOrStatusAction.FindControl("rblActionLevel") as RadioButtonList;
什么是找到最好的办法?!RadioButtonList控件是的,我与这个相当新
谢谢 吉姆萨瓦尼,GA
好,这里是弹出ASPX:
<asp:Panel ID="pnlAddMailOrStatusAction" runat="server" CssClass="modalPopupLarge" Style="display: none;">
<asp:UpdatePanel ID="upMailOrStatusAction" runat="server" UpdateMode="Conditional" ChildrenAsTriggers="false" RenderMode="Block">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="rblActionType" />
</Triggers>
<ContentTemplate>
<div class="borderDiv">
<table class="borderTable0" cellpadding="0" cellspacing="0" width="100%">
<thead>
<tr align="left">
<th colspan="9">Action Detail</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="1">
<label class="labelfield">Action Level:</label>
</td>
<td colspan="1" rowspan="1" align="left">
<asp:RadioButtonList ID="rblActionLevel" runat="server" AutoPostBack="True" RepeatDirection="Horizontal"
RepeatLayout="Flow">
<asp:ListItem Selected="True" Value="Base" Text="Base " />
<asp:ListItem Value="Coverage" Text="Coverage" />
</asp:RadioButtonList>
</td>
<td colspan="1" align="left">
<asp:Label ID="lblMSCoverage" runat="server" class="labelfield" Text="Coverage:" />
</td>
<td colspan="1" align="left">
<asp:Label ID="txtMSCoverage" runat="server" />
</td>
<td colspan="5">
</td>
</tr>
<tr>
<td colspan="9">
<hr />
</td>
</tr>
<tr>
<td colspan="9">
<st:MailAddSubform runat="server" ID="mailAddSubform" />
<st:StatusActionAddSubform runat="server" ID="statusActionAddSubform" Visible="false" />
</td>
</tr>
<tr>
<td colspan="9">
<hr />
</td>
</tr>
</tbody>
</table>
</div>
</ContentTemplate>
</asp:UpdatePanel>
</asp:Panel>
这里是子窗体的aspx:
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="MailAddSubform.ascx.cs"
Inherits="Company.Solutions.Web.Controls.MailAddSubform" %>
操作: 消息: 这里是自定义控件的aspx: 过滤器
最后,这里是背后的定制控件的代码。查找StackOverflow以查找单选按钮列表:
using System;
using System.Collections.Generic;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using Company.Solutions.Data;
using Company.Solutions.Data.Model;
using Company.Solutions.Business.ViewModels;
using Company.Solutions.Business.Helpers;
namespace Comapny.Solutions.Web.Controls
{
public partial class StMailActionLookup : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
BindForm();
}
protected void BindForm()
{
IEnumerable actions = GetClaimMailActions(GetFilter());
ddlLookup.DataSource = actions;
ddlLookup.DataTextField = "CodeAndDescription";
ddlLookup.DataValueField = "actionCd";
ddlLookup.DataBind();
}
//protected void ddlLookup_DataBound1(object sender, System.EventArgs e)
//{
// ddlLookup.Items.Insert(0, new ListItem("<Please Choose an Action>", String.Empty));
//}
private MailActionFilters GetFilter()
{
MailActionFilters filters = new MailActionFilters();
if (chkForms.Checked)
filters |= MailActionFilters.Forms;
if (chkRequested.Checked)
filters |= MailActionFilters.RequestedInfo;
if (chkOther.Checked)
filters |= MailActionFilters.Other;
return filters;
}
public IEnumerable GetClaimMailActions(MailActionFilters filter)
{
RelationalDataContext db = RelationalDataContext.Create();
List<Expression<Func<ClaimMailAction, bool>>> predicates = new List<Expression<Func<ClaimMailAction, bool>>>();
const string MAIL_ACTIONS = "0";
const char FORMS = 'F';
const char REQUESTED_INFO = 'R';
const char EXCLUDE = 'X';
//StackOverflow help
//RadioButtonList rbl = (RadioButtonList) Control.Parent.FindControl("rblActionLevel");
if ((!chkForms.Checked && !chkRequested.Checked && !chkOther.Checked) | (chkForms.Checked && chkRequested.Checked && chkOther.Checked))
{
predicates.Add(cma => cma.ActionCd.StartsWith(MAIL_ACTIONS) && (cma.EsolutionsCode == null || cma.EsolutionsCode!= EXCLUDE));
} else {
if((filter & MailActionFilters.Forms) == MailActionFilters.Forms)
predicates.Add(cma => cma.ActionCd.StartsWith(MAIL_ACTIONS) && cma.EsolutionsCode == FORMS);
if((filter & MailActionFilters.RequestedInfo) == MailActionFilters.RequestedInfo)
predicates.Add(cma => cma.ActionCd.StartsWith(MAIL_ACTIONS) && cma.EsolutionsCode == REQUESTED_INFO);
if((filter & MailActionFilters.Other) == MailActionFilters.Other)
predicates.Add(cma => cma.ActionCd.StartsWith(MAIL_ACTIONS) && (cma.EsolutionsCode == null || (cma.EsolutionsCode != EXCLUDE && cma.EsolutionsCode != FORMS && cma.EsolutionsCode != REQUESTED_INFO)));
}
var predicate = PredicateBuilder.Make<ClaimMailAction>();
predicates.ForEach(delegate(Expression<Func<ClaimMailAction, bool>> expr)
{
predicate = predicate.Or(expr);
});
var qry = db.ClaimMailActions.Where(predicate).Select(c => new { c.ActionCd, CodeAndDescription = string.Format("{0} - {1}", c.ActionCd, c.ActionDesc) });
return qry.ToList();
}
}
}
新的代码列表。我的同事将这个用于另一个查找。有人能告诉我如何为这个查找做类似的事吗?即使效率低下,如果它的效果如此。
HtmlForm form;
foreach(var ctl in Page.Controls[0].Controls)
{
if(ctl is HtmlForm)
{
form = ctl as HtmlForm;
ContentPlaceHolder holder = form.FindControl("DefaultContent") as ContentPlaceHolder;
if (holder != null)
{
PlaceHolder paymentControlHolder = holder.FindControl("plcPaymentForm") as PlaceHolder;
if (paymentControlHolder != null)
{
IListener listener;
foreach (var c in paymentControlHolder.Controls)
{
if (c is IListener)
{
listener = c as IListener;
rblPaymentType.SelectedIndexChanged += listener.AddHandler();
}
}
}
}
}
}
好吧,我想这一点,但还没有完全想通了,但如何确定单选按钮的选定值:
HtmlForm form;
foreach (var ctl in Page.Controls[0].Controls) {
if (ctl is HtmlForm) {
form = ctl as HtmlForm;
ContentPlaceHolder holder = form.FindControl("DefaultContent") as ContentPlaceHolder;
if (holder != null) {
RadioButtonList rblControlHolder = holder.FindControl("rblActionLevel") as RadioButtonList;
if (rblControlHolder != null) {
}
}
}
}
我不知道是否我完全理解你想要达到的目标。但是如果你想在你的页面上找到控件,你可能需要一个解决方案,因为我发布了here。
public static Control FindControlRecursive(Control parent, string controlId)
{
if (controlId == parent.ID)
return parent;
foreach (Control ctrl in parent.Controls)
{
Control tmp = FindControlRecursive(ctrl, controlId);
if (tmp != null)
return tmp;
}
return null;
}
它是标准查找控件的递归实现。但明智地选择你的父母。如果你有一个大的页面,并且你指出这是搜索根目录,那么它将遍历页面的所有控件,直到最深的嵌套控件。您也可以采用相反的方式,基本上从您的控制开始,递归地上升,直到达到页面级别。将是另一种选择。
我发现这个递归发现的唯一问题是,当你的页面上有一个中继器时,你可能会遇到问题。你不应该穿过中继器的内部控制。由于其架构有一些问题,否则将会失去视图状态。一旦我有空,我会发布这个递归方法的更新。
编辑:
你得到的单选按钮的选定条目,如下所示:
RadioButtonList myInstance = //find my radio button list
string selectedValue = myInstance.SelectedValue;
使用属性Parent,使自己的方式控制树。
CustomControl1.Parent.Parent.Parent.FindControl("rblActionLevel");
好吧,我明白了,但我在自定义控制的代码背后的定义是这样的: 公共部分类StMailActionLookup:System.Web.UI.UserControl 而且我得到“一个对象引用是必需的非静态字段,方法或属性'System.Web.UI.Control.Parent.Get' 使用以下内容: RadioButtonList rbl =(RadioButtonList)StMailActionLookup.Parent.FindControl(“rblActionLevel”); – James 2009-09-03 03:53:25
为什么不张贴你的整个表格,以便我们可以分析结构。 – ChaosPandion 2009-09-03 04:14:17
捎带混沌...
RadioButtonList rbl = (RadioButtonList)Control.Parent.FindControl("rblActionLevel")
“的对象引用是所必需的非静态字段,方法或属性“System.Web.UI.Control.Parent。获取”使用下面的:单选按钮列表RBL =(单选按钮列表)StMailActionLookup.Parent.FindControl( “rblActionLevel”);
你引用的对象类型 “StMailActionLookup” 时,你应该参考“邮件ActionLookup“,这是控件实例的ID。
这样的代码看起来像:
RadioButtonList rbl = (RadioButtonList) mailActionLookup.Parent.FindControl("rblActionLevel");
不知道,如果这是你想出了,但只是一个小的修正代码中的问题。
另外,请记住UpdatePanel是一个模板化的控件,RadioButtonList和所有其他控件都在UpdatePanels生命周期某处的ContentTemplateContainer中呈现(我认为它在CreateChildControls周围的某处)。它取决于你从哪里调用BindForm()方法,但可能是因为RadioButtonList在你试图找到它的时候确实不可用。即使它在标记中,模板中的控件也不会像标记中的其他控件一样创建。他们有点怪异的野兽。
对于测试,尝试在重写的Render方法或类似的东西中运行查找控制代码。通过Render方法,你可以保证所有的控件都可用。
public override Render(HtmlTextWriter writer) {
RadioButtonList rbl = (RadioButtonList)upMailOrStatusAction.FindControl("rblActionLevel");
}
此外,由于upMailOrStatusAction是一个UpdatePanel,代码可能是
upMailOrStatusAction.ContentTemplateContainer.FindControl("rblActionLevel");
对于你的第一个代码示例“mailActionLookup”和第二个示例“upMailOrStatusAction”,我得到了“该名称在当前上下文中不存在”的错误,每个错误都引用这个引号中的字段。我还没有尝试渲染,但我会。谢谢, Jim – James 2009-09-03 05:34:49
是的,对不起,我应该仔细阅读代码。 mailActionLookup是RadioButtonList的兄弟(完全错过了),因此编写非脆弱的代码很困难。最好的办法是启动页面,并按照radiobuttonlist的层次结构进行递归搜索。 Page.FindControl不会执行这个技巧,因为它只有一层深度。你需要在网上找到一个辅助方法。 或者,您可以正确使用从mailActionControl开始的帮助程序方法,并且可以搜索每个父控件的控件集合。但两者效率都很低。 – JayRu 2009-09-03 05:50:09
不知道是否可以根据单选按钮选择设置会话变量并在此处读取该值?应该有一个更简单的方法!谢谢, Jim – James 2009-09-03 05:57:59
好吧,终于得到了这方面的工作多亏了大家的帮助。感谢JayRu指导我朝着正确的方向前进。这是我使用的(它仍然需要一些工作来挂钩它):
HtmlForm form;
foreach (var ctl in Page.Controls[0].Controls) {
if (ctl is HtmlForm) {
form = ctl as HtmlForm;
ContentPlaceHolder holder = form.FindControl("DefaultContent") as ContentPlaceHolder;
if (holder != null) {
RadioButtonList rblControlHolder = holder.FindControl("rblActionLevel") as RadioButtonList;
if (rblControlHolder != null) {
if (rblControlHolder.SelectedValue == "Base") {
}
}
}
}
}
如果JayRu让你找到解决方案的途径,也许你应该接受他的答案。或者至少给他投票(假设你有足够的代表投票...不知道) – 2009-09-03 13:32:09
Juri, 目标仅仅是确定单选按钮值,以便我可以修改我的查询以相应地填充下拉列表。我会尝试你的查询以及它可能派上用场。 谢谢! Jim – James 2009-09-03 12:58:22
如果你的radiobuttonlist在你的用户控件或页面上,你应该可以直接访问它,不是吗?或者至少是它的容器元素。我真的不明白为什么你必须从页面向下遍历所有内容。 – Juri 2009-09-03 13:08:01
顺便说一句,下面的代码可以通过调用我的FindControlRecursive(this.Page,“rblActionLevel”)作为RadioButtonList来解决,尽管我仍然坚信有一个简单的方法。 – Juri 2009-09-03 13:08:50