Hallo,
ich habe leider keine Antwort zu diesem Thema gefunden, deshalb frage ich hier einmal nach.
Ich möchte selber eine generische List von List ableiten, diese soll um ein paar spezielle Methoden erweitert werden.
Beim ableiten von List wird allerdings ein Typ verlangt, aber das möchte ich ja nicht weil auch meine Klasse generisch sein soll.
Kann mir jemand sagen wie das geht, bzw. ob es überhaupt möglich ist?
Also ich würde ein UserControl und eine TabPage entwerfen.
Das UserControl kannst du im Designer zusammenklicken.
Dann musst du das UserControl nur noch deiner TabPage-Klasse
hinzufügen und fertig.
Damit sparst du dir einerseits viel Schreibarbeit, wenn du die
TabPage händisch erstellst und andererseits musst du das
UserControl nicht immer wieder händisch deiner TabPage
zuweisen.
Hallo alle,
ich suche dringend eine Klasse, die den Export von Überweisungen in eine DTAUS-Datei macht. Da ich momentan sehr unter Zeitdruck stehe, frage ich lieber hier mal, bevor ich eine Klasse selber schreiben muss.
Viele Grüße
Roland
@herbivore:
Ich habe dieses Konstrukt schon mehrmals verwendet und es funktioniert einwandfrei, mit Refresh wird auf jedenfall das Control aktualisiert.
Das einzige was passieren kann ist, wenn du Refresh sehr oft in sehr kurzen Intervallen aufrufst, dann kann das Control anfangen zu flackern.
Das muss man dann ausprobieren.
Das kommt darauf an welches DBMS du verwendest.
Bei MySQL gibt es z.Bsp. den SQL-Befehl LIMIT index, count
Du führst also dein Statement wie normal aus, sortierst die Ausgabe auch im SQL und hängst dann die Beschränkung hinten dran.
Eine Ähnliche Syntax gibt es auch für andere DBMS, da musst du halt nur in die Doku schauen.
Hast du schon mal BeginEdit und EndEdit weggelassen?
Diese Methoden benötigst du gar nicht bei einem Delete.
Oder kürzer:
object result = cmd.ExecuteScalar();
ExecuteScalar liefert den Inhalt der ersten Spalte des ersten Datensatzes.
Dann sollte das doch eigentlich recht einfach klappen!
Schreibe dir eine statische Methode die die Anzeige und Berechnung übernimmt und füge dem Formular eine Eigenschaft (ArrayList) hinzu, die du an dein Control bindest.
Wie soll das ganze jetzt aussehen?
public class MyForm : System.Windows.Forms.Form
{
// Hier nur die statische Methode, den Rest kannst du dir ja denken.
public void AnzeigenUndBerechnen(string path)
{
MyForm form = new MyForm();
form.Show();
// Datei öffnen
ArrayList lines = ... // Datei in eine ArrayList füllen
// Für jede Zeile die Berechnung durchführen und das Formular aktualisieren
foreach (string line in lines)
{
// Berechnung durchführen
string calculatedLine = ... // Berechnung durchführen
form.List.Add(calculatedLine);
form.Refresh();
}
}
}
Das müsste dann eigentlich funktionieren.
Viele Grüße
Roland
Du kannst doch bestimmt den Typ des Datensatzes identifizieren, dann brauchst du nur noch die entsprechende Konfigurationsdatei einlesen. Um das ganze natürlich wieder voll dynamsich zu halten und if bzw. switch Bedingungen zu vermeiden, nennst du die Konfigurationsdateien einfach so, wie der Typ des Datensatzes ist. Damit hast du eine Abhängigkeit entworfen die dynamisch ohne Änderung des Sourcecodes funktioniert.
Bitte poste doch mal den genauen Text der Fehlermeldung. Denn es sollte ohne weiteres möglich sein mehrere Controls an einen DataSource zu binden.
Ich vermute eher, das das Objekt welches gebunden wird Probleme damit hat.
Du kannst praktisch fast alles von Parametern abhängig machen. Doch sollten die Definitionen wie Typ, Position, Größe usw. nicht in derselben Xml-Datei stehen, wo auch die Daten enthalten sind. Speichere dafür lieber zwei Xml-Dateien, eine für die Daten und eine für die Konfiguration des Forms.
Ich kann weder deine Gedanken lesen noch habe ich deinen Quellcode geklaut! 🙂
Meine Lösung resultiert aus der logischen Konsequenz deiner Aussage, das du ein
Control gleich zwei mal anzeigen willst. Wo macht das schon Sinn, wenn nicht in
zwei TabPages oder sonstigen verdeckten Controls. 😉
Das heisst du willst die selbe Instanz eines Control in zwei verschiedenen Panels
anzeigen? Das geht meiner Meinung nach nicht gleichzeitig, da ein Control nur
einem Parant haben kann. Aber du kannst ja ein wenig tricksen! 🙂
Wenn du z. Bsp. TabPages benutzt, dann kannst du ja beim aktivieres der TabPage schnell das Control hinzufügen.
Sonst fällt mir da auf die schnelle nichts ein!
Also ich würde den Type lieber direkt in die Xml-Definition schreiben.
Also anstatt 1 für TextBox schreibst du System.Windows.Forms.TextBox.
Das spart in deinem Parser die Entscheidung was für ein Control du denn
jetzt erzeugen musst. Du nimmst einfach den String und erzeugst mit dem
Activator das Control, danach setzt du die Parameter wie Position, Größe,
Font, Farben, eventuell sogar DataBinding wenn nötig. Somit kannst du
praktisch jedes Control direkt über Xml definieren.
Dann ist der Weg den herbivore vorgeschlagen hat goldrichtig.
So wie ich das verstehe sind in der Xml Datei alle Informationen enthalten um die Controls für einen bestimmten Datensatztyp zu instanziieren. Du musst nur die Xml Datei parsen, die Controls on the fly erstellen und sie dem Formular hinzufügen. Wenn du sogar den Controltyp in der Xml-Datei stehen hast, dann kannst du dir das Control mit dem Activator erstellen.
Viele Grüße
Roland
P.S. Da fällt mir aber noch ein, du sagst das alle Datensätze ähnlich sind. Dann kannst du dir auch ein Form schreiben indem alle Controls enthalten sind, die auch in jedem Datensatz vorkommen und dann mittels Vererbung die speziellen Forms erstellen. So hast du zwar wieder mehrere Forms, die sind aber schneller entwickelt und du musst nicht so viel Aufwand betreiben.
Ja du hast Recht, es laufen zwei Threads. Auch wenn das Beispiel einwandfrei funktioniert ist es doch ein Fehler es so zu machen. Ich bin dir nicht böse, ein wenig Kritik kann ich schon verkraften. 🙂
Ich weis auch das man aus einem Thread nicht direkt auf Controls zugreifen sollte. Doch in diesem Falle wird nur ein Thread ausgeführt und dann geht das auch einwandfrei. Ausserdem war das ja auch nur ein schnelles Beispiel wie man einen Thread aufruft.
Hallo,
ich habe dir mal ein kleines Beispiel gepostet, wie du das ganze mit einem Thread realisieren könntest.
private void Form1_Load(object sender, System.EventArgs e)
{
Thread thread = new Thread(new ThreadStart(FillLines));
thread.Start();
}
private void FillLines()
{
string[] strings = new string[1000000];
for (int i = 0; i < strings.Length; i++)
{
strings[i] = "Dies ist die Zeil Nr.: " + i.ToString();
}
this.textBox1.Lines = strings;
}
Hierbei wird zuerst das Form angezeigt und anschliessend die TextBox gefüllt.
Hallo!
DataTable hat keine RowFilter-Eigenschaft, die findest du in DataView.
Und diese Eigenschaft wird folgendermassen gesetzt:
dv.RowFilter = "ItemName LIKE 'product*'";
Das hat mich eine Minute in der Doku lesen gekostet. Einfach RowFilter im Index angeben und schon bekommst du alles was nötig ist.
Ob du ein Form oder ein UserControl implementierst ist wirklich egal. Es ist der gleiche Aufwand. Deshalb möchte ich dir noch einen Tipp mit auf dem Weg geben.
Implementiere zwei Interface Methoden und das UserControl.
Die erste Methode ShowControl(ScrollableControl theControl) ist wie oben beschrieben mit dem ScollableControl Parameter versehen.
Die zwei Methode z.Bsp. ShowDialog() ruft intern ShowControl auf und übergibt einfach eine neue Instanz eines Forms welches du on the fly instanziierst.
Somit bist du ganz frei und hast sehr wenig Aufwand.
Hier ein Code-Schnipsel zum Verständnis:
class MyAddOn : IAddOn
{
public void ShowControl(ScrollableControl theControl)
{
theControl.Controls.Add(new MyAddOnControl());
}
public void ShowDialog()
{
Form form = new Form();
form.FormBorderStyle = FormBorderStyle.FixedDialog;
form.Size = new Size(400, 300);
form.StartPosition = FormStartPosition.CenterScreen;
this.ShowControl(form);
form.ShowDialog();
}
}
Hi,
also ich würde der Methode ein Argument vom Typ ScrollableControl mitgeben und für jedes AddOn ein UserControl entwerfen welches im ScrollableControl dann angezeigt wird. Damit ist es egal, ob du ein Form, ein Panel oder eine TabPage mitgibst. Das gilt natürlich für alle von ScrollableControl abgeleiteten Klassen.
In deiner Methode kannst du dann ja überprüfen ob das ScrollableControl auch auf Scrollable eingestellt ist.
Viele Grüße
Roland
panel.Controls.Clear();
YourControl yourControl = new YourUserControl();
// yourControl initialisieren
panel.Controls.Add(yourControl);
Du könntest das Enum als statisch deklarieren und über den Klassennamen drauf zugreifen.
Oder du definierst die Enums ausserhalb der Klasse.
Klar gibt es da Namespaces, die sind aber nicht im .NET Framework enthalten, dafür muss man schon spezielle Assemblies einbinden.
Er möchte doch eine MySQL-Server ansprechen, da wird SqlCommand aus dem Namespace System.Data.SqlClient nicht so gut funktionieren, da dies eine Komponente für den MSSQL-Server ist.
Es gibt verschiedene Komponenten im Netz die du dafür verwenden kannst. Google mal danach.
Ja, oder so...,
mir ist Keys nicht mehr eingefallen! 🙂
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode.ToString() == "Enter")
{
// Do something...
}
}
Mist, da war ich wohl zu langsam.
Könntest du in diesem Fall nicht einfach ein Label verwenden und dabei den Rahmen und die Hintergrundfarbe setzen, so das es aussieht wie eine TextBox?
Dann kann dir keiner den Text herauskopieren.
Original von taaz
Hat sich erledigt, danke.Wollte nämlich direkt in einer if-Anweisung abbrechen.
Da hab ich dann den rest des Codes einfach in einen else-Anweisungblick gesetzt und fertig.Taaz
Du hättest auch einfach nur mit return die Methode verlassen können.
Sorry, aber dein Ansatz ist in der Tat falsch!
Was ich meinte, ist das du dir eine DAL aufbaust in der die gesamte Kommunikation mit der Datenbank stattfindet.
Deine Anwendung arbeitet aber nur mit der abstrakten Schicht, so das du später einfach nur eine andere spezielle DAL instanziieren musst um mit einem anderen DBMS zu kommunizieren.
Nochmal ein anderes klitzekleines Beispiel zur Verdeutlichung. In diesem Fall gehe ich aber mit Absicht mal einen etwas anderen Weg.
Du hast eine Tabelle Adressen in deiner DB die du verwalten willst.
Für den Zugriff baust du dir nun eine abstrakte (DBMS unabhängige) DAL-Klasse,
die nur die Methoden zur Verfügung stellt, die du in deiner Anwendung benötigst.
public abstract class DAL
{
public abstract void Load(DataSet dataSet);
public abstract void Save(DataSet dataSet);
}
Dann baust du dir eine spezielle (DBMS abhängige) DAL-Klasse.
public class OleDbDAL : DAL
{
private OleDbConnection _conn;
private OleDbDataAdapter _data;
public OleDbDAL()
{
_conn = new OleDbConnection("ConnectionString");
OleDbCommand cmd = new OleDbCommand("SELECT * FROM Adressen", _conn);
_data = new OleDbDataAdapter(cmd);
// weitere Command für Insert, Update, Delete erzeugen
...
}
public void Load(DataSet dataSet)
{
_data.Fill(dataSet);
}
public void Save(DataSet dataSet)
{
_data.Update(dataSet);
}
}
Deine Anwendung arbeitet nur mit deiner DAL.
public class App
{
[STAThread]
static void Main()
{
DAL dal = new OleDbDAL();
DataSet dataSet = new DataSet();
dal.Load(dataSet);
// Daten bearbeiten...
dal.Save(dataSet);
}
}
Das kommt darauf an wann du dir sicher bist das die Bearbeitung zu Ende ist!
Wenn du z.Bsp. den Datensatz speichern willst, wenn der Button "Speichern" gedrückt wurde, dann sieht das folgendermassen aus:
private void button1_Click(object sender, System.EventArgs e)
{
this.BindingContext[this.dataSource].EndCurrentEdit();
this.dataAdapter.Update(this.dataSet);
}
Hallo,
du kannst dir doch eine abstrakte Klasse stricken, die Methoden für das Speichern
und Laden von Daten übernimmt.
Diese Klasse leitest du dann ab, um eine spezielle Db anzusprechen.
Ein klitzekleines Beispiel, schliesslich sollst du daraus ja lernen und nicht abpinnen.
🙂
public abstract class DbLayer
{
public abstract IDbCommand GetCommand();
}
public class OleDbLayer : DbLayer
{
private OleDbConnection _conn = null;
public OleDbLayer()
{
_conn = new OleDbConnection("Dein connection String");
}
public IDbCommand GetCommand()
{
OleDbCommand cmd = _conn.CreateCommand();
cmd.CommandText = "SELECT feld FROM tabelle";
return cmd;
}
}
Du wendest es an, sobald du sicher bist, das die Bearbeitung zu Ende ist.
Dies geschieht in der Regel kurz vorm Speichern der Daten in der DB.
Z.Bsp.
Du hast ein Formular welches Daten eines Datensatzes einliesst und sie per
DataBinding in den zuständigen Controls anzeigt.
Jetzt soll beim Schliessen des Formulares die Daten gespeichert werden.
Dafür reagierst du dann auf das Closing() Ereignis des Forms und
rufst BindingContext[dataSource].EndCurrentEdit() auf.
Danach führst du
dann die Update Methode deinen DataAdapters aus.
Hallo, auf die schnelle kann ich dir nur sagen das du auf
BindingContext[].PositionChanged regieren kannst und
dann fragst, ob die aktuelle Row neu ist.
Du kannst es auch mit ExecuteScalar machen.
object result = cmd.ExecuteScalar();
Damit steht in der Variablen result der Wert den das SQL Statement zurückgibt.
Hallo, ich nehme mal Anschluss an die Antwort von herbivore.
Das Form sollte eine MyClass-Instanz besitzen.
Deine UserControls solltest du einfach um eine Methode erweitern, die
Values an ein Objekt vom Typ MyClass anhängt, das im Parameter
übergeben wird.
Z.Bsp. so:
public class MyUserControl : UserControl
{
public void AddValues(MyClass myClass)
{
myClass.AddValue(textBox1.Text);
myClass.AddValue(textBox2.Text);
}
}
Somit hast du auch eine saubere Trennung und benötigst eigentlich keine weiteren Events.
Wenn es sich um Daten aus einer Tabelle handelt geht das eigentlich recht einfach.
Am besten schaust du mal in die Hilfe unter DataAdapter, da ist eigentlich alles sehr gut beschrieben und du findest auch Beispiele.
Vorausgesetzt, das die DataRows des Status Neu haben, kannst du einen DataAdapter benutzer der dir dann die Daten in die Tabelle schreibt.
Alternativ kannst du dir auch ein Command mit entsprechdem SQL erstellen und dann mit foreach jede DataRow durchgehen, die Parameter setzen und den Command ausführen.
Eine andere Möglichkeit sehe ich da nicht.
Hi,
also wenn du immer die gleiche TabPage mit den selben Controls benötigst, dann solltest du lieber eine TabPage ableiten, dies mit den Controls befüllen und alle initialisierungen in der neuen TabPage vornehmen. Damit du dann die Controls später noch von aussen beeinflussen kannst (falls gewünscht), dann stellst du einfach ein paar Eigenschaften nach aussen zur Verfügung.
Hier mal ein Beispiel welches ich auch verwendet habe:
public class GridTabPage : TabPage
{
private DataGrid dataGrid;
public DataGrid DataGrid
{
get{return this.dataGrid;}
}
public GridTabPage()
{
this.dataGrid = new DataGrid();
... // Hier initialisieren
this.Controls.Add(this.dataGrid);
}
}
public class GridTabControl : TabControl
{
public GridTabControl()
{
}
public GridTabPage CreateTabPage()
{
GridTabPage gtp = new GridTabPage();
this.TabPages.Add(gtp);
return gtp;
}
}
// Wenn du dieses TabControl einsetzt, musst du nur noch
this.GridTabControl.CreateTabPage();
// aufrufen um eine neue TabPage zu erstellen.
Damit verlagerst du den Code aus deinem Formular heraus und hast gleichzeitig eine neue Komponente erschaffen die du in anderen Forms einsetzen kannst, ohne wieder denselben Code programmieren zu müssen.
Du musst die Persistenten Klassen nicht rauswerfen, du kannst sie einfach mit dem Attribut NonPersistent markieren um sie aus der Persistenz auszuschliessen.
Wo ich dir Recht gebe, ist bei dem Problem eine bereits exitierende Klasse aus einer anderen Assembly zu persistieren. Das geht leider nicht so einfach.
Zum Glück habe ich das bis jetzt noch nie benötigt! 🙂
Ansonsten muss mal Wohl oder Übel eine Mapper-Klasse für das Form bauen.
Es muss doch nur die Urklasse von XPObject erben, z.Bsp. so:
[NonPersistent]
public abstract class BusinessObject : XPObject
{
...
}
public class Company : BusinessObject
{
[Size(100)]
public string Name;
[Association("CompanyEmployees", typeof(Employee), Aggregated]
public XPCollection Employees
{
get{GetCollection("Employees");}
}
...
}
[NonPersistent]
public abstract class Person : BusinessObject
{
public string Vorname;
public string Nachname;
...
}
public class Employee : Person
{
[Association("CompanyEmployees")]
public Company Company;
...
}
Man benutzt doch die Attribute um die Persistenz zu kontrollieren.
Original von Syks
@ roland:ich bin gerade dabei mir .net einzuverleiben stosse mich aber immer
an dem immensen zeitaufwand für entwicklungen mit datenbanken,
vielleicht sollt ich sagen das immo auf delphi7 arbeite 🙂
= Query - Dataset - Grid
ein simples und schnelles systemdu sprichst oben systeme an welche meinst du zb?
gibt es vergleichbares in .net? (vorallem wenn partialDataloading ne rolle spielt)tnx for help 🙂
Hi, ich komme auch ursprünglich von der Delphi-Fraktion. 🙂
Muss aber sagen, das wenn man sich mal mit .NET und C# auskennt, die Entwicklung nicht langsamer ist als in Delphi, dafür aber um einiges flexibler.
In diesem Thread handelt es sich um Komponenten die Relationale Daten mit Klassen mappen. Man benutzt in der Applikation dann keine Datensätze mehr, sondern nur noch Objekte (Mal abgesehen das DataRow auch ein Objekt ist).
Und warum sollte deine Fachklasse nicht von XPObject erben?
[NonPersistent]
public class Fachklasse : XPObject
{
// Fachklasse initialisieren...
}
public class Contact : Fachklasse
{
public string FirstName;
public string LastName;
public string PhoneNumber;
public string Email;
}
Mit dem Attribute NonPersistent schaltest du die Persistenz für diese Klasse ab, damit keine Tabelle explizit für diese Klasse erstellt wird. So werden alle Informationen aus der Fachklasse in der Tabelle Contact gespeichert.
Ich frage mich halt wieso man die Fachklassen nicht von XPObject ableiten sollte und dann noch zusätzlich Interfaces für weitere Funktionen benutzt.
Vielleicht verstehe ich dich nicht richtig, aber man kann doch eine komplette Vererbungshirarchie mit den PersistentObjects aufbauen. Das sind dann doch die (BusinessObjects) Fachklassen in der Applikation.
Ich werde mir mal andere Frameworks ansehen, damit ich verstehe was du genau meinst.
Dem kann ich nicht ganz zustimmen, denn du kannst deine Datensätze nun ganz easy mit deinen Fachlichen Informationen und Funktionen spicken.
Meine Entwicklungszeit für DbApps hat sich seitdem halbiert. Also ich bin davon begeistert und setze nichts anderes mehr ein.
Aber es steht ja jedem frei nach seinem Geschmack zu wählen! 🙂
Hallo c#pler,
hat jemand von euch schon Erfahrungen mit den PersistentObjects von DevExpress gemacht?
Ich setze diese Komponenten seit einiger Zeit ein und bin hellauf begeistert. Teilt jemand die selbe Meinung mit mir?
Übrigens die anderen Komponenten sind auch richtig gut, da lohnt sich nicht mehr noch eigene zu entwickeln.
Viele Grüße
roland
Dieser Artikel klingt interessant, es ist eigentlich so ähnlich wie ich mir das vorgestellt hatte. Allerdinge glaube ich das hier Probleme mit der Performance auftauchen werden. Deshalb habe ich mich dazu entschieden doch lieber ArrayLists und Collections zu verwenden.