Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win


Convert ASPX pagename to Page Control

Posted on 2011-03-12
Medium Priority
Last Modified: 2012-05-11
With previous assistance from Experts Exchange members I've written a recursive routine to loop through all the controls on an ASP.NET 1.1 page to assign images and tooltips from a database.
    ' Recursively set the ImageUrl and ToolTip for Images and Image Buttons
    ' together with the ToolTip for Mandatory fields. This is a modified version 
    ' that gets the tooltip from the ToolTips table and the ImageURL from the
    ' ControlNames table
    Public Sub SetIconImages(ByVal Page As Control, ByVal WebPageName As String)

        For Each ctrl As Control In Page.Controls

            If TypeOf ctrl Is ImageButton Then
                CType(ctrl, ImageButton).ImageUrl = GetSpecificImageURL(ctrl.ID.ToString)
                CType(ctrl, ImageButton).ToolTip = GetSpecificToolTip(WebPageName, ctrl.ID.ToString)
            ElseIf TypeOf ctrl Is Image Then
                If Left(ctrl.ID.ToString, 4) = "tti_" Then
                    CType(ctrl, Image).ImageUrl = GetSpecificImageURL(ctrl.ID.ToString)
                    CType(ctrl, Image).ToolTip = GetSpecificToolTip(WebPageName, ctrl.ID.ToString)
                End If
                If System.Configuration.ConfigurationSettings.AppSettings(ctrl.ID.ToString) Is Nothing Then
                    CType(ctrl, Image).AlternateText = "Assign an Image in the Web.config file to this key: " + ctrl.ID.ToString
                    CType(ctrl, Image).ImageUrl = System.Configuration.ConfigurationSettings.AppSettings(ctrl.ID.ToString)
                End If
            ElseIf TypeOf ctrl Is Label Then
                If CType(ctrl, Label).Text = "M" Then
                    CType(ctrl, Label).ForeColor = Drawing.Color.Silver
                    CType(ctrl, Label).ToolTip = "Mandatory Field: This will turn red if invalid or incomplete data is detected"
                ElseIf CType(ctrl, Label).Text = "9" Or CType(ctrl, Label).Text = "D" Or CType(ctrl, Label).TemplateSourceDirectory = "V" Then
                    CType(ctrl, Label).ForeColor = Drawing.Color.Silver
                    CType(ctrl, Label).ToolTip = "Optional Field: This will turn red if invalid or incomplete data is detected"
                End If
                If ctrl.Controls.Count > 0 Then
                    SetIconImages(ctrl, WebPageName)
                End If
            End If
    End Sub

Open in new window

. This is called from each page when it is first loaded and works fine.  
With clsGenericFunctions.GetInstance
                .SetIconImages(Me, .GetCurrentPageName)
            End With

Open in new window

I want to be able to do the same thing from a generic page, i.e. to let an administrative user see all the controls on a selected page and add image urls and/or tooltips. The problem I can't resolve is how to convert the page name I have in a listbox, e.g. MCR.aspx, back into a Page Control to pass to this routine instead of passing the varialble 'Me'. I know how to get the ID and ClientID to get the actual page name (MCR.aspx) but not how to do this in reverse.

I display a list of all the Page names, then when I select one I want call a routine that looks something like this:
Public Sub GetControlNames(ByVal Page As Control, ByVal WebPageName As String, ByVal ArrayCtrl As ArrayList)

        For Each ctrl As Control In Page.Controls

Open in new window

. The Page variable needs to be the equivalent of {asp.MCR_aspx} as a Control but I can't get this conversion to work.

I'm sure it's not too difficult for someone with more experience but any assistance will be greatly appreciated.  
Question by:pstanford
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 3

Assisted Solution

_kiwi_ earned 1200 total points
ID: 35121388

