Accessing server-side control by its ID property in ASP.net - asp.net

On my default.aspx page I have a bunch of divs with an ID and runat="server":
<div id="serverOne" runat="server"></div>
<div id="serverTwo" runat="server"></div>
<!--etc...-->
In my code behind I've declared a multidimensional array (or grid) with 2 values -- the first being an IP address and the second the server name.
Dim servers = {{"10.0.0.0", "serverOne"}, {"10.0.0.1", "serverTwo"}}
My question is, is there a way where I can target my divs from my code behind using a value from the array?
For i As Integer = 0 To 1
'This is what I want it to do:
servers(i, 1).InnerHtml = "<span>Testing " & servers(i, 1) & "</span>"
Next

You can do this using the FindControl method on the page. However, out of the box FindControl looks only at the first level of children, and does not go into the childrens' children. In order to handle this you need to use a helper method that allows FindControl to recursively search through the control hierarchy to find the one you want. Add this method to your code behind, or some shared class that multiple pages can access:
Protected Function FindControlRecursive(control As Control, id As String)
If (control.ID = id) Then
Return control
End If
For Each ctl In control.Controls
Dim foundControl = FindControlRecursive(ctl, id)
If (foundControl IsNot Nothing) Then
Return foundControl
End If
Next
Return Nothing
End Function
Once you have that, it's pretty easy to find your <div> just by using the string ID property.
For i As Integer = 0 To 1
Dim div = CType(FindControlRecursive(Me, servers(i, 1)), HtmlGenericControl)
div.InnerHtml = "<span>Testing " & servers(i, 1) & "</span>"
Next
Reference: http://forums.asp.net/t/1107107.aspx/1

Related

Render mark up in one asp repeater item

Ok just thinking of how to put the question right.
I have a datatable which returns some feedback details. The datatable contains feedbacks of two companies. The feedbacks of the datatable distinguished based on an indicator in the each data row.
The repeater is sorted on date order (newest first). If the companies are A and B, company A's feedback will be always listed in the top, since they are the newest. I have rendered an image and some wording to mention if the listed feedback is company B feedback.
Public Function RenderTitle(ByVal objItem As Object) As String
Select Case objItem
Case 1
Return String.Empty
Case 0
Return "Feedback below obtained whilst a member of our sister company " & "<img src=""../img/logo.png"" />"
Case Else
Return String.Empty
End Select
End Function
The title is rendered if the feedback belongs to company B.
Problem: I dont want the title to be rendered in all the items of the company B. I want it to render just in the first item (feedback) that belongs to Company B. How can I achieve this?
Formatting the contents of a DataList or Repeater control based upon the data can be accomplished by using two techniques.
The first technique is to create an event handler for the ItemDataBound event, which fires as each record in the data source is bound to a new DataListItem or RepeaterItem. In the ItemDataBound event handler, the current item's data can be examined, and then formatting can be applied to the contents of the template or, for DataListItems, to the entire item itself.
Alternatively, custom formatting can be realized through formatting functions. A formatting function is a method that can be invoked from the DataList or Repeater's templates that returns the HTML to emit in its place. Often, the HTML returned by a formatting function is determined by the values being bound to the current item. These values can be passed into the formatting function, either as scalar values or by passing-in the entire object being bound to the item (such as the ProductsRow instance).
http://msdn.microsoft.com/en-us/library/bb510136.aspx
Can you try something like this... (Ugly Code & Not Tested)
HTML
...
<asp:HiddenField ID="hdnIsTitleRenderd" runat="server"/>
...
CODE
Page_Load()
If Not IsPostBack
hdnIsTitleRenderd.Value = "False"
End If
End Sub
Public Function RenderTitle(ByVal objItem As Object) As String
Select Case objItem
Case 1
Return String.Empty
Case 0
If Convert.ToBoolean(hdnIsTitleRenderd.Value) = False
hdnIsTitleRenderd.Value = "True"
Return "Feedback below obtained whilst a member of our sister company " & "<img src=""../img/logo.png"" />"
Else
Return String.Empty
End If
Case Else
Return String.Empty
End Select
End Function

