Master Pages and public Properties

Why can I see a Public Property on a MasterPage (from my content page) but nothing else is visible?

Can someone show me how to get to a control on a Master Page, using either an Interface or Delegate?  I've heard that this works, but don't understand how.

My goal is to be able to call a public method that the control exposes, thus updating the control on the MasterPage from the content page.

IMPORTANT:  I am not talking about the asp controls that come with .NET but a "Web User Control" found under Add New Item.

I know that Master Pages are not really intended to support logic, but layout.  Still I want to know if this is possible.
LVL 5
Tom KnowltonWeb developerAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

SteveH_UKCommented:
The controls are not exposed from the Master property of the page unless it is cast to the appropriate type.  Then it depends on whether and if the control is exposed.

You can use this code to get a control from a master page, but you must pay attention to control hierarchy on the master page (C# code):

((MyUserControl)(this.Master.FindControl("controlID")).SomeControlMethod();

If you want the control to be directly accessible, you need to make sure that the control declaration is public or internal in either the Master.aspx.cs/vb or Master.aspx.designer.cs/vb files.  Then you can use this code:

((MyMasterPageType)(this.Master)).controlID.SomeControlMethod();
0
totaraCommented:
Do you want to access this control from
- the Master page
- or the Child page that uses the master

Where is this control located ? In the Master or in the (Child)Page
0
Tom KnowltonWeb developerAuthor Commented:
The control is on the Master Page.
0
Cloud Class® Course: CompTIA Healthcare IT Tech

This course will help prep you to earn the CompTIA Healthcare IT Technician certification showing that you have the knowledge and skills needed to succeed in installing, managing, and troubleshooting IT systems in medical and clinical settings.

Tom KnowltonWeb developerAuthor Commented:
What about using delegates or interaces to get to the control on the Master Page from the child page?
0
SteveH_UKCommented:
Neither delegates nor interfaces are appropriate in this case.  You can pull back the control as a Control object simply by using this.Master.FindControl("controlID").  If you need access to a method you should cast it to the correct type, as described above.

An alternative (but WRONG!) approach is to use reflection:

Control c = this.Master.FindControl("controlId");
c.GetType().GetMethod("methodName").Invoke(c, null);

There is no good reason not to do as I originally indicated.  Are you having trouble with that?  If so, perhaps you can post some code and we can help out.
0
Tom KnowltonWeb developerAuthor Commented:
I take issue with using FindControl.

Everywhere I read everyone says "use FindControl".  I don't buy into that.  It seems like a hack.  Why can't we use OOP to get to the Control?

0
totaraCommented:
FindControl is okay but is NOT recursive, you need to write your own recursive method.

The code presented by SteeveH in the beginning looks allright to me.

0
SteveH_UKCommented:
You use OOP to get to the control if the control is declared and you cast the Master page to the correct type, otherwise your code just thinks it is a generic Master page type.  The reason is that the Master property of the Page type is a property that returns a MasterPage object, but your particular master page is a derived type, for example:

class YourMasterPage : MasterPage
{
  public Button buttonOnMasterPage;
}

class YourPage : Page
{
   void Page_Load(object sender, EventArgs e)
  {
      YourMasterPage theMaster = (YourMasterPage) this.Master;
      thisMaster.buttonMasterPage.Text = "Some Text";
  }
}

This is exactly what I was saying in the second option of the first response to your question.

Neither case is a "hack", and both are object-oriented.  You should use the first method (FindControl) when the control may not exist (created dynamically), when it is not exposed with an accessible class member (for example it is private) or when you do not know the actual type of the master page.  If these do not apply then you should be able to cast the object to the appropriate type.  This isn't a hack, actually it is correct OOP coding.
0
Tom KnowltonWeb developerAuthor Commented:
SteveH:

Okay.

What I still don't understand is why I cannot provide public methods in the Master Page class and access them via Master in the content page.
0
SteveH_UKCommented:
You can, but only after you have cast the Master property to the correct type, for example:

YourMasterPage theMaster = (YourMasterPage) this.Master;
theMaster.MasterMethod("a test");

This code won't work because the compiler doesn't know the method exists (as it is not defined in the MasterPage class):

MasterPage theMaster = this.Master;
theMaster.MasterMethod("a test");
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Tom KnowltonWeb developerAuthor Commented:
:::: smacks self on the head::::

It works!!!!!!!!!!!!!!!

Why couldn't anyone have told me this in the first place???????

Everyone has been telling me that I have to use FindControl.  But this code works just fine!


Have I been asking the question in the wrong way, using the wrong words?


This was all I ever wanted -- to be able to "get to" a control on the Master Page and update it.



//MASTER PAGE ASPX:
 
<%@ Master Language="C#" AutoEventWireup="true" CodeFile="MasterPage.master.cs" Inherits="MasterPage" %>
<%@ Register Src="ControlOnMasterPage.ascx" TagName="ControlOnMasterPage" TagPrefix="uc1" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <uc1:ControlOnMasterPage ID="ControlOnMasterPage1" runat="server" />
        <br />
        <br />
        <br />
        <br />
        <asp:contentplaceholder id="ContentPlaceHolder1" runat="server">
        </asp:contentplaceholder>
    </div>
    </form>
</body>
</html>
 
 
//MASTER PAGE CODE BEHIND:
 
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
 
public partial class MasterPage : System.Web.UI.MasterPage
{
    protected void Page_Load(object sender, EventArgs e)
    {
 
    }
 
    public void SetControlText(string newtext)
    {
        this.ControlOnMasterPage1.SetText(newtext);
    }
}
 
 
//CHILD PAGE ASPX:
 
<%@ Page Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true" CodeFile="ChildPage.aspx.cs" Inherits="ChildPage" Title="Untitled Page" %>
<%@ MasterType VirtualPath="~/MasterPage.master" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
    <br />
    <br />
    <br />
    <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
    <asp:Button ID="Button1" runat="server" Text="Button" />
</asp:Content>
 
 
 
//CHILD PAGE CODE BEHIND:
 
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
 
public partial class ChildPage : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
 
    }
    protected void Button1_Click(object sender, EventArgs e)
    {
        MasterPage theMaster = this.Master;
        theMaster.SetControlText("a test");
    }
}

