Address Content Page Controls from Master

R

Rbrt

There is a lot of good material related to using Master Pages for formatting
controls and putting common design elements on multiple pages.

I have VB.NET code that is common to all of my pages for doing things like
rendering controls, making database connections, instantiating custom
classes, etc...

I am trying to figure out how to put code in the Master Page that will
address controls on the content pages which use that master - say for example
to set the text and tooltip of a button or label.

Is this possible? If so, how?

I tried defining a BasePage class and inheriting from that, but am having
trouble with the declarations for the events in the inheriting page.

Thanks!
 
B

Bryan Porter

Rbrt,

One technicue is to have your code in the master page find references to the
controls in the content pages by using Page.FindControl. Trouble is,
FindControl isn't recursive, so if you have a content page with a panel that
houses a TextBox named "myTextBox", FindControl("myTextBox") won't find it
(FindControl only returns matching controls in the Page's direct Controls
collection - it won't search the children of any Controls it sees.)

You could write your own, recursive FindControl method like this:

private Control FindControlRecursively(Control c, string controlId)
{
if (c.ID == controlId)
return c;

foreach (Control child in c.Controls)
{
Control result = FindControlRecursively(child, controlId);

if (result != null)
return result;
}

return null;
}

ASP.NET does not contain a recursive FindControl method since it can have an
adverse impact on performance if used too much or on pages with tons of
nested controls, so be aware of that. You'll have to cast the returned
Control to the correct type in order to operate on it.

--
Regards,

Bryan Porter
http://www.bryanporter.com/

"What A Horrible Night To Have A Curse!" - S. Belmont
 
R

Rbrt

Thanks Bryan!

Bryan Porter said:
Rbrt,

One technicue is to have your code in the master page find references to the
controls in the content pages by using Page.FindControl. Trouble is,
FindControl isn't recursive, so if you have a content page with a panel that
houses a TextBox named "myTextBox", FindControl("myTextBox") won't find it
(FindControl only returns matching controls in the Page's direct Controls
collection - it won't search the children of any Controls it sees.)

You could write your own, recursive FindControl method like this:

private Control FindControlRecursively(Control c, string controlId)
{
if (c.ID == controlId)
return c;

foreach (Control child in c.Controls)
{
Control result = FindControlRecursively(child, controlId);

if (result != null)
return result;
}

return null;
}

ASP.NET does not contain a recursive FindControl method since it can have an
adverse impact on performance if used too much or on pages with tons of
nested controls, so be aware of that. You'll have to cast the returned
Control to the correct type in order to operate on it.

--
Regards,

Bryan Porter
http://www.bryanporter.com/

"What A Horrible Night To Have A Curse!" - S. Belmont
 
B

bruce barker

this is probably a poor design. the master page is just a control on the
actual page.

a better approach is your original approach of a base page. any problems
coding for events you had with a basepage you will have with a master.

you should spend the time to understand delegates, events and overrides
to overcome your original coding errors.

-- bruce (sqlwork.com)
 
B

Bryan Porter

I wholeheartedly agree with Bruce, the base page is definitely the way to
go, but if you're looking for a quick fix FindControl will do it.

Mind you, there are caveats, big ones, but it'll get the job (poorly) done.

--
Regards,

Bryan Porter
http://www.bryanporter.com/

"What A Horrible Night To Have A Curse!" - S. Belmont
 
R

Rbrt

Yeah I am trying to do that but for some reason I keep getting a blue
squiggly that talks about using WithEvents when I put a Handles statement in
an Event Handler of the child (inheriting) page.

This used to be simple in 1.1 !
 
R

Rbrt

I got base page to work, but what I am finding is that if I put code in the
BasePage I still have to loop through every control on the inheriting page,
find the "ContentPlaceHolder" controls, and then loop through all the
controls in each "ContentPlaceHolder" in order to set the properties of each
control (button, label, etc.) on the page.
 
S

Scott Roberts

I got base page to work, but what I am finding is that if I put code in the
BasePage I still have to loop through every control on the inheriting
page,
find the "ContentPlaceHolder" controls, and then loop through all the
controls in each "ContentPlaceHolder" in order to set the properties of
each
control (button, label, etc.) on the page.

Why? Are you try to auto-magically data-bind controls based on name or
something?

Since a base page and/or master page doesn't know anything about derived
pages, there is no way to code directly to those pages. It really doesn't
even make sense to attempt that. Typically, you would makes calls from the
derived page to methods on the base class (or master page) such as:

MyBasePageMethod_BindControl(TextBox1, DataSource1);

If you're wanting to automate further and have the base class auto-discover
"TextBox1" then you'll have to use recursive looping as discussed earlier.
We do that, but we do it at the control level instead of page level (i.e. we
have a custom FormView that matches controls to object properties based on
name).
 
R

Rbrt

I am building an application that is multilingual. The text elements are
stored in a database table and when the page loads, I get all the text stuff
for the controls on that page (text, tooltip, messages for validators,
etc...) in the current user's language and then I go through each control and
set the text property, tooltip property, what have you. To do this I have
created a special interface class that does the heavy lifting - reading the
database, getting the properties, etc...

I'd be interested to hear more about that custom FormView if you've the time.
 
S

Scott Roberts

Gotcha.

Our FormView is far too customized to be useful to anyone else. We've got
all kinds of crap in there. But the part you might be interested in is a
very simple recursive routine that binds controls to our custom business
object. Here it is:

protected virtual void GenerateFieldBindings(Control containerControl)
{
// Loop through all controls and attempt to wire-up fields by matching
// the control ID to the field name.
foreach (Control c in containerControl.Controls)
{
if (c.ID != null)
foreach (IField f in BoundObject.Fields)
if (c.ID.ToUpper() == f.FieldName.ToUpper())
AddFieldBinding(c, f);

GenerateFieldBindings(c);
}
}


So, if you replace "BoundObject.Fields" with
"YourCollectionOfObjectsObtainedFromYourDB" you're pretty much set. Just
pass in a reference to your "page" to get the ball rolling (e.g. in the
Page_Load just call GenerateFieldBindings(this)).
 
R

Rbrt

Thank you!

Scott Roberts said:
Gotcha.

Our FormView is far too customized to be useful to anyone else. We've got
all kinds of crap in there. But the part you might be interested in is a
very simple recursive routine that binds controls to our custom business
object. Here it is:

protected virtual void GenerateFieldBindings(Control containerControl)
{
// Loop through all controls and attempt to wire-up fields by matching
// the control ID to the field name.
foreach (Control c in containerControl.Controls)
{
if (c.ID != null)
foreach (IField f in BoundObject.Fields)
if (c.ID.ToUpper() == f.FieldName.ToUpper())
AddFieldBinding(c, f);

GenerateFieldBindings(c);
}
}


So, if you replace "BoundObject.Fields" with
"YourCollectionOfObjectsObtainedFromYourDB" you're pretty much set. Just
pass in a reference to your "page" to get the ball rolling (e.g. in the
Page_Load just call GenerateFieldBindings(this)).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,149
Members
46,695
Latest member
StanleyDri

Latest Threads

Top