Динамично създадените контроли губят стойности

ASP.NET 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