Avatar billede bsp_andreas Nybegynder
27. august 2004 - 13:47 Der er 18 kommentarer

Dynamisk indsæt af række af inputbokse

Hej.

Jeg har en række af felter hvor brugeren kan indtaste forskellige oplysninger.
Nu skal det være sådan at når brugeren har indtastet en rækkke, kan han trykke på en knap og så kommer der en række mere, så han kan indtast en række af oplysninger mere.
På den måde bestemmer brugeren selv hvor mange han vil indtaste.

Det må kunne laves på en smart måde i et usercontrol eller noget??
Avatar billede nielsbrinch Nybegynder
27. august 2004 - 15:07 #1
Jeg tror jeg kender det rigtige princip, men jeg kan desværre ikke være mere konkret.

Du kan lave en placeholder og en usercontrol hvor din usercontrol indeholder de felter der skal indtastes. Så tilføjer du simpelt hen din placeholder til siden og du tilføjer så din usercontrol til din placeholder, i takt med at brugeren bestemmer sig for at ville indtaste en række til.

Det vil fungere, men det kræver selvfølgelig stadig en masse programmering!
Avatar billede snepnet Nybegynder
27. august 2004 - 20:13 #2
hej andreas :o)

der er rigtig mange måder du kan lave den slags på, men du kan lige få et bud på en strategi her :

jeg forestiller mig at du gerne vil gemme indtastnignerne i en database, og at brugeren eventuelt kan have indtastet noget i forvejen, så hvis du sørger for at hente din data lidt som dette :

// forbindelse, kommando og adapter
SqlConnection con = new SqlConnection(<connectionstring>);
SqlCommand com = new SqlCommand(<select string>, con);
SqlDataAdapter adap = new SqlDataAdapter(com);

// et dataset
DataSet ds = new DataSet();

// hent data
adap.Fill(ds);

// en lille finte for at sørge for at brugeren altid har en enkelt linie at indtaste i:

if(ds.Tables[0].Rows.Count==0)
{
    DataRow dr = PageDataSet.Tables[0].NewRow();
    dr["FldString"] = "test";
    ds.Tables[0].Rows.Add(dr);
}


Hvis du så sørger for at sætte et datagrid på de side, hvor du definerer en ItemTemplate med nogle indtastningsfelter - f.eks. sådan :

<asp:DataGrid id="DataGrid1" runat="server" AutoGenerateColumns="False">
    <Columns>
        <asp:TemplateColumn HeaderText="FldString">
            <ItemTemplate>
                <asp:TextBox id="Textbox2" runat="server" Text='<%# DataBinder.Eval(Container, "DataItem.FldString") %>'>
                </asp:TextBox>
            </ItemTemplate>
        </asp:TemplateColumn>
    </Columns>
</asp:DataGrid>

kan du så bare sørge for at lave en databinding til det dataset du lige har skabt med :

DataGrid1.DataSource = ds;
DataGrid1.DataBind();

Så skulle dit grid blive vist på siden, og brugeren kan så indtaste i de felter der er (jeg har jo så kun lige lavet et enkelt).

Du kan så sætte en knap ind til oprettelse af en ny linie, og i handleren af click-eventet kan du lave køre den samme kode som sikrede dig at have mindst én række - altså :

// tilføj en række
DataRow newRow = ds.Tables[0].NewRow();

// smid rækken ind i datasættet
ds.Tables[0].Rows.Add(newRow);

du skal så efterfølgende sørge for at databinde igen.

Når du skal gemme tingene igen, kan du komme meget nemt over det ved noget som nedenstående (med udgangspunkt i den adapter du så højere oppe) :

// opret commandbuilder... så fikser den insert, delete og update
SqlCommandBuilder commBuilder = new SqlCommandBuilder(adap);

// opdater data i basen
adap.Update(ds); // det samme dataset her igen

Der er lidt forskellige måder at få det hele til at spille sammen på.... og det kan være hensigtsmæssigt at lægge f.eks. dit dataset i session ell.

...

Det her var jo så bare en flok brudstykker, og du må endelig sige til, hvis du skal have en hånd med at "samle sagerne".

håber du kunne bruge det til et eller andet.

mvh
Avatar billede bsp_andreas Nybegynder
30. august 2004 - 15:32 #3
Hej - skifter lige over i det her spm.

