0

I have a Menu/MultiView control setup inside a FormView and I am trying to set the first menu item as selected on Page_Load. I'm getting a NullReferenceException error on the line where I'm trying to set Selected = True.

Markup:

<asp:FormView ID="FormView1" runat="server" CellPadding="4" DataKeyNames="ProjectID" DataSourceID="ProjectDetailsSQL" ForeColor="#333333">
    <ItemTemplate>
        <h1><asp:Label ID="Label1" runat="server" Text='<%# Eval("ProjectID") %>' /> - <asp:Label ID="Label2" runat="server" Text='<%# Bind("ProjectName") %>' /></h1>
        <asp:Menu ID="mnuProject" runat="server" CssClass="MenuStyle" Orientation="Horizontal" OnMenuItemClick="mnuProject_MenuItemClick" EnableViewState="false">
            <staticselectedstyle backcolor="Gray" borderstyle="Solid" bordercolor="Black" borderwidth="1"/>
            <Items>
                <asp:MenuItem Text="General" Value="0" />
                <asp:MenuItem Text="Scope" Value="1" />
                <asp:MenuItem Text="CAD" Value="2" />
                <asp:MenuItem Text="PM" Value="3" />  
                <asp:MenuItem Text="Submittals" Value="4" />
                <asp:MenuItem Text="ChangeOrders" Value="5" />
                <asp:MenuItem Text="Timecards" Value="6" />
                <asp:MenuItem Text="Docs" Value="7" />
                <asp:MenuItem Text="Log" Value="8" />
                <asp:MenuItem Text="Financials" Value="9" />
            </Items>
        </asp:Menu>
        <asp:MultiView ID=MultiView1></asp:MultiView>
    </ItemTemplate>
</asp:FormView>

CodeBehind:

protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                Menu mnuProject = (Menu)FormView1.FindControl("mnuProject");
                mnuProject.Items[0].Selected = true; <----- Exception thrown here
            }
        }

I have also tried Menu mnuProject = (Menu)FormView1.Row.FindControl("mnuProject"); and mnuProject is still coming back as null. I can only guess that I'm not giving it the right location for FindControl. Any help correcting my syntax would be greatly appreciated.

Jeff Cox
  • 333
  • 4
  • 14
  • I am not sure about using dupehammer here, so before voting for duplicate have a look at [this](http://stackoverflow.com/q/6105634/728795) - i suspect this is the same problem and therefore the same solution should work – Andrei Sep 30 '15 at 17:23
  • It's been a long time since I've done webform dev. EnableViewState is disabled, does that affect programmatically setting properties? – Doug Dawson Sep 30 '15 at 17:26
  • @DougDawson, no, but this is not the problem - control itself cannot be found – Andrei Sep 30 '15 at 17:27
  • Andrei, the link you listed makes it seem like the problem was the FindControl() was fired in Page_Load instead of Page_PreRender or Page_PreRenderComplete and was getting fired before the control was created. I tried moving the Page_Load code into both a Page_PreRender event and a Page_PreRenderComplete event and the same exception gets thrown. – Jeff Cox Sep 30 '15 at 18:12
  • @JeffCox, nope, that's the root of the problem as i see it. The problem in the link says that you should only run `FindControl` after FormView is data bound, because data binding is what actually creates controls inside the FormView – Andrei Oct 01 '15 at 09:45

1 Answers1

1

The findControl method is NOT recursive.

That means it will attempt to find your contol in the item you request, but NOT its children. In other words, it is looking for mnuProject within FormView1 but NOT any of FormView1's child controls.

This is a generic implementation I used to resolve it. You need to use recursion for this to behave the way you want... lucky for you I had this project open :-)

public static class pageHelpers
{
            public static System.Web.UI.Control FindControlRecursive(System.Web.UI.Control root, string id)
            {
                if (root.ID == id)
                {
                    return root;
                }

                foreach (System.Web.UI.Control c in root.Controls)
                {
                    System.Web.UI.Control t = pageHelpers.FindControlRecursive(c, id);
                    if (t != null)
                    {
                        return t;
                    }
                }
                return null;
            }
}

And let's refactor your page code, so we can determine if that resolved this issue.

  Menu mnuProject = (Menu)pageHelpers.FindControlRecursive(FormView1,"mnuProject");
  // lets test to see if our FindControlRecursive method worked before doing anything else
  if(mnuProject == null) {throw new Exception("FindControlRecursive failed!");}

  mnuProject.Items[0].Selected = true; <----- Exception thrown here
HBomb
  • 1,117
  • 6
  • 9
  • How is `mnuProject` not a direct child of the FormView here? It is specified on the top level of ItemTemplate, which makes it exactly a child control of the FormView – Andrei Sep 30 '15 at 17:44
  • Its not possible to tell that for certain, as the asp markup is not complete. There are missing end tags. You might be right, but that was why I modified the test code to throw a specific exception should findControlRecursive fail. If that exception is hit, then the problem is something else. – HBomb Sep 30 '15 at 17:55
  • Made the suggested code changes and I'm getting the FindControlRecursive failed exception. – Jeff Cox Sep 30 '15 at 18:14
  • Well unfortunately your markup is still incomplete. Your menu control is referencing a page method that is not defined in the code behind, and your formview is referencing a data source that is not defined in the page behind. That being said, I would try removing the cast to Menu and see if you still get a null value. Something like var mnuProject = pageHelpers.FindControlRecursive(FormView1,"mnuProject"); – HBomb Sep 30 '15 at 22:57