Find a image in code behind - c#

I would like to use the find control method to find a image on the designer and make it visible, but i keep getting a null
This is my Code:
foreach (ImageShow image in imageList)
{
Image Showimage = (Image)FindControl(image.imageName);
Showimage.Visible = true;
}
Any help would be much appreciated,
Thanks in advance

FindControl does not search throughout a hierarchy of controls, I presume that this is a problem.
try using the following method :
public static T FindControlRecursive<T>(Control holder, string controlID) where T : Control
{
Control foundControl = null;
foreach (Control ctrl in holder.Controls)
{
if (ctrl.GetType().Equals(typeof(T)) &&
(string.IsNullOrEmpty(controlID) || (!string.IsNullOrEmpty(controlID) && ctrl.ID.Equals(controlID))))
{
foundControl = ctrl;
}
else if (ctrl.Controls.Count > 0)
{
foundControl = FindControlRecursive<T>(ctrl, controlID);
}
if (foundControl != null)
break;
}
return (T)foundControl;
}
Usage:
Image Showimage = FindControlRecursive<Image>(parent, image.imageName);
In your case parent is this, example :
Image Showimage = FindControlRecursive<Image>(this, image.imageName);
You can use it without ID, then will find first occurrence of T :
Image Showimage = FindControlRecursive<Image>(this, string.Empty);

foreach (ImageShow image in imageList)
{
Image showimage = FindControl(image.imageName) as Image;
if(showimage != null)
{
showimage .Visible = true;
}
}

Related

Using the value of a variable to set the visiblity of a Panel

Hello all I am slowly learning c#, and I have this problem:
I want to make a function that sets all panels not visible and then set one as visible given to me from a string variable.
public void setMeVisible(string PanelName)
{
PageMainScreen.Visible = false;
PageNewRegistration.Visible = false;
PageSelectedPatient.Visible = false;
["PanelName"].Visible = true; // in this line I want to set the value of
// PanelName.Visible=true.
// what is the format that I must put PanelName?
}
For Windows, The simplest way is loop through all the controls and check if its a panel and set it to false. In the same loop you can check panel.Name for the pass in "PanelName" and set it to true. Something like this
foreach(Control control in form.Controls)
{
if( control is Panel )
{
control.Visible = false;
if(control.Name == "PanelName")
control.Visible = true;
}
}
Use Page.FindControl for ASP.Net:
var control = FindControl(PanelName);
if (control != null)
control.Visible = true;
If your control is nested, you can create a FindControlRecursive function, suggested by this answer:
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);
}
Then call it by doing:
var control = FindControlRecursive(form1, PanelName); // Or another top-level control other than form1
if (control != null)
control.Visible = true;
Use Controls.Find for a windows form application:
var control = Controls.Find(PanelName, true).FirstOrDefault();
if (control != null)
control.Visible = true;
Looping and finding controls is not really necessary. You should add all your panels to a same container, use the Controls collection and pass in the name to get the control:
public void setMeVisible(string PanelName) {
PageMainScreen.Visible = false;
PageNewRegistration.Visible = false;
PageSelectedPatient.Visible = false;
Control c = sameContainer.Controls[PanelName];
if(c != null) c.Visible = true;
}
If each time there is only 1 panel visible, you should use some variable to track the current shown panel and hide only this (instead of all controls as you did) like this:
Control currentShown;
public void setMeVisible(string PanelName) {
Control c = sameContainer.Controls[PanelName];
if(c != null) {
c.Visible = true;
if(currentShown != null) currentShown.Visible = false;
currentShown = c;
}
}
And the last, if you don't want to use the same container for all your panels. You should declare some List<Panel> to contain all your panels, then you can navigate through them easily:
List<Panel> panels = new List<Panel>();
panels.AddRange(new[]{PageMainScreen, PageNewRegistration, PageSelectedPatient});
public void setMeVisible(string PanelName) {
var c = panels.FirstOrDefault(panel=>panel.Name == PanelName);
if(c != null) {
c.Visible = true;
if(currentShown != null) currentShown.Visible = false;
currentShown = c;
}
}
NOTE: Don't try complicating your UI unnecessarily. I want to mean that you should place all your panels on the same container (such as your form). That's the way we do, that way you can use the first approach, no need to loop, easy to maintain. You should also consider the Dock and the methods like BringToFront() and SendToBack() to show/hide the view.

Equivalent to jQuery closest() in ASP.NET Web Forms