The method you are using is not a method I would recommend. Getting a recursive loop go through all your controls to have their properties modified is to me the wrong way, I would prefer modifying my layout in order to have my controls load their properties from the database (i.e. by subclassing the controls I use to have them load their content, or by using "<%# GetResourceByName(...) %>", a databinding handler that will get the data out of the database.

I see a few mistakes in your loop, you take control ID to go through the database:
- what if two controls have the same ID in the page ? (i.e. you load two UserControls that both have a "Title" label, but they mean different things)
- what would you do if the control has no ID attribute ?

If you want to have the ID of that specific control, use UniqueID property, and since they are already strings, please don't use ".ToString", because if not set you will raise an error (null reference exception) for calling ToString on a null string. But then again, what would you do if the order of the controls in the page changed ? UniqueId would change, and your database would not be consistent, and tooltips would be wrong. Same with databound controls, UniqueId changes for each item and each line, this would not work.

For your question, if you still want to go down that path, it is pretty complicated to load a page as a control from another page, what I would recommend is to call the initial url (MCR.aspx) and add it a paramater that would change the behavior of your SetIconImages to have the names saved in the database instead of read from the database.

But then again, imagine you have databound controls depending on the data, if you use templating (ITemplate), nothing would guarantee you that your recursive loop would find every control in the page, since these controls are instanciated with the data.

My recommendation is for you to add to your BasePage and default UserControl, or to make available through a static property, a function GetResource() that will take the current page URL (something like HttpRequest.Current.FilePath.Substring(HttpRequest.Current.ApplicationPath)), a data type (url, title, tooltip), a name, and the parameters you will use in that name (the values {0} {1} you will use in your string.format). Another option could be a ressourcemanager (http://msdn.microsoft.com/fr-fr/library/1ztca10y(v=VS.71).aspx#Y473) which is the default .Net 1.1 way to do this.

e.g. (coded in the browser, so not tested):

Public Sub GetResource(ByVal Type As String, ByVal ResourceID As String, ParamArray args As Object())
  Dim PageUrl As String = HttpRequest.Current.FilePath.Substring(HttpRequest.Current.ApplicationPath))
  ' Load data from database (select ResourceValue = value from resources where page = PageUrl and type = Type and resourceID = ResourceID), into string ResourceValue, using SqlConnection and SqlParameter
  GetResource = string.Format(CultureInfo.CurrentUICulture, ResourceValue, args)
End Sub

In your page, you would then have
<asp:imagebutton runat="server" imageUrl='<%# GetResource("Url", "MyImageButton") %>' tooltip='<%# GetResource("Tooltip", "MyImageButton") %>'/>

Some points of attention:
- ResourceIDs must be unique in a page
- warning about " (double quotes) and ' (single quote) in tag attributes with <%#, you should use ' outside and " inside otherwise you will have an invalid tag error thrown
- make sure you have at least one page level databind event (at onload if no postback sent) to enable <%# to work properly

Hope this helps,

Author Comment

ID: 35123655
Thanks for the very detailed response but this is way more complex than I need it to be. I'm simply trying to automate the management of images and tooltips. I have two existing tables and a link table. The first table (ControlNames) contains names of controls but by controls I mean standard controls like buttons, image buttons and images, no user controls.
 ControlNames Table DesignThe second table (WebPageNames) contains names of the .aspx pages within the application.
 WebPageNames Table DesignThe third table (ToolTips) contains references to the WebPageNames and ControlNames tables, i.e. the same control can be used on multiple pages with the same image (for Image Buttons and Images) but a different ToolTip, depending on the context.
 ToolTips Table DesignI can, using a routine similar to the one contained in the first post, iterate through the controls on any given page and get the names of those controls, look up both the image and the tooltip and apply them dynamically at runtime. If I build that functionality into each of the pages I can also push any control names back into the database and also into the link table.

I was just hoping to be able to do this in one generic function rather than having to repeat the code, so while I'm sure your solution is architecturally way more elegant than mine, this is an internal application with a known number of users and I just want the administrator to control the tooltips that are applied rather than hardcode them into the application.

I've manually created the entries in the ControlNames and WebPageNames tables but it seems like there must be a simpler way to do this through a generic routine that I call from each page rather than coding on each page. The following images show samples of the data in the ControlNames and ToolTips tables.
 ControlNames Sample Data ToolTips Sample Data
This application will ultimately be replaced by a new Silverlight application so I don't want to waste too much time on it and only an Administrator would load a page and request a list of Controls from a different page so there wouldn't be a performance issue. I'd just like to now how to do this using a generic routine.

I do appreciate your response but don't think it addresses the issue as simply as I'd like it to do.

Assisted Solution

_kiwi_ earned 1200 total points
ID: 35125756

I recommend then having your "SetIconImages" function changed to check for a "process" argument in the URL, and of this parameter is present, instead of calling GetSpecific... You shall call a SaveSpecific... which would simply call the insert statement in your db if this control does not already exist.

You can then use your dropdown to populate an hidden iframe with the target page, with the "process" parameter set.

Finally, to have your administrator modify the contents, simply develop a page that will display an editable datatable from the names found in the db, and you'll be set.

Make sure your method is called late (prerender or render), and check that your controls ids are not null.

Hope this helps,

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.


Accepted Solution

pstanford earned 0 total points
ID: 35159987
Each of the answers above has been useful from a learning perspective but I've not implemented any of this as part of the solution. While not elegant, I've simply implemented a procedure which I call, rather than the user, to generate the list of controls I want and populate those into the database. I then generate a script that can be run against the user's database to populate the appropriate tables. These controls do not change unless I make specific changes to a page in which case I'll regenerate and resynchronise the controls in the database.

The reason for the recursive loop is to address the fact that controls are contained in different sections of a page, for example, in tables that contain tables with named rows so I can collapse/expand them. Again this may not be the most elegant way to do this but it works and there isn't much money in the project, certainly not enough to make wholesale changes to the architecture at this point.

Having said all that, I'm happy to split the points as the quality of feedback and responsiveness was excellent.

Expert Comment

ID: 35163154
Thanks about that.

In the end, whatever the choice you are making, it is yours and it has to answer your specific contraints, after all you are the one coding.

Hava a Nice day.

Author Closing Comment

ID: 35187445
The techniques were useful but none of them were implemented in order to address the problem

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Sometimes in DotNetNuke module development you want to swap controls within the same module definition.  In doing this DNN (somewhat annoyingly) swaps the Skin and Container definitions to the default admin selections.  To get around this you need t…
It was really hard time for me to get the understanding of Delegates in C#. I went through many websites and articles but I found them very clumsy. After going through those sites, I noted down the points in a easy way so here I am sharing that unde…
In this video, Percona Solutions Engineer Barrett Chambers discusses some of the basic syntax differences between MySQL and MongoDB. To learn more check out our webinar on MongoDB administration for MySQL DBA: https://www.percona.com/resources/we…
In response to a need for security and privacy, and to continue fostering an environment members can turn to for support, solutions, and education, Experts Exchange has created anonymous question capabilities. This new feature is available to our Pr…
Suggested Courses

597 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question