Confused about using ViewState with dynamically added usercontrol

On my webpage I am loading multiple instances of a usercontrol, sometimes the usercontrol is laoded within itself. I need to save a bunch of properties for the round trip of a post back but i am confused on how to save those properties to ViewState and set them again to the repeater items within the usercontrol.
Can anyone help me in this situation, I have read the MSDN on Viewstate but I am not understanding it quite well for some reason
This is how I load the parent user controls (child controls are loaded the same way with the same user control)
Protected Sub Load_Controls(ByVal list As List(Of BSEvaluationGroup.category), ByVal gid As Integer, ByVal pid As Integer, ByVal fid As Integer)
Dim item As BSEvaluationGroup.category
For Each item In list
Dim ctl As PerformanceEvaluationSubcontractorControl = CType(Page.LoadControl("PerformanceEvaluationSubcontractorControl.ascx"), PerformanceEvaluationSubcontractorControl)
ctl.categoryid = item.catid
ctl.categoryname = item.catname
ctl.projectid = pid
ctl.folderid = fid
ctl.groupid = gid
ctl.parentid = item.parid
ctl.clist = item.categories
ctl.plist = item.points
ctl.parentpage = Me
ctl.EnableViewState = "true"
If (Not subcon Is Nothing AndAlso Not subcon.points Is Nothing) Then
ctl.epnts = subcon.points
End If
AddHandler ctl.BubbleCalculate, AddressOf Me.PostRating
Select Case gid
Case 1
Me.officephld.Controls.Add(ctl)
Dim ohrule As HtmlGenericControl = New HtmlGenericControl("hr")
ohrule.Style.Add("width", "100%")
ohrule.Style.Add("background-color", "Silver")
ohrule.Style.Add("size", "1px")
ohrule.Style.Add("border-width", "0")
ohrule.Style.Add("padding-top", "1px")
ohrule.Style.Add("float", "left")
Me.officephld.Controls.Add(ohrule)
Case 2
Me.sitephld.Controls.Add(ctl)
Dim shrule As HtmlGenericControl = New HtmlGenericControl("hr")
shrule.Style.Add("width", "100%")
shrule.Style.Add("background-color", "Silver")
shrule.Style.Add("size", "1px")
shrule.Style.Add("border-width", "0")
shrule.Style.Add("padding-top", "1px")
shrule.Style.Add("float", "left")
Me.sitephld.Controls.Add(shrule)
End Select
Next
End Sub
Accessing view-state is simple such as ViewState("PropertyName"). The View State bag is specific to a control instance so you can use same property name within multiple control types and instances.
Only important thing here is that ASp.NET run-time has to match view-state bags to control instances and for that it uses ID property (which is unique within the parent naming container). So its important that you assign unique IDs to your dynamic user control instances ( and maintain same control tree hierarchy and ids on postback - essentially it means that execute the same code on postback and don't use random ids). So your code should be something like
...
Dim n As Integer
n = 1
For Each item In list
Dim ctl As PerformanceEvaluationSubcontractorControl = CType(Page.LoadControl("PerformanceEvaluationSubcontractorControl.ascx"), PerformanceEvaluationSubcontractorControl)
ctl.ID = "MyCtl" & n.ToString()
ctl.categoryid = item.catid
....
It was a control ID issue, I removed it instead of adding an ID

dynamically set control ID

i have few texboxt and dropdownlist, which their id would be something like "txtName1, txtName2, txtName3..." and "ddlAction1, ddlAction2, ddlAction3...."! I would to to dynamically set the textboxt and dropdownlist id into something like this:
for i as integer = 0 to 6
a = txtName+i.text
b = ddlAction+i.SelectedValue
next i
Need help from you guys to do this! thanks....
The key is FindControl, which looks up a control by its expected ID:
For i As Integer = 0 To 5
Dim txt As TextBox = TryCast(Me.Page.FindControl("txtName" & i.ToString()), TextBox)
Dim ddl As DropDownList = TryCast(Me.Page.FindControl("ddlAction" & i.ToString()), DropDownList)
If txt IsNot Nothing AndAlso ddl IsNot Nothing Then
Dim a As String = txt.Text
Dim b As String = ddl.SelectedValue
End If
Next
It will return null/nothing if a control with that ID isn't found.
Note that FindControl will only search the given control's (or Page's) immediate children, not the entire control tree. To search recursively, you need to use your own FindControl method.
Private Function FindControlRecursive(ByVal control As Control, ByVal id As String) As Control
Dim returnControl As Control = control.FindControl(id)
If returnControl Is Nothing Then
For Each child As Control In control.Controls
returnControl = child.FindControlRecursive(id)
If returnControl IsNot Nothing AndAlso returnControl.ID = id Then
Return returnControl
End If
Next
End If
Return returnControl
End Function
.Net requires you to resolve your variable names at compile time, rather than runtime like your code is trying to do. This is a good thing, as it prevents you from making certain kinds of errors. But it does mean you'll need to look at an alternative approach for this particular problem.
One option is a FindControl -based method. But odds are the controls you care about are grouped together on the page. If they aren't already, put them in a common container control, like a panel. Then you can do something like this (requires System.Linq):
For Each t As TextBox In MyContainer.Controls.OfType(Of TextBox)()
a = t.Text
Next t
For Each d As DropDownList In MyContainer.Controls.OfType(Of DropDownList)()
b = d.SelectedValue
Next d
Also, I hope you're really doing something other than assignment inside your loop. Otherwise, most of the work is for nothing as you will exit the loop having simply assigned the value from the last iteration to your variable.
Finally, it seems like these controls might work in pairs. To me, that's a situation that calls out for you to implement a user control.
I'm not a webforms expert, but I believe the page stores a reference to each control present in the page.
You can think of webforms like an n-ary tree... each control has a parent and can have 0 to many children. So, if these are static controls you should just be able to grab a reference to their parent and iterate over that... with no need for the children's ids.
Also, you can query for children based on their id... something like myControl["myID1"] so you can concat the number with the string and get the control that way.
Lastly, if these are purely dynamic controls, i.e. you don't know how many there are, just store references to them in an ordered collection and iterate over them that way.
EDIT:
Here we go:
WebControl myControl;
myControl.Controls.Add(someControlReference);
Then, to grab a control by ID:
WebControl someControl = myControl.FindControl("someControlID1");
From there you can do like:
string a = someControl.Text