Ref. (http://www.eksperten.dk/spm/534439) - det bliver jo efterhånden møg-besværligt!

Kan jeg have et datagrid og så kun pille nogle af dataene ud? Altså f.eks. skal jeg bruge 4 kolonner til at opstille mine data med, men kun 2 af kolonnerne skal der stå "database-data" i. I de andre 2 kolonner skal der stå noget fast tekst.

Comprendé??
Avatar billede snepnet Nybegynder
30. august 2004 - 15:38 #4
morsomt... du kan lige se her :
http://www.eksperten.dk/spm/534513
Avatar billede bsp_andreas Nybegynder
30. august 2004 - 16:41 #5
det var ikke lige det jeg ledte efter.

Så!! Nu bliver det langhåret..

Mit datagrid ser således ud i ascx-filen:

<asp:DataGrid id="DataGrid1" runat="server" AutoGenerateColumns="False">
<Columns>
  <asp:TemplateColumn>
  <ItemTemplate>
    <table><tr>
    <td>Antal tryk farve: <asp:Textbox id="Textbox16" runat="server" Columns="3"></asp:Textbox>
    </td></tr>
    <tr><td>Antal tryk farve: <asp:Textbox id="Textbox17" runat="server" Columns="3"></asp:Textbox>
    </td></tr>
    </table><br>
    </ItemTemplate>
  </asp:TemplateColumn>
  <asp:TemplateColumn>
    <ItemTemplate>
    <table>
      <tr><td>
      TOP <asp:Textbox id="Textbox13" runat="server" Columns="3"></asp:Textbox>
      </td></tr>
      <tr><td>FRONT <asp:Textbox id="Textbox18" runat="server" Columns="3"></asp:Textbox>
    </td></tr>
    </table> <br>
  </ItemTemplate>
  </asp:TemplateColumn>
</Columns>
</asp:DataGrid>

i ascx.cs-filen ser det således ud:

...
protected DataSet ReproData
{
get {
  return (object)Session["ReproData"] != null ? (DataSet)Session["ReproData"] : null ;
}
set {
  Session["ReproData"] = value;
}
}

private void Page_Load(object sender, System.EventArgs e)
{   
if(!IsPostBack)
{
  DataSet ds = new DataSet();
  ds.Tables.Add();
  ds.Tables[0].Columns.Add("Farve");
  ds.Tables[0].Columns.Add("Top");
  ds.Tables[0].Columns.Add("Front");

  ReproData = ds;
}
           
if(ReproData.Tables[0].Rows.Count==0)
{
  DataRow dr = ReproData.Tables[0].NewRow();
  dr[0] = "";
  dr[1] = "";
  dr[1] = "";
  ReproData.Tables[0].Rows.Add(dr);
}

DataGrid1.DataSource = ReproData;
DataGrid1.DataBind();
}

...

private void Button1_Click(object sender, System.EventArgs e)
{
DataRow dr = ReproData.Tables[0].NewRow();
// sæt værdier og
ReproData.Tables[0].Rows.Add(dr);
// og husk derefter databinding
DataGrid1.DataBind();
}

-------
Det fungerer faktisk nu. Altså at den ligger en ekstra række til osv., så man kan indtaste mere.
Men hvis man indtaster noget nu, og så trykker på knap1, så der kommer en ekstra række, så forsvinder det som stod i datagrid'et! Hvordan får jeg lige gemt det som brugeren har indtastet??
Avatar billede bsp_andreas Nybegynder
30. august 2004 - 16:42 #6
håver du kan hjælpe :)
Avatar billede bsp_andreas Nybegynder
30. august 2004 - 16:44 #7
fuck jeg skal have en staveplade i dag!
Avatar billede snepnet Nybegynder
30. august 2004 - 16:51 #8
jeg staver også altid helt forfærdeligt her ude... det skal jo bare gå lidt stærkt :o)

du gafler dem fra griddet sådan her (husk at der nu er sikkerhed for at du har lige mange rækker i dit grid, som i din datakilde).

// når du nu har editérbare bokse skal du jo det hele igennem
foreach(DataGridItem dgItem in Dg.Items)
{
  DataRow dr = NewRow();
  dr[X] = ((TextBox)dgItem.FindControl(<kontrol navn>)).Text;
}

ok ?
Avatar billede snepnet Nybegynder
30. august 2004 - 16:58 #9
Undskyld - for h... hvor jeg sidder og kludrer. Når du opdaterer skal du have fat i den række danner grundlag for dit griditem.
hvis du har et id direkte i rækken kan du bruge den, men der er flere måder at gøre det på :

// når du nu har editérbare bokse skal du jo det hele igennem
foreach(DataGridItem dgItem in Dg.Items)
{
  // hvis du har en unik nøgle kan du gøre sådan her
  DataRow dr = PageData.Tables[0].Select(nøgle - som du så evt. har direkte i griddet>?);
  dr[X] = ((TextBox)dgItem.FindControl(<kontrol navn>)).Text;
}

Men... der er rigtig mange måder at lave den der finte på, og det er ikke sikkert at den viste passer dig.

Du kan også sørge for at proppe en attribut på hver række, for så at hente den ved opdatering :

// ved databinding
e.Item.Attributes.Add("key",<keyValy fra datarækken>);

og når der så skal opdateres :

