DataGrid c#

  • WPF
  • .NET 5–6

Es gibt 22 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    Moin Leute ich hab mal ne frage ich lese eine Excel Tabelle aus die so aussieht:

    Lukas | 90% | 82 | 90 | 90
    Tobi | 80% | 82 | 92 | 68
    Daniel| 92% | 82 | 98 | 92
    Dennis | 100% | 100 | 100 | 100
    Patrick | 50% | 40 | 60 | 50

    Diese Daten möchte ich in ein Datagrid rein packen, wenn ich sie dann reingepackt hab will ich das sich das Datagrid sortiert das heißt die Höchste Prozentzahl nach oben und die zweit beste als zweites und so weiter...(von der zweiten Spalte halt)

    also wie man eine Excel datei ausliest weiß ich aber habe keine erfahrung mit datagrid

    so sieht bisher mein Datagrid aus... aber ich weiß nicht wie man das jetzt befühlt

    XML-Quellcode

    1. <Grid>
    2. <DataGrid ItemsSource="{Binding eingaben}" AutoGenerateColumns="False" ColumnWidth="*"
    3. CanUserAddRows="False" CanUserResizeColumns="False" CanUserDeleteRows="False" CanUserSortColumns="False" CanUserReorderColumns="False" CanUserResizeRows="False">
    4. <DataGrid.Columns>
    5. <DataGridTextColumn Header="Name" Binding="{Binding name}" IsReadOnly="True"/>
    6. <DataGridTextColumn Header="Prozent" Binding="{Binding prozent}" IsReadOnly="True"/>
    7. <DataGridTextColumn Header="Test 1" Binding="{Binding test1}" IsReadOnly="True"/>
    8. <DataGridTextColumn Header="Test 2" Binding="{Binding test2}" IsReadOnly="True"/>
    9. <DataGridTextColumn Header="Test 3" Binding="{Binding test3}" IsReadOnly="True"/>
    10. </DataGrid.Columns>
    11. </DataGrid>
    12. </Grid>


    okay hab das jetzt so das ich die werte erstmal in einer Text datei speicher und ich muss leider den namen selber als string schreiben nicht wundern warum ich die Excel datei so auslese aber das geht doch bestimmt einfacher das man die daten dierekt ins grid bekommt oder ?

    C#-Quellcode

    1. ​for (int sp = 4; sp< 10; sp++)
    2. {
    3. for (int a = excelStartRow; a <= excelEndRow; a++)
    4. {
    5. if (sp ==4)
    6. {
    7. var aExcel = sh.Cells[sp, a];
    8. //Reihe 4
    9. if (aExcel.Text == String.Empty)
    10. {
    11. double value = 0.0;
    12. reihe4.Add(value);
    13. }
    14. else
    15. {
    16. double value = Convert.ToDouble(aExcel.Value.ToString());
    17. reihe4.Add(value);
    18. }
    19. }
    20. if (sp == 5)
    21. {
    22. var aExcel = sh.Cells[sp, a];
    23. //Reihe 4
    24. if (aExcel.Text == String.Empty)
    25. {
    26. double value = 0.0;
    27. reihe5.Add(value);
    28. }
    29. else
    30. {
    31. double value = Convert.ToDouble(aExcel.Value.ToString());
    32. reihe5.Add(value);
    33. }
    34. }
    35. }
    36. }
    37. // StreamWriter Write Data
    38. StreamWriter sw = new StreamWriter(swpath);
    39. sw.WriteLine("name1" + reihe4[0].ToString()+ reihe4[1].ToString()+ reihe4[2].ToString());
    40. sw.WriteLine("name2" + reihe5[0].ToString() + reihe5[1].ToString() + reihe5[2].ToString());
    41. sw.Close();

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „MrLaTuNiX“ ()

    MrLaTuNiX schrieb:

    das man die daten dierekt ins grid bekommt
    naja - man bindet an ein geeignetess Viewmodel.
    Das kann ich in deim Code nicht erkennen. Eine Textdatei ist schoma überhaupt kein Viewmodel, aber ich sehe iwas vonwegen reihe5.Add(?) - aber was zum Kuckuck ist ein reihe5?

    Jedenfalls Sortieren geht, indem man an ein ListCollectionview bindet, dem man eine Sortierung verpasst.
    Aber das setzt natürlich ein VM voraus.
    Hallo

    Das Datagrid ist doch gebunden an "Eingaben". Was ist "Eingaben"?
    Welche Klasse liegt dem Binding zugrunde?

    In meiner Tutorialreihe findest du alles zu Thema Binding ICollectionView und vieles mehr. Schau dir das mal an.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    okay ich hab mein programm mal überarbeitet ich hab das jetzt mal so gemacht :


    C#-Quellcode

    1. public ObservableCollection<DataEntry> Entries { get; set; } = new ObservableCollection<DataEntry> { };
    2. public void ReadExcelData()
    3. {
    4. int actuallyday = DateTime.Now.Day; //Aktuellen Tag auslesen
    5. File.Copy(e_OEE, e_OEE_copy); //Kopiert die Excel Datai
    6. Application app = new Application(); //open file excel using microsoft dll
    7. Workbook wk = app.Workbooks.Open(e_OEE_copy); //open workbook
    8. Worksheet sh = wk.ActiveSheet; //get first sheet
    9. //get cell
    10. // Cells[unten/rechts] Example: [1,2] = B1
    11. int excelStartRow = 2;
    12. int excelSpätRow = 3;
    13. int excelEndRow = 4;
    14. int excelStartSpalte = 4;
    15. int excelEndSpalte = 29;
    16. // Die Aktuelle Frühsicht && Spätschicht && Nachtschicht am Aktuellen Tag durchlsesen
    17. for (int att = 1; att < actuallyday; att++)
    18. {
    19. excelStartRow += 3;
    20. excelSpätRow += 3;
    21. excelEndRow += 3;
    22. }
    23. for(int spalte = excelStartSpalte; spalte < excelEndSpalte;spalte++)
    24. {
    25. //OEE Früh
    26. var aExcel = sh.Cells[spalte, excelStartRow];
    27. if (aExcel.Text == String.Empty)
    28. {
    29. double value = 0.0;
    30. früh_oee.Add(value);
    31. }
    32. else
    33. {
    34. double value = Convert.ToDouble(aExcel.Value.ToString());
    35. früh_oee.Add(value);
    36. }
    37. //OEE Spät
    38. var sExcel = sh.Cells[spalte, excelSpätRow];
    39. if (sExcel.Text == String.Empty)
    40. {
    41. double value = 0.0;
    42. spät_oee.Add(value);
    43. }
    44. else
    45. {
    46. double value = Convert.ToDouble(sExcel.Value.ToString());
    47. spät_oee.Add(value);
    48. }
    49. //OEE Nacht
    50. var nExcel = sh.Cells[spalte, excelEndRow];
    51. if (nExcel.Text == String.Empty)
    52. {
    53. double value = 0.0;
    54. nacht_oee.Add(value);
    55. }
    56. else
    57. {
    58. double value = Convert.ToDouble(nExcel.Value.ToString());
    59. nacht_oee.Add(value);
    60. }
    61. }
    62. excelStartRow = 2;
    63. excelEndRow = 4;
    64. //Excel wieder schließen ohne zu speichern!
    65. app.DisplayAlerts = false;
    66. wk.Close(0);
    67. app.Quit();
    68. //Delete the excel copy
    69. File.Delete(e_OEE_copy);
    70. KillSpecificExcelFileProcess("");
    71. for (int i = 0; i <20;i++)
    72. {
    73. Entries.Add(new DataEntry { Früh= früh_oee[i],Spät= spät_oee[i], Nacht= nacht_oee[i] });
    74. }
    75. }


    dann meine Klasse :

    C#-Quellcode

    1. public class DataEntry : PropertyChangedBase
    2. {
    3. private double _früh;
    4. private double _spät;
    5. private double _nacht;
    6. public double Früh { get => _früh; set => SetProperty(ref _früh, value); }
    7. public double Spät { get => _spät; set => SetProperty(ref _spät, value); }
    8. public double Nacht { get => _nacht; set => SetProperty(ref _nacht, value); }
    9. }


    die andere Klasse

    C#-Quellcode

    1. public class PropertyChangedBase : INotifyPropertyChanged
    2. {
    3. public event PropertyChangedEventHandler PropertyChanged;
    4. protected void RaisePropertyChanged([CallerMemberName] string propName = null)
    5. {
    6. PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
    7. }
    8. protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propName = null)
    9. {
    10. if (EqualityComparer<T>.Default.Equals(value, storage))
    11. return false;
    12. storage = value;
    13. PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
    14. return true;
    15. }
    16. }


    so sieht mein XAml code aus :

    XML-Quellcode

    1. <Grid>
    2. <DataGrid ItemsSource="{Binding Entries}" AutoGenerateColumns="False" ColumnWidth="*"
    3. CanUserAddRows="False" CanUserResizeColumns="False" CanUserDeleteRows="False" CanUserSortColumns="False" CanUserReorderColumns="False" CanUserResizeRows="False">
    4. <DataGrid.Columns>
    5. <DataGridTextColumn Header="Test 1" Binding="{Binding Früh}" IsReadOnly="True"/>
    6. <DataGridTextColumn Header="Test 2" Binding="{Binding Spät}" IsReadOnly="True"/>
    7. <DataGridTextColumn Header="Test 3" Binding="{Binding Nacht}" IsReadOnly="True"/>
    8. </DataGrid.Columns>
    9. </DataGrid>
    10. </Grid>


    aber die Daten kommen nicht ins Grid was mache ich falsch und noch eine Sache schreibt mir ruhig alle fehler die hier gemacht hab... bringe es mir halt selber bei ...
    ich hab das mit der : ObservableCollection<Entry> Entries { get; set; } = new ObservableCollection<Entry> { }; Klasse gemacht weil ich das von einen anderen gesehen hab aber ich brauche wahrscheinlich keine ObservableCollection da ich ja nur double werte hab.
    hab den fehler gefunden mir hat das gefehlt : DataContext = this;

    so meine frage ist jetzt wie kann ich die Sortieren ? das sie absteigend in der Tabelle gezeigt werden von einer Spalte nur?

    Also eine Spalte nach den daten kontrollieren und die komplette reihe muss sich dann halt noch oben bewegegen oder nach unten so das dass so aussieht

    das lese ich
    Lukas | 90% | 82 | 90 | 90
    Tobi | 80% | 82 | 92 | 68
    Daniel| 92% | 82 | 98 | 92
    Dennis | 100% | 100 | 100 | 100
    Patrick | 50% | 40 | 60 | 50

    und so soll es dann bei mir aussehen
    Dennis | 100% | 100 | 100 | 100
    Daniel| 92% | 82 | 98 | 92
    Lukas | 90% | 82 | 90 | 90
    Tobi | 80% | 82 | 92 | 68
    Patrick | 50% | 40 | 60 | 50

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „MrLaTuNiX“ ()

    Indem du nicht an die OC bindest sondern an eine ICollectionView welche die OC als Source hat.

    C#-Quellcode

    1. private ICollectionView entriesView;
    2. public ICollectionView EntriesView
    3. {
    4. get { return entriesView};
    5. set { entriesView=value; RaisePropertyChanged();}
    6. }


    und im Constructor dann:

    C#-Quellcode

    1. EntriesView=CollectionViewSource.GetDefaultView(DEINE OC)
    2. EntriesView.SortDirections.Add(new SortDirection(„Früh“,ListSortDirection.Ascending“))


    Der Code ist vom Handy geschrieben, also nicht Copypastefähig.
    Rechtschreibfehler betonen den künstlerischen Charakter des Autors.
    also ich mach das grad so aber kriege es nicht hin meine klasse sieht jetzt so aus

    C#-Quellcode

    1. ​public class DataEntry : PropertyChangedBase
    2. {
    3. private string _workplace;
    4. private string _früh;
    5. private double _spät;
    6. private double _nacht;
    7. public string Workplace { get => _workplace; set => SetProperty(ref _workplace, value); }
    8. public string Früh { get => _früh; set => SetProperty(ref _früh, value); }
    9. public double Spät { get => _spät; set => SetProperty(ref _spät, value); }
    10. public double Nacht { get => _nacht; set => SetProperty(ref _nacht, value); }
    11. private ICollectionView entriesView;
    12. public ICollectionView EntriesView
    13. {
    14. get { return entriesView; }
    15. set { entriesView = value; RaisePropertyChanged(); }
    16. }
    17. }


    aber wie mache ich das beim eintrag ich kann ja nur eins machen ?

    C#-Quellcode

    1. Entries.Add(new DataEntry { Früh = früh_oee[i].ToString("P0"),Spät= spät_oee[i], Nacht= nacht_oee[i] ,
    2. EntriesView = CollectionViewSource.GetDefaultView(Entries)
    3. });
    Das muss alles in die Klasse wo auch die OC ist.
    DataEntry ist doch dein Model und Viewmodel in einem wenn ich das richtig sehe.
    wie arbeitest du eigentlich? Codebehind oder MVVM?
    Rechtschreibfehler betonen den künstlerischen Charakter des Autors.
    Wassn das??

    MrLaTuNiX schrieb:


    C#-Quellcode

    1. Entries.Add(new DataEntry { Früh = früh_oee[i].ToString("P0"),Spät= spät_oee[i], Nacht= nacht_oee[i] ,
    2. EntriesView = CollectionViewSource.GetDefaultView(Entries)
    3. });
    Kompiliert das?
    Ansonsten schau dir Akanels Post#7 nochma an, da isses doch richtig vorgemacht:

    Akanel schrieb:


    und im Constructor dann:

    C#-Quellcode

    1. EntriesView=CollectionViewSource.GetDefaultView(DEINE OC)
    2. EntriesView.SortDirections.Add(new SortDirection(„Früh“,ListSortDirection.Ascending“))
    @MrLaTuNiX: Weisst du nicht, was ein Constructor ist?

    Ich glaub nichtmal, dass man der CollectionView eine Sortierung zufügen muss. Wenn CollectionView zwischengeschaltet, dann braucht man glaub nur im DG auf den SpaltenHeader zu klicksen und sortiert.
    (Aber sicher bin ich nicht - lang nicht mehr Wpf gemacht)
    @Akanel ich arbeite mit Codebehind
    aber mein Problem ist wenn ich das so mache :

    C#-Quellcode

    1. public class DataEntry : PropertyChangedBase
    2. {
    3. private string _workplace;
    4. private string _früh;
    5. private double _spät;
    6. private double _nacht;
    7. public string Workplace { get => _workplace; set => SetProperty(ref _workplace, value); }
    8. public string Früh { get => _früh; set => SetProperty(ref _früh, value); }
    9. public double Spät { get => _spät; set => SetProperty(ref _spät, value); }
    10. public double Nacht { get => _nacht; set => SetProperty(ref _nacht, value); }
    11. private ICollectionView entriesView;
    12. public ICollectionView EntriesView
    13. {
    14. get { return entriesView; }
    15. set { entriesView = value; RaisePropertyChanged(); }
    16. }
    17. }


    und deins dahinpacke kriege ich ein ein fehler weil ich Entries in main hab

    weil in mein Main hab ich ja

    C#-Quellcode

    1. public ObservableCollection<DataEntry> Entries { get; set; } = new ObservableCollection<DataEntry> { };


    also laut mein verständnis muss ich ja dein Code also die zwei zeilen dort einfügen wo ich auch mein DataEntry eintrage für die Entrys richtig ?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „MrLaTuNiX“ ()

    ich sags noch einmal, und dann kommste auf die Ignore-Liste:
    Guck Akanels post#7 an, und befolge die Anweisung: "Und im Constructor dann:...".
    Bzw. versuch das zumindest.
    Inzwischen glaube ich immer mehr, dass du nicht weisst, was ein Constructor ist. Das ist ja nix schlimmes, und wäre auch leicht zu erklären - wenn du danach fragen tätest.
    Oder google "Konstruktor", oder am besten lies es in einem Buch nach.
    Ist wichtig.
    okay könntest du es mir erklären?
    Mein wissen nach ist ein Constructor das hier:

    C#-Quellcode

    1. ​public class DataEntry : PropertyChangedBase
    2. {
    3. private string _workplace;
    4. private string _früh;
    5. private double _spät;
    6. private double _nacht;
    7. public string Workplace { get => _workplace; set => SetProperty(ref _workplace, value); }
    8. public string Früh { get => _früh; set => SetProperty(ref _früh, value); }
    9. public double Spät { get => _spät; set => SetProperty(ref _spät, value); }
    10. public double Nacht { get => _nacht; set => SetProperty(ref _nacht, value); }
    11. private ICollectionView entriesView;
    12. public ICollectionView EntriesView
    13. {
    14. get { return entriesView; }
    15. set { entriesView = value; RaisePropertyChanged(); }
    16. }
    17. }


    oder bin ich da jetzt falsch ?
    @ErfinderDesRades
    Was du da zeigst ist eine Klasse, mit fünf Properties, aber ohne Constructor.

    Der Constructor ist eine besondere Methode in einer Klasse. Ihr Code wird einmalig ausgeführt, wann immer ein Objekt der Klasse mit dem Schlüsselwort new erstellt wird.
    In c# ist der Constructor eine Methode, die den Namen der Klasse selbst trägt, und bei der die Angabe des Datentyps fehlt.

    ---
    Dein Window1 müsste also so ungefähr aussehen:

    C#-Quellcode

    1. public class Window1 {
    2. private ObservableCollection<DataEntry> entries = new ObservableCollection<DataEntry>();
    3. private ListCollectionView entriesView;
    4. public Window1() { //Konstruktor: eine Methode, bei der kein Datentyp angegeben ist - auch nicht void
    5. InitializeComponents(); // glaub ich - hab grad kein Wpf zur Hand
    6. entriesView = (ListCollectionView)CollectionViewSource.GetDefaultView(entries); //Akanels Code (leicht modifiziert)
    7. entriesView.SortDescriptions.Add(new SortDescription("Früh", ListSortDirection.Ascending));
    8. }
    9. public ListCollectionView EntriesView => entriesView;
    10. }
    Aber lies dir Buch - meine Ausführungen sind unvollständig.
    ZB erwähne ich weder Überladung, noch Basisklassen, und einiges andere habich bestimmt auch noch vergessen.

    Dieser Beitrag wurde bereits 7 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Das ist eine Klasse mit Eigenschaften.
    Der Konstruktor ist normalerweise in der Klasse.
    Da du keinen Explizit erstellt hast wird der DefaultKonstruktor genommen. Das passiert im Hintergrund.
    Deiner würde so aussehen.

    C#-Quellcode

    1. public DataEntry()
    2. {
    3. }


    Mir scheint so als würden dir die Grundlagen für Klassen fehlen. Vllt sogar noch andere.

    Sorry ErfinderDesRades war schneller.
    Rechtschreibfehler betonen den künstlerischen Charakter des Autors.

    Akanel schrieb:

    ErfinderDesRades war schneller.
    HAHA! :D

    Und ich zeige sogar auf, dass du garnicht vom DataEntry-Konstruktor geschrieben hast, sondern vom Window1-Konstruktor.
    Also vom Konstruktor derjenigen Klasse, die im Xaml dann den DataContext darstellt (ist hier ja leider das Window selbst).

    Die DataEntry-Klasse braucht nämlich bislang keinen Konstruktor.
    Huch - die braucht auch nicht die EntriesView!

    Ein EntriesView enthält ja DataEntries - nicht umgekehrt!
    okay ich muss mir das mit denn Klassen nochmal viel genauer anschauen allerdings wusste ich sowas wie ListCollectionView zum beispiel auch garnicht


    okay was ich jetzt wirklich nicht verstehe ist wenn ich die Liste sortiere und die Werte in double sind macht er es richtig aber mache ich das in String plus("P0") damit die zahl gerundet wird macht er es nicht whyy?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „MrLaTuNiX“ ()

    Weil double ein ganz andere DatenTyp ist als string. Strings sind Zeichenfolgen und demnach wird das anders sortiert als du denkst.
    Datentypen solltest du dir auch noch genauer ansehen. Das ist fundamental wichtig, ebenso wie Klassen.
    Rechtschreibfehler betonen den künstlerischen Charakter des Autors.
    @Akanel Nein das ist mir schon klar das dass ein ganz andere Datentyp ist ....
    nur wie mache ich das dann weil wenn man die sortierfunktion macht :

    entriesView.SortDescriptions.Add(new SortDescription("Früh", ListSortDirection.Ascending));

    kann ich ja nur ein String eingeben von der Spalte aber wenn ich halt String werte hab die könnte man das dann machen das er die als Double werte sotiert ?

    ich kenne mich damit halt nicht aus hab auch noch nie was mit datagrid gemacht deswegen ...