Im trying to figure out a way to build a somewhat clever version of the jQuery closest method in C#. Im using a generic method to find the desired control and then index the control chain
public static T FindControlRecursive<T>(Control control, string controlID, out List<Control> controlChain) where T : Control
{
controlChain = new List<Control>();
// Find the control.
if (control != null)
{
Control foundControl = control.FindControl(controlID);
if (foundControl != null)
{
// Add the control to the list
controlChain.Add(foundControl);
// Return the Control
return foundControl as T;
}
// Continue the search
foreach (Control c in control.Controls)
{
foundControl = FindControlRecursive<T>(c, controlID);
// Add the control to the list
controlChain.Add(foundControl);
if (foundControl != null)
{
// Return the Control
return foundControl as T;
}
}
}
return null;
}
To Call it
List<Control> controlChain;
var myControl = FindControls.FindControlRecursive<TextBox>(form, "theTextboxId"), out controlChain);
To find the closest element of id or type
// Reverse the list so we search from the "myControl" and "up"
controlChain.Reverse();
// To find by id
var closestById = controlChain.Where(x => x.ID.Equals("desiredControlId")).FirstOrDefault();
// To find by type
var closestByType = controlChain.Where(x => x.GetType().Equals(typeof(RadioButton))).FirstOrDefault();
Would this be a good approach or are there any other cool solutions out there creating this?
Whats your consideration?
Thanks!
Maybe something like this
public static IEnumerable<Control> GetControlHierarchy(Control parent, string controlID)
{
foreach (Control ctrl in parent.Controls)
{
if (ctrl.ID == controlID)
yield return ctrl;
else
{
var result = GetControlHierarchy(ctrl, controlID);
if (result != null)
yield return ctrl;
}
yield return null;
}
}

How to find HtmlForm element?

I am trying to find HtmlForm element using code below and add several new controls. Unfortunately this is not working, the HtmlForm element is never found.
foreach (Control c in Controls)
{
if (c is HtmlForm)
{
c.Controls.AddAt(0, manager);
c.Controls.AddAt(1, updatePanel);
}
}
How about using Page.Form to get the HtmlForm?
Do you have runat="server" specified in the form control? Otherwise; your code behind won't be aware of it.
Also, you might need some recursion here if the Control has nested controls; so something like this:
public static Control FindControlRecursive(Control containerCtl, string controlIdToFind)
{
var foundCtl = containerCtl.FindControl(controlIdToFind);
if (foundCtl != null && controlIdToFind == foundCtl.ID)
{
return foundCtl;
}
foreach (Control ctl in containerCtl.Controls)
{
foundCtl = FindControlRecursive(ctl, controlIdToFind);
if (foundCtl != null && controlIdToFind == foundCtl.ID)
{
return foundCtl;
}
}
return null;
}

A Better way? Finding ASP.NET controls, finding their id

