Init and InitComplete in user web controls

I am attempting to create a user control similar to the examples given in the MSDN library for web parts, where a user can select a mode and change to it. I do have the functionality working, except for one unrelated thing.

It says to do something like:

void Page_Init(object sender, EventArgs e)
{
Page.InitComplete += new EventHandler(InitComplete);
}

void InitComplete(object sender, EventArgs e)
{
// Do stuff here to fill the dropdownlist
}

However, InitComplete is never called. How do I know?

it says that when I try to reference the member field that stores the WebPartManager instance from PreRender, it is a null reference. It works however if I instead use Init or Load, instead of InitComplete.

Firstly, why?

Secondly, why does it specifically recommend InitComplete? What’s wrong with me using Load or Init? Right now I’m using Init just to make it work.

Here’s some code for reference:

— WebPartModes.ascx —

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="WebPartModes.ascx.cs"
    Inherits="WebPartModes" %>
<div>
    <table border="0" cellpadding="0" cellspacing="0" style="width: 100%; height: 100%">
        <tr>
            <td style="width: 25%">
                <asp:Label ID="WebPartModesLabel" runat="server" AssociatedControlID="WebPartModesDropDownList"
                    Text="Mode:"></asp:Label></td>
            <td style="width: 75%">
                <asp:DropDownList ID="WebPartModesDropDownList" runat="server" ValidationGroup="WebPartModes" OnSelectedIndexChanged="WebPartModesDropDownList_SelectedIndexChanged">
                </asp:DropDownList>
                <asp:RequiredFieldValidator ID="WebPartModesRequiredFieldValidator" runat="server"
                    ControlToValidate="WebPartModesDropDownList" Display="Dynamic" ErrorMessage="You must select a mode"
                    SetFocusOnError="True" ValidationGroup="WebPartModes"></asp:RequiredFieldValidator></td>
        </tr>
        <tr>
            <td colspan="2" align="right">
                <asp:Button ID="WebPartModesButton" runat="server" Text="Change" ValidationGroup="WebPartModes" /></td>
        </tr>
    </table>
</div>

— WebPartModes.ascx.cs —

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 WebPartModes : System.Web.UI.UserControl
{

    WebPartManager _webPartManager;

    void Page_Init(object sender, EventArgs e)
    {
        _webPartManager = WebPartManager.GetCurrentWebPartManager(Page);
        foreach (WebPartDisplayMode mode in _webPartManager.SupportedDisplayModes)
        {
            if (mode.IsEnabled(_webPartManager))
            {
                WebPartModesDropDownList.Items.Add(new ListItem(mode.Name, mode.Name));
            }
        }
    }

    protected void Page_PreRender(Object sender, EventArgs e)
    {
            WebPartModesDropDownList.SelectedIndex = WebPartModesDropDownList.Items.IndexOf(WebPartModesDropDownList.Items.FindByText(_webPartManager.DisplayMode.Name));
    }
    protected void WebPartModesDropDownList_SelectedIndexChanged(object sender, EventArgs e)
    {
        WebPartDisplayMode mode = _webPartManager.SupportedDisplayModes[WebPartModesDropDownList.SelectedValue];
        if (mode != null)
        {
            _webPartManager.DisplayMode = mode;
        }
    }
}

I am fairly certain InitComplete fires. Though a much better way to be sure that it does fire in this case is to set a breakpoint in the init complete function and step through it to see what is going wrong.

Odd though that Init and Load work, but not InitComplete, then. But I will certainly debug after I work out a few other issues. These web parts come along quite nicely once you start. :smiley:

Anyway, is there anything wrong with running it in Init or Load? Again right now I"m running it in Init, and it seems to not be causing any problems. Out of curiosity though I’ll debug with InitComplete just to see the issue.

Thanks for the help. :slight_smile:

Alright, no luck. I did debugging, and it does execute Page_Init, but it does not continue to InitComplete. Here is the code behind file again, with the attempted use of InitComplete.

By the way, I wasn’t sure if these needed to be public, especially InitComplete, since the Page.InitComplete event needs to access it.

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 WebPartModes : System.Web.UI.UserControl
{

    WebPartManager _webPartManager;

    public void Page_Init(Object sender, EventArgs e)
    {

        Page.InitComplete += new EventHandler(this.InitComplete);
    }

    public void InitComplete(Object sender, EventArgs e)
    {
        _webPartManager = WebPartManager.GetCurrentWebPartManager(Page);
        foreach (WebPartDisplayMode mode in _webPartManager.SupportedDisplayModes)
        {
            if (mode.IsEnabled(_webPartManager))
            {
                WebPartModesDropDownList.Items.Add(new ListItem(mode.Name, mode.Name));
            }
        }
    }

    protected void Page_PreRender(Object sender, EventArgs e)
    {
            WebPartModesDropDownList.SelectedIndex = WebPartModesDropDownList.Items.IndexOf(WebPartModesDropDownList.Items.FindByText(_webPartManager.DisplayMode.Name));
    }
    protected void WebPartModesDropDownList_SelectedIndexChanged(object sender, EventArgs e)
    {
        WebPartDisplayMode mode = _webPartManager.SupportedDisplayModes[WebPartModesDropDownList.SelectedValue];
        if (mode != null)
        {
            _webPartManager.DisplayMode = mode;
        }
    }
}

It dies in PreRender, since _webPartManager has not been instantiated, since apparently InitComplete was never executed. :confused:

Thanks again.

Hi!

This may be a bit late as the discussion happened 2 years ago, but I recently started using Web Parts. I had the same problem while working on a tutorial from the web.

In my case, the tutorial had teh following code:

protected void Page_Load(object sender, EventArgs e)
        {

            Page.InitComplete += new EventHandler(Page_InitComplete);
        }

Looks familiar, right?

Well, the problem is that it looks like the Load event is fired AFTER the Init event, so the InitComplete method is never called.

There are 2 easy solutions:

  1. Put the line:
Page.InitComplete += new EventHandler(Page_InitComplete);

in the Page_Init method

  1. Put the code getting the display modes from the WebPartManager in Page_Load (or you can add a Page_LoadComplete event handler and put it there)

This bug bothered me for a whole day, so I’m just happy that I figured it out and I didn’t have to smash any company equipment. :smiley: