Iterate though all controls on asp.net page - asp.net

I'm using ascx and I need to iterate through all of the controls and selects each that have cssClass attribute set to 'required'.
I have the following code:
foreach (Control masterControl in Page.Controls)
{
if (masterControl is MasterPage)
{
foreach (Control formControl in masterControl.Controls)
{
if (formControl is System.Web.UI.HtmlControls.HtmlForm)
{
foreach (Control contentControl in formControl.Controls)
{
if (contentControl is ContentPlaceHolder)
{
foreach (Control childControl in contentControl.Controls)
{
}
}
}
}
}
}
}
however.. i cannot access childControl.CssClass. How do I access it?
Thanks in advance!

CssClass property is a member of the WebControl class.
You have to check if the control is a webcontrol, or, if it's only a control, you can get the attribute "class" in the attributes collection.
for example, you can do :
List<WebControl> wcs = new List<WebControl>();
GetControlList<WebControl>(Page.Controls, wcs)
foreach (WebControl childControl in wcs)
{
if(childControl.CssClass == "required") {
// process the control
}
}
You also have to iterate recursively. Code found here : Using C# to recursively get a collection of controls from a controlcollection :
private void GetControlList<T>(ControlCollection controlCollection, List<T> resultCollection)
where T : Control
{
foreach (Control control in controlCollection)
{
//if (control.GetType() == typeof(T))
if (control is T) // This is cleaner
resultCollection.Add((T)control);
if (control.HasControls())
GetControlList(control.Controls, resultCollection);
}
}

The Control class doesn't have that CssClass property, the WebControl does. So try to cast your childControl to WebControl. If that worked, then you can access the CssClass property.
WebControl webCtrl = childControl as WebControl;
if (webCtrl != null)
{
webCtrl.CssClass = "test";
}

Regarding your comment on the answer above, you need to first check that it is a WebControl and then cast it to a WebControl
var webControl = childControl as WebControl;
if(webControl != null)
{
if(webControl.CssClass == 'required')
// Do your stuff
}

Related

How to find control image button inside repeater, which is already inside a datalist

How to find control (i.e image button) inside repeater, that repeater is already in a datalist? because I have to perform delete operation on that image button.
Here is my code, here I'm getting repeater but not image button:
foreach (DataListItem item in Dlist_SearchResult.Controls)
{
rptrResult = (Repeater)item.FindControl("Rptr_result");
imgbtnDelete = (ImageButton)item.FindControl("imgbtnDelete");
}
You can use Recursion in your FindControl. FindControl by default is not recursive.
Try this:
private static Control FindControlRecursive(Control rootCtrl, string ID)
{
if (rootCtrl.ID == ID)
return rootCtrl;
foreach (Control ctr in rootCtrl.Controls)
{
Control foundCtl = FindControlRecursive(ctr, ID);
if (foundCtl != null)
return foundCtl;
}
return null;
}
you can call it
Button btn = FindControlRecursive((Control)Page,"imgbtnDelete");

Get reference of image button click event in gridview in http module

