Avatar billede x-periment Nybegynder
17. januar 2006 - 12:12 Der er 30 kommentarer og
1 løsning

Datagrid og lists

Hvis jeg har en list

List<string> cuedStrings = new List<string>();

og ønsker at alle strengene skal vises i et datagrid

med en kollone

som fx.

  ------------
  strings
---------------
    test
---------------
    test2



stregerne er for grafisk effekt og skal selvføgelig ikke vises ;)
indtil videre har jeg oprettet et datagrid

  dataGridView1

og  har sat

dataGridView1.DataSource = cuedStrings;

men hvordan får jeg så listens strenge til at blive vist i string feltet i datagridded ???
Avatar billede bitsch Nybegynder
18. januar 2006 - 00:25 #1
Hmm... det tror jeg faktiskt ikke at du kan i dette tilfælde, men jeg er ikke 100% sikker.

Indtil andre svar dukker op kan du overføre din List<> til en DataTable. Men det ville jo være rart at undgå dette step.

            #region DataGridView

            // Demodata...
            List<string> cuedStrings = new List<string>();
            cuedStrings.Add("Test");
            cuedStrings.Add("Test2");
            cuedStrings.Add("Test3");

            // Én løsning er at smide indholdet over i en DataTable
            DataTable dataTable = new DataTable();
            DataColumn dataColumn = new DataColumn("Text");
            dataColumn.Caption = "Text";
            dataTable.Columns.Add(dataColumn);

            // Add rows.
            foreach (string item in cuedStrings)
            {
                dataTable.Rows.Add(item);
            }

            // Assign data.
            this.dataGridView.DataSource = dataTable;

            #endregion
Avatar billede x-periment Nybegynder
18. januar 2006 - 14:07 #2
private void addString(string info)
        {
            if (!cuedStrings.Contains(info))
            {
                cuedStrings.Add(info);
                dataTable.Rows.Add(info);
                dataGridView1.DataSource = dataTable;
            }
      }

      DataColumn dataColumn = new DataColumn("CuedStrings");
            dataColumn.Caption = "nextstring";
            dataTable.Columns.Add(dataColumn);

er hvad jeg har lavet indtil videre
men output i datagrided bliver
System.Windows.Forms.Label, Text: "test streng"

skal måske lige tilføje at de strenge der bliver tilføjet kommer fra labels som brugeren trykker på.... hvis det ændre noget ..
Avatar billede x-periment Nybegynder
18. januar 2006 - 14:08 #3
Der skal selvfølgelig kun stå "test streng i gridded" ..
Avatar billede bitsch Nybegynder
18. januar 2006 - 16:21 #4
Der hvor du kalder din addString(...) er da din parameter minLabelEllerHvadDenNuHedder.Text ? for ellers vil den kalde ToString! (hvis du har udeladt .Text) og så får du det resultat du har nu!
Avatar billede x-periment Nybegynder
18. januar 2006 - 18:46 #5
Godt set bare mig der havde fået en hjerneblødning .... tak for hjælpen smid et svar og få pointene :)
Avatar billede bitsch Nybegynder
18. januar 2006 - 19:07 #6
Jeg arbejder dog videre med at få et svar på dit oprindlige spørgsmål, så stay tuned...
Avatar billede x-periment Nybegynder
18. januar 2006 - 19:18 #7
det ville være fantastisk.... det kan være du lige kan hjælpe mig med hvordan jeg så sletter et felt. Det bliver altid det første felt der skal slettes ....så det burde være rimelig let har årøvet men noget ligne det her

                    cuedStrings.RemoveAt(0);
                    try
                    {
                        dataTable.Rows.RemoveAt(0);
                        try
                        {
                            dataGridView1.DataSource = dataTable;
                        }
                        }
Men jeg fr alle mulige mærkelig popup med at index 1 value is unassigned ...
Avatar billede bitsch Nybegynder
18. januar 2006 - 21:00 #8
Det letteste vil jo i så fald være at fjerne værdien fra din List<string> inden du asigner din grid. Det kan du gøre således:

        public static List<string> RemoveFirstItem(List<string> value)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            if (value.Count > 0)
            {
                value.RemoveAt(0);
            }

            return value;
        }
Avatar billede bitsch Nybegynder
18. januar 2006 - 21:02 #9
cuedStrings = RemoveFirstItem(cuedStrings);
Avatar billede bitsch Nybegynder
18. januar 2006 - 21:12 #10
Hvis du alligevel hellere vil fjerne fra gridden, så kan du ligesågodt accesse din tabel:

if (dataTable.Rows.Count > 0)
{
    dataTable.Rows.RemoveAt(0);
}

og vupti... så bliver din grid opdateret :-)
Avatar billede bitsch Nybegynder
18. januar 2006 - 23:37 #11
Svaret på det oprindelige spørgsmål er...

