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
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von ChookaC am .
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.
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..
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.
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.
Du benutzt DB2 von IBM, das ist zum Glück nicht ODBC.
Wieder ein Beispiel wie der falsche Begriff zu nachfragen führt.
Zitat
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.
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:
Zitat von ChookaC
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?
Zitat
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
Dieser Beitrag wurde 4 mal editiert, zum letzten Mal von ErfinderDesRades am .
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.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von ChookaC am .
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.
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.
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.
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.