How to enable/disable web elements of a parent aspx page from the child ascx page?

I have an aspx page with three web controls: one to control the List Users page, one to control the Edit Users page, and one to control the Add User page. I have discovered a method for accessing these elements, but it seems to be limited. Here is what I have done:
Protected Sub editUser(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewEditEventArgs)
'set selected user from gridview.
Dim index As Integer = e.NewEditIndex
Dim userId As Integer = gvListUsers.DataKeys(index).Value
Session.Item("SelectedUserId") = userId
'show edit page, hide list and add page.
With Page.Form.Controls(1)
.Controls(getControlId("loadAddUser")).Visible = False
.Controls(getControlId("loadEditUser")).Visible = True
.Controls(getControlId("loadListUser")).Visible = False
End With
End Sub
The getControlId function looks like this:
Public Function getControlId(ByVal control As String) As Integer
Dim enumer As System.Collections.IEnumerator = Page.Form.Controls.Item(1).Controls.GetEnumerator
Dim i As Integer
For i = 0 To (Page.Form.Controls.Item(1).Controls.Count - 1)
If Page.Form.Controls(1).Controls.Item(i).ID = control Then
Return i
End If
Next
Return Nothing
End Function
This works in most cases. However, I am unable to access the "enabled" attribute of these web controls. Why is this, and how might I access that attribute?
Thanks :)
You could raise events from your UserControls which you subscribe to in the parent ASPX page. In the parent page event action you could enable/disable your controls,
Here's an example of events in UserControls: http://codebetter.com/blogs/brendan.tompkins/archive/2004/10/06/Easily-Raise-Events-From-ASP.NET-ASCX-User-Controls.aspx
Something else to think about: are you getting any benefit from moving this code into usercontrols? Would any of the individual controls be re-usable on their own? Creating tightly coupled controls that rely on each other being present doesn't give you much re-usability of the individual controls.
Visible is a property provided by the System.Web.UI.Control class, which is why you can access it directly. Enabled is not a property on this class, so you need to map the control object to a variable of the type of your custom control class if you want to access the Enabled property.
Dim myControl As TheAddUserControl
With Page.Form.Controls(1)
myControl = .Controls(getControlId("loadAddUser"))
myControl.Enabled = False
.Controls(getControlId("loadEditUser")).Visible = True
.Controls(getControlId("loadListUser")).Visible = False
End With
To expose an Enabled property in you user control:
Public Property Enabled As Boolean
Get
Return (Child1.Enabled And Child2.Enabled And Child3.Enabled)
End Get
Set(ByVal value As Boolean)
Child1.Enabled = value
Child2.Enabled = value
Child3.Enabled = value
End Set
End Poperty

