Showing posts with label repeater. Show all posts
Showing posts with label repeater. Show all posts

Wednesday, March 21, 2012

CascadingDropDown inside of a repeater

I'm trying to create a CascadingDropDown inside of a repeater, and just can't seem to figure it out.

I have a dropdownlist created within a repeater that should cascade from another dropdownlist that is also generated within the repeater.

The problem that arises from this situation is when I go to set the CascadingDropDownProperties, I get this error:

Object reference not set to an instance of an object.

Description:Anunhandled exception occurred during the execution of the current webrequest. Please review the stack trace for more information about theerror and where it originated in the code.

Exception Details:System.NullReferenceException: Object reference not set to an instance of an object.

Source Error:

An unhandled exception was generated during the execution of thecurrent web request. Information regarding the origin and location ofthe exception can be identified using the exception stack trace below.


Stack Trace:

[NullReferenceException: Object reference not set to an instance of an object.]
AtlasControlToolkit.CascadingDropDown.OnPreRender(EventArgs e) in d:\Depot\Atlas\agility\AtlasControls\MAIN\Src\ControlLibrary\CascadingDropDown\CascadingDropDownExtender.cs:60
System.Web.UI.Control.PreRenderRecursiveInternal() +77
System.Web.UI.Control.PreRenderRecursiveInternal() +161
System.Web.UI.Control.PreRenderRecursiveInternal() +161
System.Web.UI.Control.PreRenderRecursiveInternal() +161
System.Web.UI.Control.PreRenderRecursiveInternal() +161
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1360


When I go through with the debugger it doesn't break on any line of code, so I'm not totally sure what's causing the error. I have figured out that the problem happens when I set the TargetControlID, because If I comment out that line then It'll work. I'm guessing I'll have the same problems with the ParentControlID, also.

cddpNew.TargetControlID = DropDownListControl.ClientID

Has anyone gotten a Cascading drop down to work within a repeater?Since that didn't work I decided to take another approach, which is to put the CascadingDropDown inside the repeater. This had it's own problem.

When trying to get the control from within the repeater during the function that handles the databinding event for the repeater I get the error:

Value of type 'System.Web.UI.Control cannot be converted to 'AtlasControlToolkit.CascadingDropDownProperties'.

So, no luck this direction either.Sad
In the first case, you probably need to access the CascadingDropDown through the Repeater container (recall that the Repeater creates many instances of its contents). The way ASP.NET implements repeaters is a little tricky, but I think you should be able to accomplish what you want with the right code.

CascadingDropDown in repeater

I have three dropdownlists, three cascadingdropdown extenders, and updatepanel within a repeater. I need to update a label control inside of the updatepanel when the selectedindexchanged event fires for the last dropdown. The problem I'm having is that the event doesn't seem to fire the first time the selectedindex is changed. It works as expected after changing the first time. Anyone have any ideas as to why this is happening. Here is my code.

<asp:RepeaterID="uxPublicationRepeater"OnItemDataBound="PublicationRepeater_ItemDataBound"OnItemCommand="Pub_ItemCommand"runat="server">

<ItemTemplate>

<ajax:CascadingDropDownID="uxPublicationCascading"runat="server"

Category="Publication"

ServiceMethod="GetPublicationsByMarket"TargetControlID="uxPubDropDownList"

ParentControlID="uxMarketDropDownList"PromptText="Select.."LoadingText="Loading.."/>

<ajax:CascadingDropDownID="uxPublicationYearCascading"runat="server"

Category="PublicationYear"PromptText="Select.."LoadingText="Loading.."

ServicePath="~/Services/LookupWebService.asmx"ServiceMethod="GetYearsByPublication"

TargetControlID="uxPublicationDateDropDownList"ParentControlID="uxPubDropDownList"/>

<asp:DropDownListID="uxMarketDropDownList"runat="server"/>

<asp:DropDownListID="uxPubDropDownList"runat="server"/>

<asp:DropDownListID="uxPublicationDateDropDownList"OnSelectedIndexChanged="IndexChanged"AutoPostBack="true"runat="server"/>

<asp:UpdatePanelID="uxUpdatePanel"ChildrenAsTriggers="false"UpdateMode="conditional"runat="server">