Desværre er det som jeg formodede, DataGrid & DataGridView databinder kun til properties. Da strenge ikke har properties vil det derfor ikke være muligt. Hvis du vil bruge din generiske liste direkte er du altså nødsaget til at pakke din streng pænt ind i en klasse som eksponerer strengen vha. en property.
Avatar billede bitsch Nybegynder
18. januar 2006 - 23:50 #12
Og et hurtigt eksempel på dette kan se ud som følger:

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            List<StringClass> cuedStrings = new List<StringClass>();
            cuedStrings.Add(new StringClass("Test1"));
            cuedStrings.Add(new StringClass("Test2"));
            cuedStrings.Add(new StringClass("Test3"));

            this.dataGridView1.DataSource = cuedStrings;
        }
    }

    public class StringClass
    {
        private string text;

        public string Text
        {
            get { return this.text; }
            set { this.text = value; }
        }

        public StringClass(string text)
        {
            this.text = text;
        }
    }
Avatar billede x-periment Nybegynder
19. januar 2006 - 16:39 #13
det ser udtil at virke næsten .... :( med deet sidste du har lavet...

private void addNumber(string info)
        {
            if (!cuedStrings.Contains(new StringClass(info)))
            {
                cuedStrings.Add(new StringClass(info));
                MessageBox.Show(info);
                this.dataGridView1.DataSource = cuedStrings;
               
            }
           
        }

men jeg kan af mystiske årsager kun vist den første streng der bliver tilføjet...
har tjekket alle strenge ligger cuedStrings hvilket de rigtig nok gør.
det næste er jeg stadig får en execption når jeg sletter fra cuedStrings får jeg fejlen DataGridview index out of range execption ...
Avatar billede x-periment Nybegynder
19. januar 2006 - 16:39 #14
næsten i mål mangler så lidt
Avatar billede x-periment Nybegynder
19. januar 2006 - 16:43 #15
helt precist er fejle index 0 har ikke en værdi ....

Skal jeg forresten  gør sådan efter jeg fjernet fra cuedstrings
cuedTrack.RemoveAt(0);
this.dataGridView1.DataSource = cuedTrack;
Avatar billede x-periment Nybegynder
19. januar 2006 - 17:05 #16
Har lige siddet og kigget lidt på det.. hvis den første streng bliver slette kommer den næste til også videre så det der vises er næste som fifo kø ... Ved bare ikke hvordan man lige får tilføjet en række når der sættes ind i cuedStrings
Avatar billede x-periment Nybegynder
19. januar 2006 - 17:15 #17
public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            List<StringClass> cuedStrings = new List<StringClass>();
                    }
    }
Avatar billede x-periment Nybegynder
19. januar 2006 - 17:17 #18
sorry forkert knap sådan ser min kode ud nu

List<StringClass> cuedStrings = new List<StringClass>();
public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

           
                    }
    }

private void addNumber(string info)
        {
            if (!cuedStrings.Contains(new StringClass(info)))
            {
                cuedStrings.Add(new StringClass(info));
                MessageBox.Show(info);
                this.dataGridView1.DataSource = cuedStrings;
               
            }
           
        }
Avatar billede bitsch Nybegynder
19. januar 2006 - 22:46 #19
Nu er jeg ikke helt med på mere hvad du egentligt gerne vil have.
Jeg har vist dig hvorledes du binder en List<string> til en grid.
Jeg har også vist dig hvordan du fjerner første element fra denne liste.

Men er dit ønske nu at List<StringClass> skal være unik (ingen duplikater), for umiddelbart ser det ud til at det er det du forsøger.
Avatar billede bitsch Nybegynder
19. januar 2006 - 23:56 #20
Fordi du har pakket din streng pænt ind i en klasse kan kan du ikke umiddelbart sammenligne ens lignende objekter.

Derfor vil det fejle når du spørger på:  if (!cuedStrings.Contains(new StringClass(info)))...

Du må derfor gøre noget for at det kan lade sig gøre.
Du kan læse om hvordan på:http://msdn2.microsoft.com/en-us/library/7h9bszxx.aspx og: http://msdn2.microsoft.com/en-us/library/336aedhh.aspx

For at få din cuedStrings.Contains til at virke skal du som minimum override din Equals metode. Man bør dog også implementere ==, !=, <, >.
Men det er ikke nødvendigt for at få din kode til at du. (I dette tilfælde)

Prøv følgende:

cuedStrings.Add(new StringClass("123"));

if (cuedStrings.Contains(new StringClass("123")))
{
    MessageBox.Show("Det virker");
}

Som du vil se får du ingen "Det virker" besked...

Prøv så at tilføre følgende til StringClass:

public override bool Equals(object obj)
{
    if (obj == null || GetType() != obj.GetType()) return false;

    StringClass stringClass = obj as StringClass;

    return this.text.Equals(stringClass.text);
}

Kør dit eksempel igen, hvorefter en MessageBox vil skrive "Det Virker".
Avatar billede x-periment Nybegynder
20. januar 2006 - 11:10 #21
Først vil jeg gerne lige takke dig for din kæmpe tålodighed med mig...
Jeg har tjekket og fået det til at virker med at der ikke kommer duplikater i listen
mit problem er bare at datagrided kun viser den første streng i listen. og his listen bliver tom får jeg  fejlen DataGridview index out of range execption ...
Avatar billede bitsch Nybegynder
20. januar 2006 - 12:00 #22
Hvis du skal anvende løsningen med List<StringClass> som DataSource, så skal du kun binde denne, EFTER at du har adderet alle dine resultater til listen, og altså ikke som i din kode hvor du binder hver gang du adder et item!

