Существует множество похожих вопросов по SO ( 1 , 2 , 3 , 4 и т. Д.) И в Интернете ( 1 , 2 и т. Д.), Но ни один из соответствующих ответов не проясняет мою ситуацию.
У меня есть простой пользовательский элемент управления, состоящий из двух раскрывающихся списков. Выбор значения в одном раскрывающемся списке должен привести к заполнению другого. Пока я объявляю пользовательский элемент управления в коде .aspx, все работает как положено.
Теперь я хочу добавить пользовательский элемент управления на странице программно (по нажатию кнопки). Хотя элемент управления добавляется, выбор в одном раскрывающемся списке вызывает только обратную передачу, но не выполняет никаких действий в другом раскрывающемся списке.
Во время отладки я обнаружил, что не только OnSelectedIndexChanged
не срабатывает, но также OnLoad
и все другие события.
Общие причины такого поведения в отношении всех обсуждений, которые я просматривал, следующие:
AutoPostBack
из DropDownList
не установлен в значение true или привязка данных DropDownList
восстанавливается при каждой обратной передаче, что приводит к потере событий. // здесь не так, скорее всего, это динамически добавленные выпадающие списки
ID
назначается динамически добавляемому элементу управления автоматически при каждой обратной передаче (и каждый раз другой, так что ViewState
не сохраняется правильно и события не знают, что они должны срабатывать). // хорошо, я проверил это и теперь присваиваю идентификатор вручную
Элемент управления добавляется только один раз (в отличие от добавления при каждой обратной передаче, что необходимо, поскольку в ViewState
сохраняются только состояние (значения) серверных элементов управления, но не сами элементы управления) и / или
элемент управления добавляется при каждой обратной передаче, но слишком поздно в жизненном цикле страницы. // хорошо, теперь я добавляю свой элемент управления в OnInit
обработчик событий
Чтобы сообщить странице, что элемент управления был добавлен (и сколько их), я использую Session
. Ниже немного кода и, наконец, вопрос:)
.aspx:
<asp:Content ID="Content3" ContentPlaceHolderID="MainContent" runat="server">
<asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
<asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" />
</asp:Content>
и код:
protected void Page_Load(object sender, EventArgs e)
{
if(!this.IsPostBack)
{
Session.Remove("Childcontrols");
}
}
private void AddTransitControl()
{
List<Control> controls = (List<Control>)Session["Childcontrols"];
AddTransitPoint atp = (AddTransitPoint)LoadControl("~/UserControls/AddTransitPoint.ascx");
string id = this.ID + "_eb" + (controls.Count).ToString();
atp.ID = id;
controls.Add(atp);
PlaceHolder1.Controls.Add(atp);
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
if (Page.IsPostBack)
{
if (Session["Childcontrols"] == null)
{
Session["Childcontrols"] = new List<Control>();
}
List<Control> controls = (List<Control>)Session["Childcontrols"];
int count = 0;
foreach (Control c in controls)
{
// AddTransitPoint atp = (AddTransitPoint) c; //mystically not working (fires no events)
AddTransitPoint atp = (AddTransitPoint)LoadControl("~/UserControls/AddTransitPoint.ascx"); //it is working!
string id = this.ID + "_eb" + count;
count++;
atp.ID = id;
PlaceHolder1.Controls.Add(atp);
}
}
}
protected void Button1_Click(object sender, EventArgs e)
{
AddTransitControl();
}
(Я уверен, что код самого пользовательского элемента управления не очень подходит для данного случая, но по запросу я могу добавить его позже).
Итак, теперь вопрос: методом проб и ошибок я обнаружил, что если я сохраню вновь добавленный элемент управления в коллекции в Session
и OnInit
, то просто вытащу элемент управления из этой коллекции и снова добавлю его в элемент управления. коллекция моего заполнителя, никакие события этого элемента управления не запускаются при следующей обратной передаче (независимо от способа вызова обратной передачи). Другой способ, если я создаю OnInit
новый элемент управления для каждого, сохраненного в Session
, и добавляю в коллекцию элементов управления заполнителя этот вновь созданный элемент управления - все работает! Так что же не так с сохраненными в Session
элементах управления и почему они теряют свои события?
И еще один маленький вопрос здесь. Какова наилучшая практика для создания идентификаторов для таких элементов управления? Я использую строку определенного формата вместе со счетчиком, но сомневаюсь, что это лучший способ сделать это. Например, если я добавлю различные типы элементов управления, у меня возникнет проблема с этим методом.
Спасибо всем за чтение такого длинного вопроса и за ваш ценный вклад!