#c# #asp.net #user-controls
#c# #asp.net #пользовательские элементы управления
Вопрос:
У меня есть веб-страница, содержащая панель и кнопку. Когда вы нажимаете кнопку, я хочу добавить новый экземпляр UserControl на панель.
Панель.Элементы управления.Метод Add указывает, что он добавляет элемент в коллекцию.
Я могу сделать это, используя локальную переменную для хранения количества экземпляров элемента управления. Затем, когда один из них добавлен, он повторяет цикл столько раз, создавая новые элементы управления.
private void AddUCToUI(int counter)
{
for (int i = 0; i < counter; i )
{
MyControl ctrlMyControl = (MyControl)LoadControl("MyControl.ascx");
ctrlMyControl.SetID(i);
myPanel.Controls.Add(ctrlMyControl);
}
}
НО я не хочу каждый раз воссоздавать все элементы управления, поскольку пользователь, возможно, уже ввел в них данные…
Итак, все, что я хочу сделать, это создать другой элемент управления и добавить его в коллекцию, которая уже содержит первый.
private void AddUCToUI(int counter)
{
MyControl ctrlMyControl = (MyControl)LoadControl("MyControl.ascx");
ctrlMyControl.SetID(counter);
myPanel.Controls.Add(ctrlMyControl);
}
Это должно создать новый элемент управления, присвоить ему идентификатор, затем добавить его в коллекцию. Однако, похоже, что сначала добавляется элемент управления, а затем перезаписывается этот элемент управления в коллекции, когда я пытаюсь добавить другой. Почему это?
Комментарии:
1. Вы уверены, что не вызываете код с одним и тем же значением переменной counter несколько раз?
2. вы уверены, что находитесь на той же странице? что произойдет, если вы не добавите вообще никаких элементов управления?
3. @Joon Я увеличиваю значение для счетчика при нажатии кнопки. Даже в этом случае все равно следует добавить несколько элементов управления с одинаковым идентификатором, поскольку ID — это просто переменная, которую я устанавливаю.
4. @Vlad Страница начинается без элементов управления. Первое нажатие кнопки добавляет один элемент управления. Второй щелчок заменяет этот элемент управления новым. Наверняка следует добавить еще один?
5. не уверен, что я чего-то здесь не понимаю…. всякий раз, когда вызывается AddUCToUI, разве LoadControl не выдает вам новый экземпляр MyControl.ascx? если да, нужен ли вам уникальный идентификатор? и явно использовать setID? Извините, если это звучит глупо, я мало работал с LoadControl…
Ответ №1:
Мне удалось решить эту проблему:
Перемещение кода из onInit
в Page_Load
и использование переменной сеанса для counter
решило проблему увеличения ее значения. Переменные сеанса не сбрасываются при выполнении обратной передачи.
Вот мое решение:
protected override void Page_Load(object sender, EventArgs e)
{
int counter;
if (Session["counter"] == null)
{
counter = 0;
}
else
{
counter = (int)Session["counter"];
}
for (int i = 0; i < counter; i )
{
MyControl ctrlMyControl = (MyControl)LoadControl("MyControl.ascx");
ctrlMyControl.ID = String.Format("ctrl_{0}", myPanel.Controls.Count); //count = 0
myPanel.Controls.Add(ctrlMyControl); //count = 1
}
}
Ответ №2:
Поскольку вы добавляете элементы управления динамически, вам придется каждый раз создавать их заново. Однако, если вы присвоите тот же идентификатор элементам управления при их повторном создании, они будут повторно заполнены из ViewState. Если элементы управления не заполняются повторно, вы, вероятно, воссоздаете их слишком поздно в жизненном цикле страницы. Попробуйте воссоздать их во время OnInit
:
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
for (int i = 0; i < counter; i )
{
MyControl ctrlMyControl = (MyControl)LoadControl("MyControl.ascx");
ctrlMyControl.ID = String.Format("ctrl_{0}", myPanel.Controls.Count); //count = 0
myPanel.Controls.Add(ctrlMyControl); //count = 1
}
}
Другим вариантом является DynamicControlsPlaceHolder
. По сути, этот элемент управления выполняет все вышеперечисленное за вас, не требуя никакого дополнительного кода.
Вы можете скачать его здесь:
http://www.denisbauer.com/ASPNETControls/DynamicControlsPlaceholder.aspx
Комментарии:
1. Я не уверен, что это так. Метод SetID — это всего лишь один из созданных мной методов. Он устанавливает локальную переменную в MyControl. Я не думаю, что ViewState будет повторно заполняться на основе этой переменной, поскольку она не идентифицирует этот экземпляр MyControl в коллекции. Как я могу изменить это, чтобы ViewState повторно заполнял его?
2. Если вы воссоздадите элементы управления во время
OnInit
и присвоите элементам управления те же идентификаторы, они должны быть повторно заполнены ViewState.3. Другой вариант — использовать
DynamicControlsPlaceHolder
, который я включил в свой ответ. Это действительно отличный элемент управления, который устраняет всю работу, необходимую для сохранения динамических элементов управления.4. Я добавил метод Oninit и метод getCounter, чтобы заставить это работать. Единственная проблема, с которой я сталкиваюсь сейчас, заключается в том, что во время выполнения метода OnInit счетчик, похоже, не имеет значения?
5. Вы добавляете все эти элементы управления в какой-то контейнер, например
Panel
илиPlaceHolder
?