Reputation: 305
I have the following nested structure. What I need is to filter a DB Linq query from within CustomControl1 code behind based on the value of the RadioButtonList selection.
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)
I am trying something like the following to find the control, but it says "The name 'upMailOrStatusAction' does not exist in the current context.
RadioButtonList rbl = upMailOrStatusAction.FindControl("rblActionLevel") as RadioButtonList;
What is the best way to find the RadioButtonList control? Yes, I am fairly new with this!
Thank you, Jim in Suwanee, GA
Ok, Here is the Popup 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>
And here is the subform aspx:
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="MailAddSubform.ascx.cs"
Inherits="Company.Solutions.Web.Controls.MailAddSubform" %>
Action:
Message:
And here is the custom control aspx:
Filters
And finally, here is the code behind for the custom control. Look for StackOverflow for where I am tring to lookup the radio button list:
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();
}
}
}
New code list. My co-worker used this for another lookup. Could someone show me how I would do something similar for this lookup? Even if inefficient, if it works so be it.
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();
}
}
}
}
}
}
Ok, I am trying this, but have not quite figured out yet how to determine the selected value of the radio button:
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) {
}
}
}
}
Upvotes: 0
Views: 3446
Reputation: 32950
I'm not sure whether I fully understood what you're trying to achieve. But if you want to find a control on your page, you might want a solution as I posted 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;
}
It is a recursive implementation of the standard find control. But choose your parent wisely. If you have a large page and you indicate that to be the search root, then it will traverse all of the controls of the page till the deepest nested control. You could also go the reversed way, basically starting from your control and recursively go up till you reach the page level. Would be another option.
The only issue I found with this recursive find is that you might get problems when having a repeater on your page. You shouldn't traverse the repeater's inner controls. Due to its architecture there are some problems that it will loose it's viewstate otherwise. Once I've time I'll post an update of this recursive method.
Edit:
You get the selected entry of the radio button as follows:
RadioButtonList myInstance = //find my radio button list
string selectedValue = myInstance.SelectedValue;
Upvotes: 2
Reputation: 305
Ok, finally got this working thanks to everybody's help. Thanks JayRu for steering me in the right direction. Here is what I am using (it still needs a bit of work to hook it up):
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") {
}
}
}
}
}
Upvotes: 0
Reputation: 319
"An object reference is required for the non-static field, method, or property 'System.Web.UI.Control.Parent.Get' Using the following: RadioButtonList rbl = (RadioButtonList) StMailActionLookup.Parent.FindControl("rblActionLevel");
You reference the object type "StMailActionLookup" when you should reference "mailActionLookup", the ID of the instance of the control.
So that code would look like:
RadioButtonList rbl = (RadioButtonList) mailActionLookup.Parent.FindControl("rblActionLevel");
Not sure if that's the problem with the code you came up with, however, just a small correction.
Also, remember that the UpdatePanel is a templated control and the RadioButtonList and all other controls are rendered inside of its ContentTemplateContainer somewhere in the UpdatePanels's lifecycle (I think it's somewhere around CreateChildControls). It depends on where your BindForm() method is called from, but it could be that the RadioButtonList truly isn't available yet at the time you're trying to find it. Even if its in markup, controls in a template aren't created the same way as other controls in markup are. They're kind of weird beasts.
For a test, try running the find control code in an overridden Render method or something like that. By the Render method you're guaranteed that all controls will be available.
public override Render(HtmlTextWriter writer) {
RadioButtonList rbl = (RadioButtonList)upMailOrStatusAction.FindControl("rblActionLevel");
}
Also, since the upMailOrStatusAction is an UpdatePanel, the code might be
upMailOrStatusAction.ContentTemplateContainer.FindControl("rblActionLevel");
Upvotes: 0
Reputation: 52547
Piggybacking on Chaos...
RadioButtonList rbl = (RadioButtonList)Control.Parent.FindControl("rblActionLevel")
Upvotes: 0
Reputation: 78312
Use the property Parent to make your way up the control tree.
CustomControl1.Parent.Parent.Parent.FindControl("rblActionLevel");
Upvotes: 0