I have a method that finds all the controls, iterates through them, determines if they are a textbox,drop down list, etc.. retrieves their ID name, and depending on the ID name it will set a boolean statement (thus I would know if that section of the form is complete, and will email to a certain group of people) unfortunetly this is done with too many if statements and was wondering if I could get some help making this more manageable
protected void getEmailGroup()
{
Control[] allControls = FlattenHierachy(Page);
foreach (Control control in allControls)
{
if (control.ID != null)
{
if (control is TextBox)
{
TextBox txt = control as TextBox;
if (txt.Text != "")
{
if (control.ID.StartsWith("GenInfo_"))
{
GenInfo = true;
}
if (control.ID.StartsWith("EmpInfo_"))
{
EmpInfo = true;
}
}
}
if (control is DropDownList)
{
DropDownList lb = control as DropDownList;
if (lb.SelectedIndex != -1)
{
if (control.ID.StartsWith("GenInfo_"))
{
GenInfo = true;
}
if (control.ID.StartsWith("EmpInfo_"))
{
EmpInfo = true;
}
}
}
}
}
}
Why not just use the Control.FindControl(string) method?
private void Button1_Click(object sender, EventArgs MyEventArgs)
{
// Find control on page.
Control myControl1 = FindControl("TextBox2");
if(myControl1!=null)
{
// Get control's parent.
Control myControl2 = myControl1.Parent;
Response.Write("Parent of the text box is : " + myControl2.ID);
}
else
{
Response.Write("Control not found");
}
}
from: https://learn.microsoft.com/en-us/dotnet/api/system.web.ui.control.findcontrol
It is hard to understand the logic behind your code, but I'm sure it can be written easier. For example you can do something like this:
DropDownBox box = FlattenHierachy(Page)
.Where(c => c is DropDownList)
.Cast<DropDownList>()
.Where(d => d.SelectedIndex != -1)
.FirstOrDefault();
if (box != null)
{
if (box.ID.StartsWith("GenInfo_"))
{
GenInfo = true;
}
if (box.ID.StartsWith("EmpInfo_"))
{
EmpInfo = true;
}
}
Obviously you can make this generic if you extract the lambda expression from the seconde Where call. So you could reuse it for different types. That's the solution which is as close to your code as possible, but I guess it would be a better idea to use a recursive method traversing the page and giving that method your predicates as lambda expressions.
Cleaned up you code a little to only include each check once.
protected void getEmailGroup()
{
Control[] allControls = FlattenHierachy(Page);
foreach (Control control in allControls)
{
if (control.ID != null &&
((control is TextBox && ((TextBox)control).Text = "" )
|| (control is DropDownList && ((DropDownList)control).SelectedIndex != -1 ))
{
if (control.ID.StartsWith("GenInfo_"))
GenInfo = true;
if (control.ID.StartsWith("EmpInfo_"))
EmpInfo = true;
}
}
}
}
Instead of using the Lambda expression I have created a method that handles the control for me, and depending on the name of the control, it sets that section to be true
public bool setGroup(Control ctrl)
{
isAControl = false;
//set a section to true, so it will pull the html
if (ctrl.ID.StartsWith("GenInfo_"))
{
GenInfo = true;
lstControls.Add(ctrl.ID.Replace("GenInfo_", ""));
isAControl = true;
return isAControl;
}
here is a small snippet of my code I only want to check for certain controls(to speed things up) and I go through each control as each control has a different way to get the value (textbox would use .text where dropdownlist would use .selectedValue)
if(control is TextBox || control is DropDownList || control is RadioButton || control is RadioButtonList
|| control is CheckBox || control is CheckBoxList)
{
if (control is TextBox)
{
TextBox txt = control as TextBox;
if (txt.Text != "" && txt.Text != "YYYY/MM/DD")
{
setGroup(control);
if (isAControl)
{
string controlNoGroup = lstControls.Last();
strHtml = strHtml.Replace("#" + (controlNoGroup.ToString()) + "#", txt.Text);
}
}
}

How to Identify Postback event in Page_Load

We have some legacy code that needs to identify in the Page_Load which event caused the postback.
At the moment this is implemented by checking the Request data like this...
if (Request.Form["__EVENTTARGET"] != null
&& (Request.Form["__EVENTTARGET"].IndexOf("BaseGrid") > -1 // BaseGrid event ( e.g. sort)
|| Request.Form["btnSave"] != null // Save button
This is pretty ugly and breaks if someone renames a control. Is there a better way of doing this?
Rewriting each page so that it does not need to check this in Page_Load is not an option at the moment.
This should get you the control that caused the postback:
public static Control GetPostBackControl(Page page)
{
Control control = null;
string ctrlname = page.Request.Params.Get("__EVENTTARGET");
if (ctrlname != null && ctrlname != string.Empty)
{
control = page.FindControl(ctrlname);
}
else
{
foreach (string ctl in page.Request.Form)
{
Control c = page.FindControl(ctl);
if (c is System.Web.UI.WebControls.Button)
{
control = c;
break;
}
}
}
return control;
}
Read more about this on this page:
http://ryanfarley.com/blog/archive/2005/03/11/1886.aspx
In addition to the above code, if control is of type ImageButton then add the below code,
if (control == null)
{ for (int i = 0; i < page.Request.Form.Count; i++)
{
if ((page.Request.Form.Keys[i].EndsWith(".x")) || (page.Request.Form.Keys[i].EndsWith(".y")))
{ control = page.FindControl(page.Request.Form.Keys[i].Substring(0, page.Request.Form.Keys[i].Length - 2)); break;
}
}
}
I am just posting the entire code (which includes the image button / additional control check that causes postback). Thanks Espo.
public Control GetPostBackControl(Page page)
{
Control control = null;
string ctrlname = page.Request.Params.Get("__EVENTTARGET");
if ((ctrlname != null) & ctrlname != string.Empty)
{
control = page.FindControl(ctrlname);
}
else
{
foreach (string ctl in page.Request.Form)
{
Control c = page.FindControl(ctl);
if (c is System.Web.UI.WebControls.Button)
{ control = c; break; }
}
}
// handle the ImageButton postbacks
if (control == null)
{ for (int i = 0; i < page.Request.Form.Count; i++)
{
if ((page.Request.Form.Keys[i].EndsWith(".x")) || (page.Request.Form.Keys[i].EndsWith(".y")))
{ control = page.FindControl(page.Request.Form.Keys[i].Substring(0, page.Request.Form.Keys[i].Length - 2)); break;
}
}
}
return control;
}

Categories

Resources