Динамически созданные элементы управления теряют значения

АСП.НЕТ 4.0. Я хочу разрешить пользователям просматривать/редактировать элементы по лицензии клиента. Лицензия включает продукты 1-M, и список продуктов со временем будет расширяться, поэтому я динамически создаю список всех продуктов (в Page_Load) с флажком, чтобы указать, есть ли в лицензии этот продукт, например:

CheckBox cbxProduct = new CheckBox();
cbxProduct.ID = "cbxProduct" + product.ID.ToString();

Я могу найти эти динамические элементы управления и получить доступ к их значениям в PostBack, используя:

CheckBox cbxProd = (CheckBox)pnlLicenseDetails.FindControl("cbxProduct" + productID.ToString());

но только если они были только что воссозданы в Page_Load (или Page_Init, похоже, не имеет значения). Проблема в том, что я хочу, чтобы пользователь мог снять флажок, чтобы удалить продукт из лицензии, а затем сохранить результаты. Но для того, чтобы найти флажок и определить его значение, мне приходится заново создавать элементы управления, что, конечно же, стирает любое введенное пользователем значение.

Если я попытаюсь сослаться на флажки без их повторного создания, я, конечно, получу ошибку "ссылка на объект не установлена...". Поэтому мне нужен какой-то способ зафиксировать значения, которые вводит пользователь, до того, как они будут уничтожены.

Предложения?


person SteveEx    schedule 20.06.2013    source источник


Ответы (1)


Вы должны создать динамические элементы управления в Page_Init. Вы должны создать их одинаково для всех запросов. Это означает, что запускайте один и тот же код для создания элемента управления и добавляйте его в коллекцию элементов управления каждый раз, когда загружается страница, независимо от того, IsPostBack или нет.

Кроме того, я бы посоветовал вам сохранить экземпляр динамического элемента управления в частной переменной-члене, чтобы вам не приходилось вызывать FindControl, поскольку это потенциально дорого.

Поскольку похоже, что у вас где-то есть список продуктов, вот пример использования словаря для хранения флажков:

public partial class _Default : Page
{
    private Dictionary<Int32,CheckBox> _myDynamicCheckBoxes;

    protected override void OnInit(EventArgs e)
    {
        _myDynamicCheckBoxes = new Dictionary<Int32,CheckBox>();

        foreach (var product in _listOfProducts)
        {
            var chkBox = new CheckBox {ID = "CheckBox" + product.ID.ToString()};
            _myDynamicCheckBoxes.Add(product.ID,chkBox);
            //add the checkbox to a Controls collection
        }
    }
}

Затем где-то еще в вашем коде, когда у вас есть продукт и вы хотите найти связанный с ним флажок, вы можете использовать: var aCheckBox = _myDynamicCheckBoxes[product.ID];

person matt-dot-net    schedule 20.06.2013
comment
Спасибо, @matt-dot-net. Можете ли вы объяснить альтернативу FindControl? Я не уверен, что вы подразумеваете под частной переменной-членом. - person SteveEx; 20.06.2013
comment
Кстати, я настроил так, чтобы функция BuildControls вызывалась в Page_Init независимо от PostBack. Ошибка ссылки на объект сохраняется при попытке сохранить изменения пользователя. Если я вызываю BuildControls из события SaveChanges, я обхожу это, но получаю сообщение об ошибке, говорящее о том, что несколько элементов управления имеют один и тот же идентификатор, очевидно, поскольку BuildControls также находится в Page_Init. - person SteveEx; 20.06.2013
comment
Эта идея Словаря была серебряной пулей, которую я искал. Спасибо, @matt-dot-net! - person SteveEx; 21.06.2013