Find controls on sharepoint master page

I'm trying to loop through all the controls on a sharepoint page, for the purposes of testing i just want to output the control ID
this is the code i'm using
Public Shared Sub SubstituteValues3(ByVal CurrentPage As Page, ByRef s As StringBuilder)
'Page()
'- MasterPage
'- HtmlForm
'- ContentPlaceHolder
'- The TextBoxes, etc.
For Each ctlMaster As Control In CurrentPage.Controls
If TypeOf ctlMaster Is MasterPage Then
HttpContext.Current.Response.Output.Write("Master Page <br/>")
For Each ctlForm As Control In ctlMaster.Controls
If TypeOf ctlForm Is HtmlForm Then
HttpContext.Current.Response.Output.Write("HTML Form <br/>")
For Each ctlContent As Control In ctlForm.Controls
If TypeOf ctlContent Is ContentPlaceHolder Then
HttpContext.Current.Response.Output.Write("Content Placeholder <br/>")
For Each ctlChild As Control In ctlContent.Controls
HttpContext.Current.Response.Output.Write(ctlChild.ID.ToString & "<br />")
Next
End If
Next
End If
Next
End If
Next
HttpContext.Current.Response.Output.Write("--------------")
HttpContext.Current.Response.End()
however it's not getting past the 'MasterPage' output.
I would expect to see the names of all the controls i have inside my content placeholder but i find it all a bit confusing.
Start with Page.Master.Controls
From there what you have should basically work
For Each ctlForm As Control In Page.Master.Controls
If TypeOf ctlForm Is HtmlForm Then
HttpContext.Current.Response.Output.Write("HTML Form <br/>")
For Each ctlContent As Control In ctlForm.Controls
If TypeOf ctlContent Is ContentPlaceHolder Then
HttpContext.Current.Response.Output.Write("Content Placeholder <br/>")
For Each ctlChild As Control In ctlContent.Controls
HttpContext.Current.Response.Output.Write(ctlChild.ID.ToString & "<br />")
Next
End If
Next
End If
Next
A MasterPage isn't a control of the current page, it's a property of it, in Page.MasterPage
i found this piece of code which seems list the controls I need, i think it's more of a hack though.
For i = 0 To CurrentPage.Request.Form.AllKeys.Length - 1
If CurrentPage.Request.Form.GetKey(i).Contains("ctl00$PlaceHolderMain$") Then
Dim key As String = CurrentPage.Request.Form.GetKey(i).Substring(22)
Dim keyText As String = String.Format("[{0}]", key)
HttpContext.Current.Response.Output.Write(keyText & "<br/>")
'Text.Replace(keyText, CurrentPage.Request.Form("ctl00$PlaceHolderMain$" & key))
End If
Next
you can do this simply with recursion, not efficent, but it is simple... try this method:
public void getControls(Control input)
{
foreach (Control c in input.Controls)
{
Response.Write(c.GetType().ToString() + " - " + c.ID + "<br />");
getControls(c);
}
}
And call it like this:
getControls(Page);
That will cycle trough all controls on your page and output the type - ID of them and print it out to the top of the page... you could also use the code to construct a list or whatever you want to do.

Resources