int id = int.Parse(e.Item.Attributes["key"]);

du kan så bruge id til at finde den rigtige række i dit datagrundlag.

det blev lidt rodet... kunne det bruges til noget ?

mvh
Avatar billede bsp_andreas Nybegynder
31. august 2004 - 11:30 #10
Hej - ja nu har jeg virkelig prøvet en masse ting, men jeg har stadig problemer.
Jeg kan pt. ikke lige få det du skrev til at fungere, så jeg prøvede bare lige at lave noget test.

Min button_click ser sådan ud.

private void Button1_Click(object sender, System.EventArgs e)
{
ReproData.Tables[0].Rows[0].ItemArray[0] = "400";

DataRow dr = ReproData.Tables[0].NewRow();
// sæt værdier og
ReproData.Tables[0].Rows.Add(dr);
// og husk derefter databinding
DataGrid1.DataBind();
}

hvor jeg bare lige prøver at sætte et felt til "400", og så  laver den lige en ny række. Den nye række bliver lavet og lagt til, men det felt bliver ikke sat til "400" - hvad glemmer jeg??
Avatar billede snepnet Nybegynder
31. august 2004 - 13:14 #11
private void Button1_Click(object sender, System.EventArgs e)
{
// først ny række
DataRow dr = ReproData.Tables[0].NewRow();

// så sætte data
dr[X] = someValue; // sæt f.eks. en stringkolonne til "test"

// klaske ind i tabellen
ReproData.Tables[0].Rows.Add(dr);

// og binde
DataGrid1.DataBind();
}
Avatar billede bsp_andreas Nybegynder
31. august 2004 - 14:39 #12
fuck jeg flipper snart over det her. Synes ikke jeg laver andet end at læse og læse om det datagrid og jeg kommer ingen vejne. øv :D

Nå, men nu fik jeg den jo til at skrive noget ind, som du forklarede her til sidst.

Så nu er jeg gået tilbage i nogle af dine gamle svar for at komme videre og få den til at gemme det skrammel som brugeren indtaster.

foreach(DataGridItem dgItem in Dg.Items)
{
  // hvis du har en unik nøgle kan du gøre sådan her
  DataRow dr = PageData.Tables[0].Select(nøgle - som du så evt. har direkte i griddet>?);
  dr[X] = ((TextBox)dgItem.FindControl(<kontrol navn>)).Text;
}