Open in new window

0
Tom KnowltonWeb developerAuthor Commented:
Excellent job, Steven
0
Tom KnowltonWeb developerAuthor Commented:
I tried changing the name of the class to something else

public partial class MasterPage : System.Web.UI.MasterPage

changed to:

public partial class MyMasterPage : System.Web.UI.MasterPage


And I kept getting an error:

c:\Users\tom\Desktop\AJAXEnabledWebSite2\MasterPage.master.cs(912305,33): error CS0115: 'ASP.masterpage_master.FrameworkInitialize()': no suitable method found to override
0
Tom KnowltonWeb developerAuthor Commented:
Oh, I get it ... I would also have to change the Inherits="MasterPage" to Inherits="MyMasterPage"
0
SteveH_UKCommented:
Sorry I haven't been able to respond before now.  Thanks for the points :)

>Why couldn't anyone have told me this in the first place???????
>Everyone has been telling me that I have to use FindControl.  But this code works just fine!
>Have I been asking the question in the wrong way, using the wrong words?
>This was all I ever wanted -- to be able to "get to" a control on the Master Page and update it.

It is all to easy for us to presume the question is harder than it is.  This may be part of the reason we answered the way we did.  Casting objects to an appropriate type is often automatic in my thinking, at least, and so I was possibly assuming that either you didn't have access to the code in the Master Page, or that the control was not directly accessible, such as a control within a template of a templated control (like the Repeater control).

Often the controls are not directly accessible because they are marked as "protected" so they are not accessible to a Page, however they can be accessed by using a 'cast' with the FindControl method.

Finally, please note that I did offer a 'cast' solution in my first post (the second option), and that your original question was for a public method on a control, rather than a public method on the Master Page.

Anyway, I hope you have found the discussion useful.  The following page may also prove informative: http://msdn2.microsoft.com/en-us/library/c8y19k6h.aspx.
0
Tom KnowltonWeb developerAuthor Commented:
Thanks for your comments and the link, Steve.


Tom
0
SteveH_UKCommented:
You're welcome :)
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
ASP.NET

From novice to tech pro — start learning today.