Page view counter

Masterpages and the INamingContainer

Rate It (1)

Last post 03-03-2006 12:32 PM by BrianOConnell. 12 replies.

Sort Posts:

  • Masterpages and the INamingContainer

    06-01-2005, 2:23 PM
    • Loading...
    • BrianOConnell
    • Joined on 08-04-2002, 12:24 PM
    • Dublin, Ireland
    • Posts 825
    • Points 4,395
    I've asked before but I'm wondering what is the thinking is in renaming controls in a masterpage. This works against designers and their css files that reference specific ids of controls. Is there a way to stop this happening? I can't help thinking it would be better if it did not rename controls and just warned developer in the ide if they have 2 controls of the same id.
    Brian O'Connell (MCAD) - http://www.systemdotweb.com
  • Re: Masterpages and the INamingContainer

    06-08-2005, 6:03 PM
    • Loading...
    • BrianOConnell
    • Joined on 08-04-2002, 12:24 PM
    • Dublin, Ireland
    • Posts 825
    • Points 4,395
    Wow no matter what I say nobody gives two you know whats about this. Amazing after the fantastic job the asp.net team has done with support for standards and accesability that nobody seems to care that designers will be jumping through hoops to get their # css identifiers to work. It's seems so straight-forward to hand over the responsibility to the developer to ensure no controls will have the same id or at least to give them the option to turn off the functionality of the inaming container. Maybe theres a simple way around this but I would have thought someone might have replied to this post if there was. Dissappointingly nobody cares. Oh well.
    Brian O'Connell (MCAD) - http://www.systemdotweb.com
  • Re: Masterpages and the INamingContainer

    07-03-2005, 9:49 AM
    • Loading...
    • dekale
    • Joined on 11-01-2004, 12:26 PM
    • Posts 47
    • Points 235
    Brian,

    I've having the same problems with the INamingContainer and the MasterPage. I'm generating my interface from the database and so I can give my controls an unique id. The problem here is that the MasterPage changes every unique id's to an even more uniqueness. So now I can't find my controls anymore (using the Request.Form), because they're name has changed.

    The MasterPage shouldn't be implemented with the INamingContainer interface in the first way. The ContentPlaceholder control that is used in the MasterPage does ALREADY implement the INamingContainer interface. So there is no need for MasterPage to implement it.

    Kale

  • Re: Masterpages and the INamingContainer

    07-04-2005, 4:22 AM
    • Loading...
    • Dave Sussman
    • Joined on 06-17-2002, 11:53 AM
    • UK
    • Posts 1,960
    • Points 13,947
    • TrustedFriends-MVPs
    Actually this is more of an issue than you realise. Some of the controls themselves have odd behaviour. For example, why does the CheckBox get wrapped in a span when you add a CssClass? Why, when customising the layout of a Login control using the LayoutTemplate does your content in the template get wrapped within a table (a 1 cell table)? These are things that really drive me crazy.

    For the renaming of controls your best bet is to use class names rather than IDs.

    Dave
  • Re: Masterpages and the INamingContainer

    07-04-2005, 6:32 AM
    • Loading...
    • dekale
    • Joined on 11-01-2004, 12:26 PM
    • Posts 47
    • Points 235
    Are these issues known to Microsoft, or should we make a suggestion in the MSDN Product Feedback Center
  • Re: Masterpages and the INamingContainer

    07-04-2005, 12:15 PM
    • Loading...
    • Dave Sussman
    • Joined on 06-17-2002, 11:53 AM
    • UK
    • Posts 1,960
    • Points 13,947
    • TrustedFriends-MVPs
    You're right, I've now added them as suggestions in the feedback centre.
  • Re: Masterpages and the INamingContainer

    07-04-2005, 12:43 PM
    • Loading...
    • dekale
    • Joined on 11-01-2004, 12:26 PM
    • Posts 47
    • Points 235
    Well, and I've got now a nasty solution for my INaming-problem. Because I know my Controls must have a unique id, I can search for a control ending with that id. My own version of the Page's FindControl function looks like this.


            public System.Web.UI.Control FindControlEndingWith(string id)
            {
                System.Web.UI.Control control = null;

                foreach (string key in this.Request.Form)
                {
                    if (key.EndsWith(id) == true)
                    {
                        if (control != null) throw new System.Data.DuplicateNameException(
                            "Duplicate control has been found. Both the controls " +
                            control.ID + " and " + key + " end with " + id + ".");

                        control = this.FindControl(key);
                    }
                }
                return control;
            }


    p.s. Can you post the link to your suggestion in the feedback center, so I can track it.

  • Re: Masterpages and the INamingContainer

    07-04-2005, 1:19 PM
    • Loading...
    • Dave Sussman
    • Joined on 06-17-2002, 11:53 AM
    • UK
    • Posts 1,960
    • Points 13,947
    • TrustedFriends-MVPs
  • Re: Masterpages and the INamingContainer

    07-04-2005, 2:14 PM
    • Loading...
    • BrianOConnell
    • Joined on 08-04-2002, 12:24 PM
    • Dublin, Ireland
    • Posts 825
    • Points 4,395
    I made a suggestion a while ago about the master pages and they say they will take it into consideration. As you say for now tell your designers to use class names. They are bound to see how good asp.net is with that kind of restriction. Anyway good to see I'm not the only one.
    Brian O'Connell (MCAD) - http://www.systemdotweb.com
  • Re: Masterpages and the INamingContainer

    07-20-2005, 8:30 PM
    • Loading...
    • dekale
    • Joined on 11-01-2004, 12:26 PM
    • Posts 47
    • Points 235
    I'd like to come back on the code I posted earlier in this Thread. The code isn't good, so I baked some other code and I'd like to share it with you all.

    First of all, what is wrong with the code above. Well the function searches for Control ID's using the Page's Request.Form object. The Form however, does NOT contain ID's of control's that have their enabled property set to false (or disabled attribute set at html side), while these Controls could still be of importance.

    After I while I came to the conclusion (but please correct me if I'm wrong) that there isn't a 10 line solution to this problem. You'll have to go through the complete Control tree by hand. And by hand means: Building you're own copy of the tree and search it recursively. So behold the ControlTree class.

    /// <summary>Builds up a tree of <see cref="Control"/> objects and enables specific searches through the tree.</summary>
    class ControlTree
    {
        private ControlCollection _collection;
        private List<ControlTree> _childNodes = new List<ControlTree>();

        /// <summary>Constructor</summary>
        /// <param name="collection">The <see cref="System.Web.UI.ControlCollection"/> object to start the tree with</param>
        public ControlTree(ControlCollection collection)
        {
            this._collection = collection;

            foreach (Control control in collection)
            {
                if (control != null && control.Controls != null)
                    this._childNodes.Add(new ControlTree(control.Controls));
            }
        }

        /// <summary>Finding and returning the controls who's ID ends with the id parameter.</summary>
        /// <param name="id">The *id to search for.</param>
        /// <returns>The matching control or null (Nothing in VB) when no control is found.</returns>
        public Control FindControlEndingWith(string id)
        {
            Control match = null; // The reference to the matching control

            foreach (Control control in _collection)
            {
                if (control != null && control.ID != null && control.ID.EndsWith(id))
                {
                    if (match != null) throw new Exception("Duplicate control found.");
                    match = control; // We've got a match
                }
            }

            foreach (ControlTree node in this._childNodes)
            {
                Control control = node.FindControlEndingWith(id);

                if (control != null)
                {
                    if (match != null) throw new Exception("Duplicate control found.");
                    match = control; // We've got a match
                }
            }
            return match;
        }
    }

    You initialize the tree with the Page's Controls object (a ControlCollection). The old function that I wrote for my BasePage now looks like this:

    private ControlTree _controlTree;
    public Control FindControlEndingWith(string id)
    {
        if (this._controlTree == null) this._controlTree = new ControlTree(this.Controls);
        return this._controlTree.FindControlEndingWith(id);
    }

    A strong warning here, because I assume here that that Page's control tree will never change after calling FindControlEndingWith(id) for the first time. When it does, you will have to recreated the ControlTree on every call (and that can cause performance to drop), or find a smart way to indicate if the tree has changed.

  • Re: Masterpages and the INamingContainer

    02-13-2006, 5:55 PM
    This has been a real pain for me too. I got around the problem in serverside code by having my page objects implement specific interfaces providing accessor methods for the controls they needed to share with other pages. Takes a bit more work, but it seems like the cleanest way to do it - looking controls up by id seems kind of fragile in principle anyway.

    One place I can't get around it without ugliness however is clientside code; javascript's document.getElementById() is rendered useless by INaming and there's not much I can do about it without writing some kind of messy custom find functions. I'm nervous about coding anything that assumes things about the naming container's id formats because I have no control over how it does it, but writing something that takes into account possibly variable naming conventions makes for some real slow code.

    Bottom line is it's crazy frustrating to not be able to either turn off this naming stuff, use a non-INaming container in place of ContentPlaceHolder, or even have ANY kind of access to the unique string the container is applying to its controls. If anyone knows a way of doing any of these things, please yell out.
  • Re: Masterpages and the INamingContainer

    02-14-2006, 3:01 PM
    • Loading...
    • dekale
    • Joined on 11-01-2004, 12:26 PM
    • Posts 47
    • Points 235
    For getting the controls using document.getElementById() on the client, you should use the ClientID property of a control, rather than it's ID property. This will solve most of the problems when trying to get the html element the control represents.

    public class MyControl : TextBox
    {
        protected override void OnPreRender(EventArgs e)
        {
            this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(),
                "MyControl",
                @"function SetMyColorOnClick() {
                    var e = document.getElementById('" + this.ClientID + @"').style.backgroundColor = '#FF0000';
                }", true);

            this.Attributes.Add("onclick", "SetMyColorOnClick()");

            base.OnPreRender(e);
        }
    }

    does this help?
  • Re: Masterpages and the INamingContainer

    03-03-2006, 12:32 PM
    • Loading...
    • BrianOConnell
    • Joined on 08-04-2002, 12:24 PM
    • Dublin, Ireland
    • Posts 825
    • Points 4,395
    The problem with this is that you have to have javascript in your html page. I prefer to use external javascript files and it's an easy way of adhering to standards.
    My simple solution to INaming is to create my templates using non server controls. i.e. divs. Originally I thought it would be nice to create one masterpage with for example a 3 column layout using panels but then referencing the id of the control in css is useless (the way most standards cimpliant templates are created) and then using code I could easily change this to a 2 column or 1 column layout. Using divs without runat=server I can correctly reference their id in css and there are workarounds to control the appearance in code.
    My new pet hate is inline styles in controls. A Gridview with no formatting will render with a style attribute regardless. Top of my wishlist is for all controls to have a property which allows me to turn off style so that my css files will control formatting completely. Again you can workaround this by creating custom controls that overide the output of the style attribute.
    Brian O'Connell (MCAD) - http://www.systemdotweb.com
Page 1 of 1 (13 items)