Bit of a tough bug I'm dealing with. I've created an ASP DropDownList using a Repeater like so in my .aspx file:
mypage.aspx
<asp:Repeater ID="rptTemplateFields" runat="server"
DataSource='<%# rptrDataSource %>'
OnItemDataBound="rptTemplateFields_OnItemDataBound">
<ItemTemplate>
<asp:DropDownList ID="ddlRepeater" runat="server" AppendDataBoundItems="true"
AutoPostBack="True"
OnSelectedIndexChanged="ddlRepeater_SelectedIndexChanged"
width="360" Visible="False">
<asp:ListItem Text="" Value="" />
</asp:DropDownList>
</ItemTemplate>
</asp:Repeater>
And I'm populating these dropdowns with the following in my codebehind:
mypage.aspx.cs
protected void rptTemplateFields_OnItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.AlternatingItem)
{
dynamic field = e.Item.DataItem;
BugFieldName fieldName = field?.FieldName;
string fieldContent = field?.FieldContent;
var allowedValues = GenerateAllowedValues(fieldName);
if (!fieldName.IsNullOrUnsetValue() && !allowedValues.IsNullOrEmpty())
{
var ddl = e.Item.FindControl("ddlRepeater") as DropDownList;
ddl.ID = "_ddlField" + fieldName;
ddl.Attributes.Add("Name", "_ddlField" + fieldName);
ddl.ClientIDMode = ClientIDMode.Static;
ddl.DataSource = allowedValues;
ddl.SelectedValue = allowedValues.Contains(fieldContent)
? fieldContent
: null;
ddl.Visible = true;
ddl.DataBind();
}
}
}
protected void ddlRepeater_SelectedIndexChanged(object sender, EventArgs e)
{
var ddlRepeater = sender as DropDownList;
var state = (string)ViewState[ddlRepeater.Attributes["Name"]];
if (state != ddlRepeater.SelectedItem.Text)
{
ViewState[ddlRepeater.Attributes["Name"]] = ddlRepeater.SelectedItem.Text;
}
}
The problem is the first time I click the drop down list and change the item (immediately post creation and databind), a page load is triggered and the ddl.SelectedValue, etc. state is wiped and the DropDownList's "OnSelectedIndexChanged" event handler does not fire.
Immediately following this page load, subsequent changes in the DropDownList DO trigger OnSelectedIndexChanged and the list's state is preserved. I imagine something funky is going on with the postback and data binding, but I'm not sure where I'm going wrong.
So far I've tried using other event handlers without any luck. I've confirmed that a page load does occur and it is a PostBack. I added <%@ Page ViewStateMode="Enabled" %> to my aspx file. I also tried using an ItemCommand listener on the repeater. This also did not fire.
Ok, this issue looks to be that you set the data source of the repeater in the markup. So, with any post-back, your re-load and re-binding code runs again, and that results in the loss of any selecting you make (re-binding reruns your row data bound code again and again). So, any changes you make are lost due to the post back and the reloading of data again.
The simple solution is to bind the data to the repeater in code behind, and ONLY one time.
Hence, say this simple markup:
And our code behind, and note VERY close how we ensure only a binding of the data on the first page load (IsPostBack = false).
Hence this code:
And the result is now this:
So, often it can be ok to place some data source in the markup, but the instant you have post backs and additional code logic, then I suggest you "take control" of the data binding by using code behind, and not leave up when re-binding may, or may not reoccur.