03. juli 2004 - 14:28Der er
14 kommentarer og 1 løsning
Placeholder med dynamisk antal kontroller
Hej Jeg har lavet en form ved hjælp af en placeholder. Jeg har et antal checkboxe og en checkbox list for hver af disse. Jeg har implementeret checkboxene så man ved hjælp af en parameter kan endre på antallet af checkbox men jeg kan ikke finde ud af at implementere listboxene så disse også dynamisk kan endre deres antal. Dette skyldes at jeg har defineret nogle checkboxliscontroller i dette tilfelde 2 (til eksemplet) og dette virker fint men så er jeg jo bundet af dette antal. Hvis brugeren vil have 3 så skal jeg ind og udvide koden.
Kan nogen fortælle mig hvad der skal til så også antallet af checkboxlister kan udvides dynamisk?
Min nuværende kode ser således ud :
CheckBoxList lstFeaturedetails1 = new CheckBoxList(); CheckBoxList lstFeaturedetails2 = new CheckBoxList();
for (features=1;features<numberOfSelectedFeatures+1;features++) { spacer = space * (features-1); buttonTopBase = buttonTopBase + space; // this is a new instance of the cehckbox object? chkFeature = new CheckBox(); chkFeature.Text = featureName[features-1]; chkFeature.AutoPostBack = true; chkFeature.ID = "" + ((features-1)+1) + ""; if (searchmethod == "details") { chkFeature.CheckedChanged += new EventHandler(FeaturedetailsPannel); } plhSearchHolder.Controls.Add(chkFeature); if (searchmethod == "details") { switch (features) { case 1: plhSearchHolder.Controls.Add(lstFeaturedetails1); break; case 2: plhSearchHolder.Controls.Add(lstFeaturedetails2); break; } } }
Som det ses bruger jeg idag en case sætning til at udfylde 2 lstFeaturedeatails kontroller, det er dette jeg godt vil lave mere dynamisk så jeg ikke skal ind ændre koden hvergang jeg vil have nogle flere checkboxlister.
Er der nogen der har et hint til hvordan dette kan gøres?
Kommunerne har digitaliseret indgangen for borgerne. Men bag skærmen håndteres mange arbejdsgange stadig manuelt mellem systemer, mails og organisatoriske siloer.
// til checkboxlisterne CheckBoxList cbList = null;
// hashtabel til emulering af dynamisk ressource Hashtable listResource = new Hashtable();
// initialisering af ressourcen listResource.Add(0, new string[] {"0hej","0med","0dig"}); listResource.Add(1, new string[] {"1hej","1med","1dig"}); listResource.Add(2, new string[] {"2hej","2med","2dig"});
// iteration over ressourcen foreach(DictionaryEntry de in listResource) { // oprettelse af ny liste cbList = new CheckBoxList();
// angivelse af at data skal hentes fra ressourcen cbList.DataSource = (string[])listResource[de.Key];
// indsættelse af kontrollen this.Controls[1].Controls.AddAt(0,cbList);
// databinding cbList.DataBind(); }
Nu er det jo bare et lille uanvendeligt eksempel, men hvis det er lidt i den retning kan jeg udvide det lidt med en måde at lægge data til initialisering uden for koden, hvis du skulle være interesseret.
Hov - det må du undskylde. Det var ikke så relevant det jeg sendte :o( Jeg skal nok lave et andet eksempel til dig... Vil de helst have at ressourcen hvor værdierne til listerne kommer fra er et dataset, nogle værdier i web.config, eller ?
Det er ikke så vigtigt hvor verdierne kommer fra det der generer mig er at jeg skal gemme dem i : CheckBoxList lstFeaturedetails1 = new CheckBoxList(); CheckBoxList lstFeaturedetails2 = new CheckBoxList();
Hvis man dog bare kunne sige CheckBoxList[] lstFeaturedetails1 = new CheckBoxList()[antal]; så ville man kunne udvide antallet af kontroller dynamisk og så ville mit problem være løst men bryder compileren sig ikke om.
Hvis du har en løsning til hvordan jeg opbevare kontroldataene i en felles container feks en indexer ville jeg være glad. En anden løsning vil være hvis jeg kunne kopiere indholdet af lstFeaturedetails1 over i lstFeaturedetails. Altså indholdet fra en kontrol over i en anden kontrol af samme type, det ville også hjælpe mig meget på dette område.
Der er for øvrigt ikke noget i vejen for at du laver collection af den ene eller anden art, og så laver en indexer i den forbindelse (det er ikke indexeren der holder data - den realiserer bare en lettere adgang til dem).
En indexer kan laves sådan rimelig enkelt - du kan lige få et pricipielt eksempel her :
public class SomeIndexerhungryClass { // et eller andet array private int[] someInts = new int[10];
// og en indexer for adgang til arrayet public int this [int index] { // getter get{return someInts[index];}
Nu har jeg forsøgt at putte et array element i en placeholder.
Koden er denne :
#code start CheckBoxList[] lstFeaturedetails = new CheckBoxList[5];
for (features=1;features<numberOfSelectedFeatures+1;features++) { plhSearchHolder.Controls.Add(lstFeaturedetails[features-1]); } #code slut
Men for følgende fejl :
Value cannot be null. Parameter name: child
Når jeg putter en checkboxliste er der ingen problemer.
#code start CheckBoxList lstFeaturedetails1 = new CheckBoxList(); plhSearchHolder.Controls.Add(lstFeaturedetails1); #code slut
Hvorfor denne forskel?
Jeg kan få fejlen væk ved at gøre følgende :
#code start lstFeaturedetails[features-1] = lstFeaturedetails1; plhSearchHolder.Controls.Add(lstFeaturedetails[features-1]); #code slut
men så for jeg en ny fejl : Failed to load viewstate. The control tree into which viewstate is being loaded must match the control tree that was used to save viewstate during the previous request. For example, when adding controls dynamically, the controls added during a post-back must match the type and position of the controls added during the initial request.
Er dette noget du kender noget til?.
I øvrigt, post lige et svar for points, og tak for de mange tips :-)
Første denne : #code start CheckBoxList[] lstFeaturedetails = new CheckBoxList[5]; for (features=1;features<numberOfSelectedFeatures+1;features++) { // her bliver du nødt til at tilføje : lstFeaturedetails[features-1] = new CheckBoxList(); // så vil denne virke plhSearchHolder.Controls.Add(lstFeaturedetails[features-1]); } #code slut
Men denne : #code start lstFeaturedetails[features-1] = lstFeaturedetails1; plhSearchHolder.Controls.Add(lstFeaturedetails[features-1]); #code slut
Har jeg lidt sværere ved at svare på - så skal jeg se lidt mere kode, men helt generelt får du problemer hvis du får skabt et viewstate udfra et kontroltræ, og så efterfølgende under initialiseringen af en side ændrer på det kontroltræ. På den måde vil det ikke være muligt at retablere dine kontroller.
Et eksempel kunne være :
// i page_load :
// til checkboxlisterne CheckBoxList[] cbListArray = new CheckBoxList[5];
// iteration i fohold til antallet af checkboxlister for(int i=0;i<cbListArray.Length;i++) { // init cbListArray[i] = new CheckBoxList();
// angivelse af at data skal hentes fra ressourcen cbListArray[i].DataSource = new string[] {"hej","med","dig"};
// indsættelse af kontrollen this.Controls[1].Controls.AddAt(0,cbListArray[i]);
Det er nøjagtig det samme - den nederste kan du bare kun skrive hvis du et andet sted har angivet at chkFeature er af typen CheckBox. Den vil ikke kunne stå alene.
Hvis det er pga. den med arrayet CheckBox[] checkboxes = new CheckBox[5], hvor det efterfølgende er nødvendigt at lave en checkboxes[x] = new CheckBox(), så er årsagen at du sådan set bare har forberedt et array indeholdende elementer af en specifik type, men du har ikke instatieret nogle af elementerne endnu, hvilket er hvad du gør med checkboxes[x] = new CheckBox();
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.