<ContentTemplate>

<asp:LabelID="uxLabel"runat="server"/>

</ContentTemplate>

<Triggers>

<asp:AsyncPostBackTriggerControlID="uxPublicationDateDropDownList"EventName="SelectedIndexChanged"/>

</Triggers>

</asp:UpdatePanel>

</ItemTemplate>

</asp:Repeater>

Thanks for the help.

Have you taken a look at the sample?http://www.asp.net/AJAX/Control-Toolkit/Live/CascadingDropDown/CascadingDropDown.aspx

This could be related to EventValidation (see http://www.asp.net/AJAX/Control-Toolkit/Live/Walkthrough/CCDWithDB.aspx specfically:"Finally, in order for the values to be submitted, EventValidation needs to be disabled for the page. EventValidation ensures that the values in each control match the values that were present when the page was rendered, but since these drop downs are populating on the client side, this is never true.")

-Damien


I tried turning event validation off and still no good. The event fires the first time if the controls are outside of the repeater, but doens't fire until the second time when inside the repeater.


No one else has ran into this problem? If I take the cascadingdropdown extender out, the events fire correctly. Just to recap, dropdownlists in a repeater, selectedindexchange event fires correctly. Dropdownlists and cascadingdropdown extenders inside a repeater the event doesn't fire until the second time the selectedindex is changed. If anyone is interested I have a small sample app that illustrates the problem.


c.barnes01:

No one else has ran into this problem? If I take the cascadingdropdown extender out, the events fire correctly. Just to recap, dropdownlists in a repeater, selectedindexchange event fires correctly. Dropdownlists and cascadingdropdown extenders inside a repeater the event doesn't fire until the second time the selectedindex is changed. If anyone is interested I have a small sample app that illustrates the problem.

Hi,

I'd like to see your small sample, it will be preferred to use NorthWind database or a fake data source built in code.


Here is a small app that illustrates the problem.

<%@. Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" EnableEventValidation="false" Inherits="_Default" %><%@. Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="cc1" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> <title>Untitled Page</title></head><body> <form id="form1" runat="server"> <asp:ScriptManager ID="ScriptManager1" runat="server" /> <div> <asp:Repeater ID="uxTestRepeater" OnItemDataBound="Repeater_DataBound" runat="server"> <ItemTemplate> <cc1:CascadingDropDown ID="uxCountriesCascading" Category="Countries" runat="server" ParentControlID="uxCountryDropDownList" TargetControlID="uxStatesDropDownList" LoadingText="Loading.." PromptText="Select.." ServiceMethod="GetScopedStates" /> <asp:DropDownList ID="uxCountryDropDownList" runat="server" /> <asp:DropDownList ID="uxStatesDropDownList" AutoPostBack="true" OnSelectedIndexChanged="SelectedIndex_Changed" runat="server" /><br /> <asp:UpdatePanel ID="uxUpdatePanel" runat="server"> <ContentTemplate> <asp:Label ID="uxStateLabel" runat="server" Text="Select a State" /> </ContentTemplate> <Triggers> <asp:AsyncPostBackTrigger ControlID="uxStatesDropDownList" EventName="SelectedIndexChanged" /> </Triggers> </asp:UpdatePanel> <hr /> </ItemTemplate> </asp:Repeater> </div> </form></body></html>

using System;using System.Collections;using System.Collections.Generic;using System.Collections.Specialized;using System.Data;using System.Configuration;using System.Web;using System.Web.Security;using System.Web.Services;using System.Web.Script.Services;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.WebControls.WebParts;using System.Web.UI.HtmlControls;using AjaxControlToolkit;public partialclass _Default : System.Web.UI.Page{protected void Page_Load(object sender, EventArgs e) {if (!Page.IsPostBack) {this.uxTestRepeater.DataSource = GenerateRepeaterDataSource();this.uxTestRepeater.DataBind(); } }private List GenerateRepeaterDataSource() { List toReturn =new List(); toReturn.Add(new MyClass(1,"Chris"));return toReturn; }protected void Repeater_DataBound(object sender, RepeaterItemEventArgs e) { DropDownList countryDropDownList = e.Item.FindControl("uxCountryDropDownList")as DropDownList; countryDropDownList.DataSource = GenerateCountries(); countryDropDownList.DataTextField ="Value"; countryDropDownList.DataValueField ="Key"; countryDropDownList.DataBind(); }private Dictionary<int,string> GenerateCountries() { Dictionary<int,string> toReturn =new Dictionary<int,string>(); toReturn.Add(1,"USA"); toReturn.Add(2,"Canada"); toReturn.Add(3,"Mexico");return toReturn; }protected void SelectedIndex_Changed(object sender, EventArgs e) { DropDownList stateDropDown = senderas DropDownList; Label stateLabel = stateDropDown.NamingContainer.FindControl("uxStateLabel")as Label; stateLabel.Text = stateDropDown.SelectedItem.Text; } [WebMethod] [ScriptMethod]public static CascadingDropDownNameValue[] GetScopedStates(string knownCategoryValues,string category) { CascadingDropDownNameValue[] toReturn =null; StringDictionary values = CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues);if (values.Count == 1) {string key = values["undefined"];switch (key) {case"1": toReturn = GetStatesForUsa();break;case"2": toReturn = GetStatesForCanada();break;case"3": toReturn = GetStatesForMexico();break;default:break; } }return toReturn; }public static CascadingDropDownNameValue[] GetStatesForUsa() { CascadingDropDownNameValue[] toReturn =null; toReturn =new CascadingDropDownNameValue[5]; toReturn[0] =new CascadingDropDownNameValue("SC","1"); toReturn[1] =new CascadingDropDownNameValue("GA","2"); toReturn[2] =new CascadingDropDownNameValue("NY","3"); toReturn[3] =new CascadingDropDownNameValue("FL","4"); toReturn[4] =new CascadingDropDownNameValue("NC","5");return toReturn; }public static CascadingDropDownNameValue[] GetStatesForCanada() { CascadingDropDownNameValue[] toReturn =null; toReturn =new CascadingDropDownNameValue[5]; toReturn[0] =new CascadingDropDownNameValue("Saskatchewan","1"); toReturn[1] =new CascadingDropDownNameValue("Alberta","2"); toReturn[2] =new CascadingDropDownNameValue("British Columbia","3"); toReturn[3] =new CascadingDropDownNameValue("Nunavut","4"); toReturn[4] =new CascadingDropDownNameValue("Yukon","5");return toReturn; }public static CascadingDropDownNameValue[] GetStatesForMexico() { CascadingDropDownNameValue[] toReturn =null; toReturn =new CascadingDropDownNameValue[5]; toReturn[0] =new CascadingDropDownNameValue("Hidalgo","1"); toReturn[1] =new CascadingDropDownNameValue("Veracruz","2"); toReturn[2] =new CascadingDropDownNameValue("Puebla","3"); toReturn[3] =new CascadingDropDownNameValue("Durango","4"); toReturn[4] =new CascadingDropDownNameValue("Sonora","5");return toReturn; }}public class MyClass{private int id;public int ID {get {return id; }set { id =value; } }private string name;public string Name {get {return name; }set { name =value; } }public MyClass(int id,string name) {this.id = id;this.name = name; }}

I still haven't found a solution to this yet. Anyone have any suggestions?

Thanks


Bump


What is the full type name of the toReturn( List toReturn =new List();) object?


It should have been, List<MyClass> toReturn = new List<MyClass>();

thanks


I looked into it through, and found out that the reason is because the items are filled on client side.

1. On the first request( when isPostback is false ), there is no items in DDLState.

2. DDLState is filled when the page has been rendered in the browser

3. Select an item in the DDL to start a postback

4. The DDL tries to find the currentIndex( it's -1 since it can't be found ) and compares it with previousIndex( it's -1 since there is no item previously ) to see if a selectedChanged event should be fired. And it won't be fired because they are equal

5. On the second request, the previously posted item is kept in ViewState and subsequently added into DDLState's items collection

6. The previously index is 0 because the only item currently in DDLState matches the previous value. And currently posted item's value still doesn't exist, so currentIndex is -1. They are not equal, thus the SelectedIndexChanged event is fired.



Thanks for looking into the problem. It's weird that it works when not in a repeater.