Man kan godt assigne en tom List<T> til DataSource, men så kan den ikke efterfølgende tilskrives uden at få fejl. Man kan så snyde og vente med at binde sin liste indtil det første item er adderet. Derefter kan man addere efterfølgende:

List<StringClass> cuedStrings = new List<StringClass>();
            cuedStrings.Add(new StringClass("Test1"));
            this.dataGridView1.DataSource = cuedStrings;

            cuedStrings.Add(new StringClass("Test2"));
            cuedStrings.Add(new StringClass("Test3"));
            cuedStrings.Add(new StringClass("Test4"));

Men bemærk at valget af den rette løsning afhænger af dine datamængder. Er det et lille antal som blot skal visualiseres, kan du anvende List<T> løsningen (eller anden type af collection)
Er det større mængder, bør du klart overveje DataTable løsningen fordi du har mulighed for løbende at opdatere dit UI samtidig med at du indlæser data.

At du kun ser ét item må skyldes noget andet, som jeg ikke kan se ud fra den kodestump.
Avatar billede x-periment Nybegynder
21. januar 2006 - 23:13 #23
okay det nu gik roder jeg lidt videre med datatable løsning den første du kom med ... men hvis der er  3 element i datatable og jeg sletter det det jeg sletter nummer 2 for jeg en fejl om index 1 doesn't have a value ...
Avatar billede x-periment Nybegynder
21. januar 2006 - 23:36 #24
så selvom jeg gør dette får jeg fejlen cuedTrack.RemoveAt(0);
this.dataGridView1.DataSource = cuedTrack;
Avatar billede x-periment Nybegynder
21. januar 2006 - 23:43 #25
det virker hvis jeg bare altid sørger for at der ligger et tomt felt i row 0 (?)
Avatar billede bitsch Nybegynder
22. januar 2006 - 09:36 #26
Problemet med List<T> er at det ikke er bygget til at binde. Der findes dog en BindingList<T> som implementerer IBindingList. Denne kan du binde fint til din grid uden problemer.

            this.cuedStrings = new BindingList<StringClass>();

            this.dataGridView1.DataSource = this.cuedStrings;

            this.cuedStrings.Add(new StringClass("Test1"));
            this.cuedStrings.Add(new StringClass("Test2"));
            this.cuedStrings.Add(new StringClass("Test3"));


Men uansset hvad. Når du forsøger at slette ved at angive en index value, så bør du først checke om denne eksisterer. Hvis du stadig har problemer så må jeg se noget mere af din kode.
Avatar billede bitsch Nybegynder
22. januar 2006 - 09:38 #27
Du kan for øvrigt læse om BindingList<T> her:
http://msdn2.microsoft.com/en-us/library/ms132679.aspx
Avatar billede bitsch Nybegynder
22. januar 2006 - 09:42 #28
Desuden findes der også en desideret Queue<T> klasse som måske kan have din interesse. Desværre ser det ikke ud til at der er en BindingQueue, så der er man nødt til at lave sin egen som implementerer IBindingList.
Avatar billede x-periment Nybegynder
24. januar 2006 - 23:03 #29
kan du som en sidste ting lige fortælle mig hordan jeg sætter en fixed width på en DataColumn ? så hver gang der tilføjes en streng er kolonon 100 bred selv om strengen kun 10 tegn bred
Avatar billede x-periment Nybegynder
24. januar 2006 - 23:39 #30
det er bare sådan at størrelse af koloner i mit datagrid ikke ændre sig bare fordi der kommer en længere streng og eller hvis der bliver slettet en lang streng
Avatar billede bitsch Nybegynder
26. januar 2006 - 09:14 #31
Nu er du jo så heldig at du ved hvad din property på StringClass hedder, så løsningen er let.

Gå til designeren og tilfør en kolonne til din grid (eller kod det i hånden)
Kolonnen skal afspelje det som du ønsker at vise, og i dette tilfælde er det Text propertyen.
Så for at binde kolonnen til din StringClass.Text property skal du på kolonnen assigne DataPropertyName med værdien "Text".

Når du har lavet din kolonne kan du ændre et hav af visningsmåder. Du kan også give kolonnen en ny label etc.

Men i dette tilfælde skal du ændre den måde kolonnen resizes. Det gør du ved at vælge en af de muligheder som tilbydes på propertyen AutoSizeMode.
Du skal her vælge AllCells som medfører at kolonnen akkurat passer til din tekst.

Koden for kolonnen vil se ud som følger:
//
// ColumnText
//
this.ColumnText.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.AllCells;
this.ColumnText.DataPropertyName = "Text";
this.ColumnText.HeaderText = "Text";
this.ColumnText.Name = "ColumnText";
this.ColumnText.ReadOnly = true;
this.ColumnText.Width = 53;

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