13. oktober 2007 - 12:51Der er
15 kommentarer og 1 løsning
checkboxlist og database.
Hej Eksperter,
jeg har en hovedtabel med et ID og en anden tabel der indeholder landsdele:
Stor København Fyn Midt Jylland ...
denne tabel viser jeg i en CheckBoxList - selve visningen af disse virker fint.
Jeg har en anden reference tabel hvor jeg knytter hovedtabelens ID og de valgte landsdele - nu vil jeg gerne kæde disse sammen så jeg kan vise hvilke der er valgt når jeg lister landsdele for brugeren.
eksempel:
Stor København - Checked Syd Sjælland - Checked Fyn - UnChecked Sønder Jylland - Unchecked Midt Jylland - Checked
når jeg har fået vist hvilke landsdele der er valgt, har jeg en ide om at jeg vil tjekke på om der sker ændringer ved false, true på hvert CheckBoxListItem:
int index = ChkLandsdeleListe.SelectedIndex; if (index > -1) { if (ChkLandsdeleListe.Items[index].Selected == true) { lblTjeck.Text = ChkLandsdeleListe.Items[index].Text.ToString() + " : true"; //insert i DB } else if (ChkLandsdeleListe.Items[index].Selected == false) { lblTjeck.Text = ChkLandsdeleListe.Items[index].Text.ToString() + " : false"; //slet fra DB }
Jeg er ikke sikker på at dette er den rigtige måde at opbygge DB på eller om det er for en besværlig måde at få vist valgte værdier som checked og stadig får vist den samlede landsdele liste.
Er det som ovenstående ? Og hvad er det du ønsker at slette/inserte i db'en ? Jeg er for så vidt ligeglad med indholdet, det er mere for at kunne forstå logikken i hvad du ønsker. Kunne du illustrere med nogle ord eller komme med et eksempel?
landsdeletabel: (Bruges til at styre hvilke landsdele der skal kunne vælges imellem) landsdeleID landsdelnavn
landsdelsreftabel: (skal indeholde de valgte landsdele pr. hovedID) landsdelrefID landsdeleID hovedID
jeg vil vise en liste af landsdele fra Landsdeletabellen via checkboxlist, og vil gerne have at de landsdele der er valgt skal have flueben i. så man man sige at checked (hvis den fandtes i checkboxlist) skulle være true såfremt det står i referencetabellen.
Her knytter du to tabeller sammen vha en tredje. I den tredje kan du så i princippet nøjes med en composite primary key, bestående af HovedID og LandsdelID som så også er foreign keys. Med andre ord når du danner en record i Landsdelreftabel, så har du jo keys fra Hovedtabel og Landsdeltabl, og de bliver til en kombineret primær nøgle for er record i landsdelreftabel.
B. Eftersom du har et begrænset antal landsdele, og disse ikke formodes at ændre sig, så kunne du også knytte dem sammen på en anden måde. Du kunne tilføje lidt kolonner til din Hovedtabel:
Så for hver HovedID har du en række af yes/no som siger om den er valgt i den givne landsdel. Entusiaster kunne for en megastor DB tillige finde på at koge alle disse forskellige bit-kolonner ned til en enkelt int32/int64, hvori man kan gemme den samme information bit-by-bit:)
det er helt klart A løsningen jeg vil gå efter - men det der faktisk er problemet lige nu er at få vist hele landsdelelisten fra den ene tabel, og så få dem markeret som true i checked såfremt de findes i referencetabellen. har du en ide til det loop der skal kunne håndtere dette, og hvordan ville du eventuelt opdatere reference tabellen, ville du slette alle de hidtil valgte og herefter indsætte dem alle på ny igen eller...?
C. løsning kunne måske også være at have et felt i hovedtabellen som tekst og så skrive en comma separeret tekst med de valgte som man så kigger igennem, dog løser der stadig ikke mit problem med at få det til at blive vist korrekt - men måske det ville være lettere at overskrive et felt i hovedtabellen end at skulle hitte ud af det andet :) ???
Ad C. Næppe - det er jo selv at lave arbejde som systemet kan gøre for dig (at parse noget string halløj), så det vil jeg ikke anbefale.
Det er aledeles uklart for mig hvorfor du ønsker A - men ok, kan være der er andre faktorer som spiller ind:).
Hvis du vil opdatere en "link-tabel" for en many-to-many relation så har du to optioner:
a). Slette det hele og inserte nye links på baggrund af nye data. Det kan du gøre som du strot set selv har bekrevet i dit oprindelige spørgsmål - blot kald din kode f.eks. når brugeren trykker Done/Save eller en eller anden Next-knap. Husk blot først at loope og slette alle, og derpå loope en gang til og nu inserte alle dem som er checked.
b). Med det samme slette en landsdel hvis den blev unchecked, eller inserte den hvis den blev checked. Du kunne lave en eventhandler minCheckBoxList_SelectedIndexChanged (bare dobeltklik på din checkboxlist i Designeren) som trigges når man klikker i checkboxlisten. I handleren skal du så finde ud af om den checkbox som triggede eventet (=se hvilken værdi selectedindex har nu) nu har fået status checked=true eller false, og så med det samme fare ud i db'en og slette/tilføje den record.
Nu ved jeg ikke hvilken DB du kører med, men for at sætte dine checkboxes true/false med data fra db'en kunne du bruge noget som ligner dette:
Dim myDBConnection As OleDbConnection = utils.DBconnection Dim myID As Integer
Dim queryString As String queryString = "" Dim command As OleDbCommand = New OleDbCommand("", myDBConnection) command.CommandText = "SELECT profileID FROM UserProfiles WHERE userID=" & myID.ToString
Dim mylist As CheckBoxList = DetailsView1.FindControl("CheckBoxList1") Dim myReader As OleDbDataReader = command.ExecuteReader
Dim myVal As Integer Do While myReader.Read() myVal = myReader.GetInt32(0) For Each li As ListItem In myCehckBoxList.Items If li.Value = myVal Then li.Selected = True End If Next Loop myReader.Close() myDBConnection.Close()
OleDbConnection MyConnection = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|test.mdb"); String SelectCmd = "SELECT [LandsdelRefID], [LandsDelID] FROM [LandsdelRef] WHERE ParterRefID = 1"; OleDbCommand MyCommand = new OleDbCommand(SelectCmd, MyConnection); MyCommand.Connection.Open(); OleDbDataReader result;
try { result = MyCommand.ExecuteReader(); while (result.Read()) { int myVal = result.GetInt32(1); foreach (ListItem li in CheckBoxList1.Items) { if (li.Value == myVal.ToString()) { li.Selected = true; } } } } catch (OleDbException ex) { throw ex; //return 0; } MyCommand.Connection.Close();
nu er det bare lige det emd at få det til at virke i et formview i Editmode. har du prøvet at benytte event SelectedIndexChanged() hvor du vil finde ud af om en checkbox er sat til true eller false?
prøvede ovenstående kode hvor jeg udfyldte selve checkboxlisten med en almindelige GUI ObjectDataSource - men den ville ikke vælge de valgte, det var som om at den arbejde før selve checkboxlisten var udfyld, så count altid var 0.
Hvis du har det hele liggende inde i et formview så er det mere logisk først at gemme ændringerne når brugeren siger OK, og dvs du skal så bare delete de gamle og inserte de nye.
Jeg har noget gammel skodkode som gør det inde i et detailsview, den må du kunne tilpasse:
Protected Sub DetailsView1_ItemUpdated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DetailsViewUpdatedEventArgs) Handles DetailsView1.ItemUpdated Dim newID As Integer Dim myDBConnection As OleDbConnection = utils.DBconnection
newID = DetailsView1.SelectedValue
' save profile by first deleting old profile and then saving the new one Dim queryString As String queryString = "" Dim command As New OleDbCommand(queryString, myDBConnection) command.CommandText = "DELETE FROM UserProfiles WHERE userID=" & newID.ToString ' command.Connection.Open() command.ExecuteNonQuery()
Dim mylist As CheckBoxList = DetailsView1.FindControl("CheckBoxList2") For Each li As ListItem In mylist.Items
If li.Selected Then command.CommandText = "INSERT INTO UserProfiles (userID, profileID) VALUES ('" & newID.ToString & "','" & li.Value.ToString & "')" command.ExecuteNonQuery() End If Next myDBConnection.Close()
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.