Den select() returnerer jo et helt array - hvordan får du det til at virke. jeg har lige lavet en ekstra kolonne, på min table, som hedder id (jeg har endnu ikke koblet db'en på - for at gøre det lettere for mig selv)
Jeg kan ikke få det Select til at fungere??
Avatar billede bsp_andreas Nybegynder
31. august 2004 - 14:59 #13
jeg forstår måske heller ikke helt hvorfor jeg skal lave den select??
Avatar billede snepnet Nybegynder
31. august 2004 - 15:03 #14
ahh.... hvis du ikke får et unikt id med op, må du sikre dig at tabellen har sådan en svedske, eller kan du ikke vælge en specifik ud på den måde :

Du kan jo koble en base på - eller lave lidt sampledata-halløjsa i koden... Du kan lige få en klasse til det her :

using System;
using System.Data;

namespace ExpArticles.ExpData
{
    /// <summary>
    ///    Klasse der kan generere lidt sampledata, og returnere det som et DataSet
    /// </summary>
    /// <remarks>
    ///   
    /// </remarks>
    public class ExpDataAccess
    {       
        private int _autoRows = 10;
   
        /// <summary>
        ///    Default antal rækker der indsættes i tabellen, hvis ikke andet er angivet
        /// </summary>
        public int AutoRows
        {
            get{return _autoRows;}
            set{_autoRows = value;}
        }

        /// <summary>
        ///    SampleData med det antal rækker i tabellen der er angivet i AutoRows
        /// </summary>
        ///
        /// <returns>
        ///    Et SampleDataSet objekt
        /// </returns>
        public SampleDataSet GetSampleData()
        {
            SampleDataSet ds = new SampleDataSet();
            TableFillers.FillTable(ds.Tables[SampleTable.TableName], AutoRows);
            return ds;
        }

        /// <summary>
        ///    Returnerer et SampleDataSet
        /// </summary>
        /// <param name="numberOfRows" type="int">
        ///    <para>
        ///        Antallet af rækker der genereres i tabellen
        ///    </para>
        /// </param>
        /// <returns>
        ///    Et SampleDataSet objekt
        /// </returns>
        public SampleDataSet GetSampleData(int numberOfRows)
        {
            AutoRows = numberOfRows;
            return GetSampleData();
        }
    }

    /// <summary>
    ///    SampleDataSet
    /// </summary>
    /// <remarks>
    ///   
    /// </remarks>
    public class SampleDataSet : DataSet
    {
        public SampleDataSet() : base()
        {
            InitClass();
        }

        public void InitClass()
        {
            this.DataSetName = "SampleDataSet";
            this.Namespace = "ExpArticles";
            this.Tables.Add(new SampleTable());           
        }
    }

    /// <summary>
    ///    En SampleTable
    /// </summary>
    /// <remarks>
    ///   
    /// </remarks>
    public class SampleTable : DataTable
    {
        new public const string TableName = "SampleTableName";
       
        public const string FldId            = "FldId";
        public const string FldString        = "FldString";
        public const string FldInt            = "FldInt";
        public const string FldDateTime        = "FldDateTime";
        public const string FldDecimal        = "FldDecimal";
        public const string FldBool            = "FldBool";
       
        public SampleTable() : base(TableName)
        {
            InitClass();
        }

        private void InitClass()
        {
            DataColumn c = this.Columns.Add(FldId, typeof(int));
            c.AllowDBNull = false;
            c.AutoIncrement = true;
            c.AutoIncrementSeed = 0;
            c.AutoIncrementStep = -1;

            DataColumn[] pKeys = {c};
            this.PrimaryKey = pKeys;       
       
            c = this.Columns.Add(FldString, typeof(string));
            c.AllowDBNull = true;
            c.DefaultValue = "Sample String";

            c = this.Columns.Add(FldInt, typeof(int));
            c.DefaultValue = 100;
            c.AllowDBNull = true;

            c = this.Columns.Add(FldDateTime, typeof(DateTime));
            c.DefaultValue = DateTime.Now;
            c.AllowDBNull = true;

            c = this.Columns.Add(FldDecimal, typeof(Decimal));
            c.DefaultValue = 100.00;
            c.AllowDBNull = false;

            c = this.Columns.Add(FldBool, typeof(bool));
            c.AllowDBNull = false;
            c.DefaultValue = false;
        }
    }

    /// <summary>
    ///    Klasse der er i stand til at generere et antal rækker i en tabel.
    ///    Rækkerne fyldes med defaultværdier, hvis nogle er angivet i tabellen.
    /// </summary>
    /// <remarks>
    ///   
    /// </remarks>
    public class TableFillers
    {
        /// <summary>
        ///    Metode til at fylde rækker i en tabel.
        /// </summary>
        /// <param name="table" type="System.Data.DataTable">
        ///    <para>
        ///        Den tabel rækkerne skal fyldes i 
        ///    </para>
        /// </param>
        /// <param name="numberOfRows" type="int">
        ///    <para>
        ///        Antallen af rækker der skal fyldes i table
        ///    </para>
        /// </param>
        /// <returns>
        ///    void
        /// </returns>
        public static void FillTable(DataTable table, int numberOfRows)
        {
            for(int i=0;i<numberOfRows;i++)
                table.Rows.Add(table.NewRow());
        }
    }
}

Det er hverken fint eller flot - men det kan da give dig lidt data at arbejde med (og der er unikt id i tabellen)
Avatar billede snepnet Nybegynder
31. august 2004 - 15:05 #15
selecten skal du lave for at få fat i den nøjagtige række du skal modificere.... (det er ikke så smart at tro på index ell... der går sikkert ikke mange splitsekunder, før der er en der vil kræve at du skal kunne sortere i dine lister og den slags alligevel ;o)
Avatar billede bsp_andreas Nybegynder
31. august 2004 - 16:10 #16
min db er connected osv - kunne ikke lige få klassen til at køre :) typisk mig!

Men jeg skal vide noget om den select-ting - man kan ikke bruge den på den måde som du viser. Den returnere jo et helt array, og jeg kan ikke få den til at returnere andet.

foreach(DataGridItem dgItem in DataGrid1.Items)
{
  DataRow dr = ReproData.Tables[0].Select("ID"); //dette fungerer ikke???
  dr[3] = ((TextBox)dgItem.Item.FindControl("Textbox18")).Text;
}
Avatar billede snepnet Nybegynder
02. oktober 2004 - 03:06 #17
hej andreas - her har jeg åbenbart også sovet... du har jo nok fået løst det nu, men mht :
DataRow dr = ReproData.Tables[0].Select("ID"); //dette fungerer ikke???

så returnerer select altid et array... der kan jo potentielt altid være flere rækker der overholder det du beder om, men du skal sørge for at bede om noget... f.eks. :

DataRow[] dr = ReproData.Tables[0].Select("ID>10");

mvh
(det er jo en lidt halvgammel sag den her, så du får lige et svar hvis jeg skulle have været til nytte, og du spørger bare hvis der skulle være mere).
Avatar billede snepnet Nybegynder
21. oktober 2004 - 19:46 #18
kan vi lukke her andreas ?
mvh
Avatar billede Ny bruger Nybegynder

Din løsning...

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.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester