Laden...

Wie kann ich im DataGridView alle Ergebnisse in eine Zeile einfügen (nicht in mehrere)?

Erstellt von MMazi vor 3 Jahren Letzter Beitrag vor 3 Jahren 1.672 Views
M
MMazi Themenstarter:in
45 Beiträge seit 2020
vor 3 Jahren
Wie kann ich im DataGridView alle Ergebnisse in eine Zeile einfügen (nicht in mehrere)?

Hallo alle zusammen.

ich schreibe eine Art Zeitefassungstool.mit Start, Ende und Dauer Button.

die Egebnisse solllen in die Tabellen von DataGridView eingetragen werden

soweit funktioniert und der Code berechnet alles so wie sein soll und die Ergebnisse werden auch eingetragen aber nicht jewels in eine Zeile.

was muss ich noch an Code ändern ?

Danke für eure Antworten


  using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Zeiterfassungstool
{
    public partial class Form1 : Form
    {

        //Globale Variabeln
        
        public DateTime startTime;
        public DateTime endTime;
        //public table.Rows.[0];
         

        public Form1()
        {
            InitializeComponent();
        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {

        }
//--------------------------------------START------------------------------------------------


        private void btnStart_Click(object sender, EventArgs e)
        {
            this.startTime = DateTime.Now;
            textBox1.Text = startTime.ToString();
            textBox2.Text = startTime.ToString();
            int n = dataGridView1.Rows.Add();
            dataGridView1.Rows[n].Cells[0].Value = textBox1.Text;

            //table.Rows.Add(newRow);
            //table.Rows[0]["Bemerkung"] = "";
        }
            
//--------------------------------------ENDE------------------------------------------------
            

        private void btnEnde_Click(object sender, EventArgs e)
        {
            




            this.endTime = DateTime.Now;
            textBox3.Text = endTime.ToString();
            int n = dataGridView1.Rows.Add();
            dataGridView1.Rows[n].Cells[1].Value = textBox3.Text;


            TimeSpan dauer;
            dauer = endTime.Subtract(startTime);
            int m = dataGridView1.Rows.Add();
            dataGridView1.Rows[m].Cells[2].Value = dauer.TotalHours.ToString("0.00");
D
161 Beiträge seit 2017
vor 3 Jahren

Nutz doch bitte die Code Tags.

[CSHARP][/CSHARP] (ohne *)

Nur für den Code, nicht für den ganzen Beitrag.

4.931 Beiträge seit 2008
vor 3 Jahren

Hallo und willkommen,

du fügst ja auch jedesmal mit dataGridView1.Rows.Add() eine neue Zeile hinzu (und trägst dann in dieser neuen Zeile den Wert ein).

M
MMazi Themenstarter:in
45 Beiträge seit 2020
vor 3 Jahren

Da Problematik ist, dass erst der Button Start gedruckt werden muss um den Startwert erstmal in Tabelle einzutragen. daher


this.startTime = DateTime.Now;
textBox1.Text = startTime.ToString();
textBox2.Text = startTime.ToString();
int n = dataGridView1.Rows.Add();
dataGridView1.Rows[n].Cells[0].Value = textBox1.Text;

dann nach dem, dass Startwert eingetragen ist kann ich der Ende Button drucken.


private void btnEnde_Click(object sender, EventArgs e)
        {
            




            this.endTime = DateTime.Now;
            textBox3.Text = endTime.ToString();
            int n = dataGridView1.Rows.Add();
            dataGridView1.Rows[n].Cells[1].Value = textBox3.Text;


            TimeSpan dauer;
            dauer = endTime.Subtract(startTime);
            int m = dataGridView1.Rows.Add();
            dataGridView1.Rows[m].Cells[2].Value = dauer.TotalHours.ToString("0.00");


wie könnte mann der

dataGridView1.Rows.Add() 

so umschreiben ,dass nur einmal angegeben wird ?

4.931 Beiträge seit 2008
vor 3 Jahren

Wenn du in der btnEnde_Click-Methode immer nur in die letzte Zeile etwas eintragen möchtest, dann benutze:


int n = dataGridView1.Rows.Count - 1;

M
MMazi Themenstarter:in
45 Beiträge seit 2020
vor 3 Jahren

Sehr gut, Dankeschön

F
10.010 Beiträge seit 2004
vor 3 Jahren

Oder Du machst es gleich richtig und frickelst die Daten nicht in das Control.

Benutze eine Datenklasse, die INotifyPropertyChanged implementierst, erstellst eine ObservableCollection und bindest diese an DataGridView.DataSource.

Macht laden und speichern viel einfacher und deutlich schneller.

M
MMazi Themenstarter:in
45 Beiträge seit 2020
vor 3 Jahren

Danke Fzelle , das hat auch ganz gut geklappt. Danke für die Antworten

C
14 Beiträge seit 2020
vor 3 Jahren

Oder Du machst es gleich richtig und frickelst die Daten nicht in das Control.

Benutze eine Datenklasse, die INotifyPropertyChanged implementierst, erstellst eine ObservableCollection und bindest diese an DataGridView.DataSource.

Macht laden und speichern viel einfacher und deutlich schneller.

Hallo, ich klinke mich mal dazwischen, habe mitgelesen und den Hinweis nachzuverziehen versucht.

Folgendes Beispiel habe ich da gefunden:

using System;  
using System.Collections.Generic;  
using System.ComponentModel;  
using System.Drawing;  
using System.Runtime.CompilerServices;  
using System.Windows.Forms;  

// Either change the following namespace to the name of your project,   
// or name your project with the following name when you create it.  
namespace TestNotifyPropertyChangedCS  
{  
    // This form demonstrates using a BindingSource to bind  
    // a list to a DataGridView control. The list does not  
    // raise change notifications. However the DemoCustomer type   
    // in the list does.  
    public partial class Form1 : Form  
    {  
        // This button causes the value of a list element to be changed.  
        private Button changeItemBtn = new Button();  

        // This DataGridView control displays the contents of the list.  
        private DataGridView customersDataGridView = new DataGridView();  

        // This BindingSource binds the list to the DataGridView control.  
        private BindingSource customersBindingSource = new BindingSource();  

        public Form1()  
        {  
            InitializeComponent();  

            // Set up the "Change Item" button.  
            this.changeItemBtn.Text = "Change Item";  
            this.changeItemBtn.Dock = DockStyle.Bottom;  
            this.changeItemBtn.Click +=  
                new EventHandler(changeItemBtn_Click);  
            this.Controls.Add(this.changeItemBtn);  

            // Set up the DataGridView.  
            customersDataGridView.Dock = DockStyle.Top;  
            this.Controls.Add(customersDataGridView);  

            this.Size = new Size(400, 200);  
        }  

        private void Form1_Load(object sender, EventArgs e)  
        {  
            // Create and populate the list of DemoCustomer objects  
            // which will supply data to the DataGridView.  
            BindingList<DemoCustomer> customerList = new BindingList<DemoCustomer>();  
            customerList.Add(DemoCustomer.CreateNewCustomer());  
            customerList.Add(DemoCustomer.CreateNewCustomer());  
            customerList.Add(DemoCustomer.CreateNewCustomer());  

            // Bind the list to the BindingSource.  
            this.customersBindingSource.DataSource = customerList;  

            // Attach the BindingSource to the DataGridView.  
            this.customersDataGridView.DataSource =  
                this.customersBindingSource;  

        }  

        // Change the value of the CompanyName property for the first   
        // item in the list when the "Change Item" button is clicked.  
        void changeItemBtn_Click(object sender, EventArgs e)  
        {  
            // Get a reference to the list from the BindingSource.  
            BindingList<DemoCustomer> customerList =  
                this.customersBindingSource.DataSource as BindingList<DemoCustomer>;  

            // Change the value of the CompanyName property for the   
            // first item in the list.  
            customerList[0].CustomerName = "Tailspin Toys";  
            customerList[0].PhoneNumber = "(708)555-0150";  
        }  

    }  

    // This is a simple customer class that   
    // implements the IPropertyChange interface.  
    public class DemoCustomer : INotifyPropertyChanged  
    {  
        // These fields hold the values for the public properties.  
        private Guid idValue = Guid.NewGuid();  
        private string customerNameValue = String.Empty;  
        private string phoneNumberValue = String.Empty;  

        public event PropertyChangedEventHandler PropertyChanged;  

        // This method is called by the Set accessor of each property.  
        // The CallerMemberName attribute that is applied to the optional propertyName  
        // parameter causes the property name of the caller to be substituted as an argument.  
        private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")  
        {  
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }  

        // The constructor is private to enforce the factory pattern.  
        private DemoCustomer()  
        {  
            customerNameValue = "Customer";  
            phoneNumberValue = "(312)555-0100";  
        }  

        // This is the public factory method.  
        public static DemoCustomer CreateNewCustomer()  
        {  
            return new DemoCustomer();  
        }  

        // This property represents an ID, suitable  
        // for use as a primary key in a database.  
        public Guid ID  
        {  
            get  
            {  
                return this.idValue;  
            }  
        }  

        public string CustomerName  
        {  
            get  
            {  
                return this.customerNameValue;  
            }  

            set  
            {  
                if (value != this.customerNameValue)  
                {  
                    this.customerNameValue = value;  
                    NotifyPropertyChanged();  
                }  
            }  
        }  

        public string PhoneNumber  
        {  
            get  
            {  
                return this.phoneNumberValue;  
            }  

            set  
            {  
                if (value != this.phoneNumberValue)  
                {  
                    this.phoneNumberValue = value;  
                    NotifyPropertyChanged();  
                }  
            }  
        }  
    }  
}

Ich muß nicht genau das machen was der Threadersteller geschrieben hat, aber das kann ja noch ein Feature werden das benutzt oder gebraucht werden kann. Es geht mir eher um die strukturelle Darstellungsweise des Programmcodes, bzw. um eine bessere Kapselung und im Zuge dessen übersichtlicher Code.

Im Moment arbeite ich grade an einer Darstellung die eine Mahnungsbearbeitung vereinfache soll. Dazu benötige ich zwei DataGrids.

Frage in Bezug auf oben genanntes Beispiel aus den Microsoft Docs ist momentan wie greife ich auf die Spaltennamen eines DataGrids welches ich im Code Designer erstellt und eingestellt habe auf die einzelnen Spalten mithilfe einer DataBindingSource bzgl. des aktuellen DataGrids zu?

Mit den Spaltennamen klappt es schonmal nicht.

Beispiel das nicht geht:

 p
rivate DemoCustomer(DataRow row) { // Daten bereitstellen pro Zeile
// DataGridViewName in Bindingsource from DataSource <====> DataTableRowColumn by Name from Database opt: manipulate it
            this.FirmaValue      = row["DR1_FIRMA"].ToString(); // springt in getter setter
            this.BezeichnungValue    = "MAHNUNGEN";
            this.KennungValue = "DI677DK";
            this.DatumValue = row["DR1_DATUM"].ToString();
            this.ErstUhrzeitValue = row["DR1_UHRZEIT"].ToString();
            this.DokumenteValue = row["DR1_OBJEKT"].ToString();
            // StatusValue = true;
            this.BearbeiterValue = PNR;
            this.ReorgDatumValue = row["DR1_DTREORG"].ToString();
        }

Ergebniß: Im Anhang

Gibts nicht.

F
10.010 Beiträge seit 2004
vor 3 Jahren

Du greifst gar nicht per Spaltennamen zu.
Die BindingSource hat ein Property Current, das auf den ausgewählten Datensatz zeigt.
Den musst du dann nach DemoCustomer casten und kannst hanz normal drauf zugreifen.


...
    public DemoCustomer SelectedCustomer
    {
        get { return customersBindingSource.Current as DemoCustomer; }
    }
...

DataRow gehört zu einer DataTable, die benutzt du nicht.

C
14 Beiträge seit 2020
vor 3 Jahren

DataRow gehört zu einer DataTable, die benutzt du nicht.

Ok, danke für den Hinweis werde ich testen.

Die row brauche ich da ich von einer Datenbank Tabelle die entsprechenden Werte zuweisen will.

Die Daten aus der Tabelle lade ich in eine DataTable über die ich dann iteriere.

Oder kann ich ein ResultSet geschickter auswerten und die Zeileninfos zuweisen in diesem Kontext?

Hinweis von Abt vor 3 Jahren

Keine Full Quotes
[Hinweis] Wie poste ich richtig?

Gibts nicht.

F
10.010 Beiträge seit 2004
vor 3 Jahren

Und warum benutzt du die DataTable überhaupt?
Und ResultSet ist VB6, sag lieber mal was du wirklich machen willst, bzw wie du das bisher machst.

C
14 Beiträge seit 2020
vor 3 Jahren

Und warum benutzt du die DataTable überhaupt?
Und ResultSet ist VB6, sag lieber mal was du wirklich machen willst, bzw wie du das bisher machst.

Die DataTable benutze ich da ich es schneller geht, die Tabelle von der ich lese hat 4GB, die Daten die ich filter haben dann noch ca. 2GB.

Ich erstelle eine Mahnungsdruck C# Form Anwendung, welche zwei DataGrids zum vereinfachten arbeiten bietet und darüberhinaus ein Druckprogramm triggert welches Serien PDFs erstellt, die dann über das DataGrid abrufbar sein sollen. Das Ganze soll halt super schnell gehen.

Es hat sich rausgestellt das DataTable und eine for Schleife viel schneller sind, als wenn ich das ResultSet direkt aus der ODBC-Connection auswerte. ResultSet heißt es auch in anderen Sprachen.

Ich möchte mein Code ein bischen mehr kapseln und strukturierter aufbauen, kann ich die Daten direkt in eine BindingSource aus der ODBC-Connection schreiben?

Und wie greife ich dann auf die Spalten zu die ich mit dem Code Editor erzeugt habe? Die Funktionalität im Code Editor möchte ich beibehalten..

Gibts nicht.

F
10.010 Beiträge seit 2004
vor 3 Jahren

Die DataTable ist ein riesiger Speicherfresser und definitiv langsmer als per DataReader die Daten entweder direkt zu materialisieren oder mit z.b. Dapper zu arbeiten.

Und warum ODBC? Gibt es für diese DB keinen vernünftigen ADO.NET Treiber?
ODBC ist sehr langsam und hat auch noch bei einigen anderen Sachen Probleme.

Eine Bindingsource hat keine eigene Datenhaltung, sie benutzt die übergebene Liste.

Und für das bessere Strukturieren schau dir evtl mal [Artikel] Drei-Schichten-Architektur an.

ResultSet heißt es auch in anderen Sprachen.

Mag sein, aber in C# und Dotnet gibt es halt bestimmte Begrifflichkeiten die hier garnicht oder anders als z.b. in Java bentzt werden.
Und wenn Du die "falschen" Begriffe benutzt, kann es eben zu missverständnissen führen.

C
14 Beiträge seit 2020
vor 3 Jahren

Diese using Direktive wird für die DB verwendet.

using IBM.Data.DB2.iSeries;

Wenn ich mir die Docs ansehe sind die Beispiele mit Bindingsource alle in Verbindung mit einer DataTable. Ok ich prüfe die Vorschläge.

Zu DataGrid und CodeEditor:

Ich greife doch normalerweise mit dem Spaltennamen und einem Iterator auf die Zellen bzw. Zeilen zu.

Wie kann ich in Verbindung mit einer BindingSource darauf zugreifen?

Macht es überhaupt Sinn eigene getter / setter zu verwenden?

Gibts nicht.

F
10.010 Beiträge seit 2004
vor 3 Jahren

Du benutzt DB2 von IBM, das ist zum Glück nicht ODBC.
Wieder ein Beispiel wie der falsche Begriff zu nachfragen führt.

Wenn ich mir die Docs ansehe sind die Beispiele mit Bindingsource alle in Verbindung mit einer DataTable. Ok ich prüfe die Vorschläge.

Das liegt aber eher daran, das WindowsForms und auch die BindingSource schon ca 15 Jahre von neueren Sachen abgelöst wurden.
In WPF ist databinding viel einfacher geworden ( wenn man MVVM erst einmal verstanden hat ).

Und DataTable und Co wurden durch leichtgewichtigere alternativen wie OR-Mapper abgelöst
( von mini Mappern wie Dapper , über z.b. Linq2DB bis hin zu EntityFramework ).

Wenn du über die BindingSource auf die aktuelle Zeile zugreifst ( wie oben schon gezeigt ),
hast Du direkt das Object/class das die Daten beinhaltet, und da greifst Du wie auf jedes andere Object auch zu.

87 Beiträge seit 2016
vor 3 Jahren

Hallo,

Diese using Direktive wird für die DB verwendet.
Zu DataGrid und CodeEditor:

Ich greife doch normalerweise mit dem Spaltennamen und einem Iterator auf die Zellen bzw. Zeilen zu.

Wenn sowieso alle Zeilen betroffen sind, kannst du doch gleich über die DataTable gehen. Das DataGrid zeigt die Daten bloß an.

glandorf

5.299 Beiträge seit 2008
vor 3 Jahren

Hi!
Ich arbeite ganz viel mit Datasets - typisierten allerdings. Ich finde, das hat deutliche Vorteile - zB ein an eine DataTable gebundenes DatagridView kann out-of-the-box nach beliebigen Spalten sortieren (bei vielen Datensätzen oft hilfreich).
(ORM - weiss ich garnet, ob die dann neue Abfragen auslösen müssen, oder wie man bei denen Sortierung umsetzt - jedenfalls nicht out-of-box)

Ich wundere mich, wenn du sagst:

Die DataTable benutze ich da ich es schneller geht, die Tabelle von der ich lese hat 4GB, die Daten die ich filter haben dann noch ca. 2GB. Du willst doch nicht etwa ein DatagridView anzeigen mit 2GB Daten?

Wie kann ich in Verbindung mit einer BindingSource darauf zugreifen? Beim typisierten Dataset brauchst du keine eigenen Datenklassen zu erstellen, das macht der Dataset-Designer.
auf eine typisierte Row greift man so zu:


        void changeSelectedCustomerBtn_Click(object sender, EventArgs e)
        {
            var rwCustomer = (CustomerRow)((DataRowView)customersBindingSource.Current).Row;// Get the current Customer from the BindingSource.  
            rwCustomer.CustomerName = "Tailspin Toys";
            rwCustomer.PhoneNumber = "(708)555-0150";
        }

        void changeFirstCustomerBtn_Click(object sender, EventArgs e)
        {
            var rwCustomer = (CustomerRow)((DataRowView)customersBindingSource[0]).Row;// Get the first Customer from the BindingSource.  
            rwCustomer.CustomerName = "Tailspin Toys";
            rwCustomer.PhoneNumber = "(708)555-0150";
        }

Mehr brauchts nicht - nichtmal Kommentare - wenn zB die Buttons korrekt benamt sind.
Sind sie aber bei dir nicht, und deine Kommentation ist scheints veraltet, und trifft unzutreffende Aussagen

Der frühe Apfel fängt den Wurm.

C
14 Beiträge seit 2020
vor 3 Jahren

Danke für die Erläuterungen, werden geprüft und ich gebe dann nochmal Feedback.

Anfangs wollte ich jeden einzelnen Datensatz der 2GB filtern und zu einem Kunden zusammenfassen, bzw. anzeigen lassen. Das hat sich aber erledigt, kann aber sein das es noch soweit kommt..:)

Ich schau einfach das ich das auf einen aktuellen Entwicklungsstand bringen kann.

Guten Rutsch, frohe Tage und schönes Neues.

Gibts nicht.

C
14 Beiträge seit 2020
vor 3 Jahren

Ich möchte einfach meine Code neu strukturieren damit alles übersichtlicher wird, da ich mit PHP viel OOP also mit Interfaces, abstrakten Klassen etc. und starker Kapselung gearbeitet habe, und sich rausgestellt hat das sich so der Code einfacher darstellen lässt und sich neue Möglichkeiten ergeben.

Klar ist C# jetzt eine komplett andere Entwicklung aber Kapselung über die vorhanden using Direktiven hinaus sollte schon möglich sein.

Gibts nicht.

16.806 Beiträge seit 2008
vor 3 Jahren

Erneut der Hinweis, bitte die Full Quotes zu unterlassen. Nicht notwendig, dass wir dauernd die Beiträge editieren müssen. Danke. [Hinweis] Wie poste ich richtig?

PHP mit C# zu vergleichen ist halt auch sehr schwierig.
Zum einen, weil Du nun von Web- auf Desktop-Entwicklung wechselst, die ohnhin anders ist (auch ASP.NET vs Desktop programmiert man "anders"); zum anderen weil PHP eben historisch eine untypisierte Sprache war (yaaay, Freiheit!!!!) und nun doch Types nachträglich unterstützt (nooo, zuviel Freiheit!!!!) und das eben anders umgesetzt wurde als in einer Sprache, die das schon von Beginn an im Design hatte.

C
14 Beiträge seit 2020
vor 3 Jahren

Nicht notwendig, dass wir dauernd die Beiträge editieren müssen. Danke.

>

------------------){gray}

PHP mit C# zu vergleichen ist halt auch sehr schwierig.
Zum einen, weil Du nun von Web- auf Desktop-Entwicklung wechselst, die ohnhin anders ist (auch ASP.NET vs Desktop programmiert man "anders"); zum anderen weil PHP eben historisch eine untypisierte Sprache war (yaaay, Freiheit!!!!) und nun doch Types nachträglich unterstützt (nooo, zuviel Freiheit!!!!) und das eben anders umgesetzt wurde als in einer Sprache, die das schon von Beginn an im Design hatte.

Ja, das ist alles richtig was du sagst. Mir geht es aber um OOP und das geht über alle Sprachen hinweg. Und auf dieser Ebene spielt Typisierung ob unterstützt oder nicht ja fast überhaupt keine Rolle.

Über die Drei Schichten Architektur bin ich mir bewußt, genau darum geht es mir ja.

Abstrakte Klassen, Interfaces, Konstruktoren gibt es in C# auch, nur ist es mittlerweile so einfach geworden das ja praktisch jeder ein Projekt erstellt und anfängt rumzunudeln bis es einigermaßen Sinn ergibt.

Mein Projekt hier wird noch größer und da will ich einfach eine Struktur reinbringen.

Deswegen meine Frage/n.

BTW: keine Ahnung was du mit Quotes meinst aber ich benutze die Funktionen die mir diese Editor Tool bietet. Und ja, ich bin auch noch in vielen anderen (Fach-) Foren unterwegs.

Gibts nicht.

5.657 Beiträge seit 2006
vor 3 Jahren

Siehe dazu der von Abt verlinkte Hinweis: [Hinweis] Wie poste ich richtig?

Punkt 2.3

Full Quotes (also das vollständige Wiederholen des/eines vorangegangenen Beitrags als Zitat) sind nicht erwünscht

Weeks of programming can save you hours of planning

C
14 Beiträge seit 2020
vor 3 Jahren

Achsooo 😃, ok ab jetzt, Danke für den Hinweis.

Gibts nicht.