How do we pass the Click event of ImageButton inside a GridView to httpmodule
for linkbutton's i am doing this way:
if (request.Form.GetValues("__EVENTTARGET") != null)
{
//If it's a link button execute we can directley check for the params
if (request.Params.Get("__EVENTTARGET").Contains("xyz"))
{
//some Code
}
This is not working for ImageButton.
If you're trying to attach an event to a button within a gridview might I suggest in your base page on the prerender event parse through all gridviews on the page (use a recursive findcontrol algorithm) and look for any imagebuttons, if you find one you should then be able to attach an event to it.
EDIT:
I use something similar in the following:
public abstract class AmendmentPopUpWindow : BaseMasterPlanPage
{
// override this method if the correct save controls arent being hidden in the popups
public virtual IEnumerable<WebControl> SaveControls
{
get { return Controls.All().OfType<WebControl>().Where(c => c.ID.ToLower().Contains("save")); }
}
protected override void OnPreRender(EventArgs e)
{
if (WebConfiguration.Global_EnableAmendments && SystemVersion.HasValue)
{
foreach (var control in Controls.All())
{
if (control is RadioButton || control is TextBox || control is DropDownList || control is RadComboBox || control is CheckBox || control is CheckBoxList ||
control is RadEditor || control is RadTextBox || control is RadNumericTextBox)
{
var webControl = control as WebControl;
webControl.Enabled = false;
webControl.ForeColor = Color.Gray;
}
}
foreach (var saveControl in SaveControls)
saveControl.Visible = false;
}
base.OnPreRender(e);
}
EDIT: The .All() is an extension method defined as follows (stolen from here)
public static IEnumerable<Control> All(this ControlCollection controls)
{
foreach (Control control in controls)
{
foreach (Control grandChild in control.Controls.All())
yield return grandChild;
yield return control;
}
}
ImageButtons have an additional quasi-property in their names which identifies the mouse-coordinates (X and Y).
So to find the ImageButton's name your should iterate through posted parameters and found those which end with .x or .y:
foreach (string item in request.Form)
{
if (item.EndsWith(".x") || item.EndsWith(".y"))
{
var controlName = item.Substring(0, item.Length - 2);
// some code here
}
}
You could also cound this answer useful. It contains a more generic method to determine which control caused a postback.

any easy way to check if no items has been selected in a checkboxlist control?

I know I can loop through a checkboxlist.Items and see if none of them is selected, but is there a better way to find out if no items have been selected, in the code behind?
You have to check the SelectedIndex. If it equals -1, its means nothing is selected.
CheckBoxList list = new CheckBoxList();
if (list.SelectedIndex == -1)
{
//Nothing is selected
}
CheckBoxList has properties for SelectedIndex and SelectedValue.
You can check whether there is a SelectedIndex; it will be -1 if no items are checked.
This is probably the easiest way to validate the CheckBoxList:
Use a custom validator:
<asp:CustomValidator runat="server" ID="cvmodulelist" ClientValidationFunction="ValidateModuleList" ErrorMessage="Please Select Atleast one Module"></asp:CustomValidator>
Create a JavaScript function to validate the CheckBoxList:
// javascript to add to your aspx page
function ValidateModuleList(source, args)
{
var chkListModules= document.getElementById ('<%= chkModuleList.ClientID %>');
var chkListinputs = chkListModules.getElementsByTagName("input");
for (var i=0;i<chkListinputs .length;i++)
{
if (chkListinputs [i].checked)
{
args.IsValid = true;
return;
}
}
args.IsValid = false;
}
Another option is to create a custom validation control, like this:
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
namespace CustomValidators
{
public class RequiredFieldValidatorForCheckBoxLists : System.Web.UI.WebControls.BaseValidator
{
private ListControl _listctrl;
public RequiredFieldValidatorForCheckBoxLists()
{
base.EnableClientScript = false;
}
protected override bool ControlPropertiesValid()
{
Control ctrl = FindControl(ControlToValidate);
if (ctrl != null)
{
_listctrl = (ListControl) ctrl;
return (_listctrl != null);
}
else
return false; // raise exception
}
protected override bool EvaluateIsValid()
{
return _listctrl.SelectedIndex != -1;
}
}
}
You have to check selected index. If selected index is -1 it means that no item is being selected.
if (CheckBoxList1.SelectedIndex == -1)
{
Response.Write("<script> alert('Show your message') </script>");
}

Access nested web user control elements

I have a nested web user control. Main web user control I have used on a page but now I want to access the control inside the inner web user control and its events.
Can any body help me in this issue.
In the parent user control, expose a reference to your child control, or it's properties through a property. For example
public partial class ParentControl : UserControl
{
...
// Expose the whole child control
public ChildControl MyChild
{
get { return this.theIdOfTheChildControl; }
}
...
// or expose specific properties
public string MyChildText
{
get { return this.theIdOfTheChildControl.Text; }
set { this.theIdOfTheChildControl.Text = value; }
}
}
try this method
private List<Control> GetAllNestedUserControl(Control ph)
{
List<Control> Get = new List<Control>();
foreach (var control in ph.Controls)
{
if (control is UserControl)
{
UserControl uc = control as UserControl;
if (uc.HasControls())
{
Get = GetAllNestedUserControl(uc);
}
}
else
{
Control c = (Control)control;
if (!(control is LiteralControl))
{
Get.Add(c);
}
}
}
return Get;
}
this method will return the list of all controls then do the following to get the control u want
List<Control> Get = GetAllNestedUserControl(ph);
Label l = (Label)Get.Find(o => o.ID == "lblusername");
l.Text = "changed from master";

Programatic Access to DragHandleTemplate in ASP.NET AJAX ReorderList

Is there a way to programatically access the DragHandleTemplate of a ReorderList (ASP.NET AJAX Control Toolkit) ... Specifically during ItemDataBound for the ReorderList, in order to change its appearance at the per item level?
You can also express FindControlRecursive in LINQ:
private Control FindControlRecursive(Control root, string id)
{
return root.ID == id
? root
: (root.Controls.Cast<Control>().Select(c => FindControlRecursive(c, id)))
.FirstOrDefault(t => t != null);
}
Unfortunately there is no way of getting drag holder from ReorderListItem. Instead, you can create a server control inside DragHandleTemplate (e.g. PlaceHolder) and then find it in your ItemDataBound event handler:
In aspx file:
<DragHandleTemplate>
<div class="dragHandle">
<asp:Label ID="lblDragHandle" runat="server" />
</div>
</DragHandleTemplate>
In aspx.cs file:
protected void ReorderList1_ItemDataBound(object sender, AjaxControlToolkit.ReorderListItemEventArgs e)
{
Label lblDragHandle = (Label)FindControlRecursive(e.Item, "lblDragHandle");
lblDragHandle.Text = e.Item.ItemIndex.ToString();
}
private Control FindControlRecursive(Control root, string id)
{
if (root.ID == id)
{
return root;
}
foreach (Control c in root.Controls)
{
Control t = FindControlRecursive(c, id);
if (t != null)
{
return t;
}
}
return null;
}
I copied FindControlRecursive method from Jeff's blog.
You can not access DragHandleTemplate programatically on the server, but if you create the surrounding elements with unique ID's (per row) you should be able the use CSS-selectors or Javascript to only change some of the items.

Resources