views:

2374

answers:

3

I have a CompositeControl that contains a DropDownList.

I have set the AutoPostBack property of the DropDownList to true.

On the page, I have:

<asp:UpdatePanel ID="UpdatePanel" runat="server">
    <ContentTemplate>
        <MyControl:Control ID="CustomControl" runat="server" />
    </ContentTemplate>
</asp:UpdatePanel>

I've also tried setting ChildrenAsTriggers="true" and UpdateMode="Always," but neither resolved the problem.

The problem is that the UpdatePanel is not intercepting the CompositeControl's DropDownList's post back. (A full POST is being performed when the DropDownList is changed)

How can I get the UpdatePanel to handle the postback?

Thanks!

Edit -- Requested Info

Country and states are both DropDownLists in the CompositeControl.

country.SelectedIndexChanged += new EventHandler(country_SelectedIndexChanged);

protected void country_SelectedIndexChanged(Object sender, EventArgs e)
{
    states.DataSource = XXX;
    states.DataBind();
}
+2  A: 

Ok so this may not be the best answer, but I think the problem you're having it that the UpdatePanel just can't see the child control's event. Good news is, it's easy to fix. Say you have a control (CatchMyEvent, which by the way is a crazy clever name) and it has a DropDownList on it. Now you want the parent page to see the SelectedIndexChanged event fire on that list and update a label to match the SelectedItem.Text. As it is, the parent can't really do that. So let's change that:

public partial class CatchMyEvent : System.Web.UI.UserControl
{
    public delegate void ChangedIndex(object sender, EventArgs e);
    public event ChangedIndex SelectedIndexChanged;

    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);
        dropDownListThrow.SelectedIndexChanged += new EventHandler(dropDownListThrow_SelectedIndexChanged);
        labelOutput.Text = "no";
    }

    public void dropDownListThrow_SelectedIndexChanged(object sender, EventArgs e)
    {
        labelOutput.Text = ((DropDownList)sender).SelectedItem.Text;
        if(SelectedIndexChanged != null)
        {
            SelectedIndexChanged(sender, e);
        }
    }
}

Basically all I did is have the control capture the DropDownList's SelectedIndexChanged event and fired it so that any parent page or control could see it. Essentially all I've done is passed it on. Now on the parent page, it's really easy to capture.

You just need to add an UpdatePanel with a trigger that holds:

asp:AsyncPostBackTrigger ControlID="catchMyEventMain" EventName="SelectedIndexChanged"

(Can't past full asp code it seems or I'm doing something wrong) and of course add this to the code behind for the parent page:

protected override void OnInit(EventArgs e)
{
    base.OnInit(e);
    catchMyEventMain.SelectedIndexChanged += dropDownListThrow_SelectedIndexChanged;
}

public void dropDownListThrow_SelectedIndexChanged(object sender, EventArgs e)
{

    labelSelectedValue.Text = ((DropDownList)sender).SelectedItem.Text;
}

Where the label is the before mentioned label. And then let the magic happen.

Also two notes:

1) Don't be an idiot like I was when testing this and forget to set the AutoPostBack property on the DropDownList to true.

2) Make sure the label is in the UpdatePanel's ContentTemplate.

Hope this helps.

Programmin Tool
I added a handler to the constructor for my CompositeControl, but in the hanlder, SelectedIndexChanged alway == null, so it never gets fired.
AlexWalker
That means the parent control isn't hooked into that event. Not sure you know, but just in case The if not null check is a way to make sure something is handling that event somewhere.catchMyEventMain.SelectedIndexChanged += dropDownListThrow_SelectedIndexChanged;On the parent page.
Programmin Tool
Basically makes sure your parent page is handling the SelectedIndexChanged event you created on the child control.
Programmin Tool
A: 

I made the following at the end of the BuildControlHierarchy:

        ...
        if (DesignMode || Page == null) return;

        var sm = ScriptManager.GetCurrent(Page);
        if (sm == null)
        {
            throw new MissingFieldException("The ScriptManager is needed on the page!");
        }
        sm.RegisterAsyncPostBackControl(<control which initiates async postback>);
A: 

Just make sure every control in your whole hierarchy has an ID set.

See this question.

tomfanning