Autor Beitrag
Talemantros
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 444
Erhaltene Danke: 2

Win7 Proff 64bit
C# (VS2013)
BeitragVerfasst: Sa 29.11.14 00:37 
Hallo,
es tut mir sehr leid, wenn ich jetzt anscheinend wieder dasselbe frage, aber ich komme einfach nicht klar und verzweifel gerade.

Ich hatte vor einiger Zeit zu meinem Testprojekt mal folgenden Threat gehabt
www.entwickler-ecke....ighlight=talemantros

Dann dachte ich es ist wie ich mir das vorstelle und hatte es aber nicht fertig gemacht, weil anders leichter wirkte.
Nun dachte ich ein Schritt weiter im Wissen zu sein und habe es wieder ausgegraben und komme kein Stück weiter.

Ich versuche es mal so gut wie möglich zu erklären und hoffe auf Hilfe.

Also ich habe folgende Modellklasse, die 3 Listen beinhaltet von anderen Modellklassen

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
    public class Customer
    {
        public Customer()
        {
            ListCostumerContact = new List<CustomerContact>();
            ListCostumerTP = new List<CustomerTP>();
            ListCostumerUnit = new List<CustomerUnit>();
        }
        
        public long Id { get; set; }
        public long CustomerId { get; set; }
        public string CompanyName { get; set; }
        public string InvoiceName { get; set; }
        public string Charge { get; set; }
        public string Street { get; set; }
        public string Postale { get; set; }
        public string City { get; set; }
        public int ChargeBegin { get; set; }
        public int ChargeEnd { get; set; }
        public int HasTp { get; set; }
        public int HastUnit { get; set; }
        public int Active { get; set; }
        public long? DocumentPath { get; set; }
        public List<CustomerContact> ListCostumerContact { get; set; }
        public List<CustomerTP> ListCostumerTP { get; set; }
        public List<CustomerUnit> ListCostumerUnit { get; set; }

        public bool IsValid
        {
            get
            {
                return !string.IsNullOrWhiteSpace(CompanyName) &&
                        !string.IsNullOrWhiteSpace(InvoiceName) &&
                        !string.IsNullOrWhiteSpace(Charge) &&
                        !string.IsNullOrWhiteSpace(Street) &&
                        !string.IsNullOrWhiteSpace(Postale) &&
                        !string.IsNullOrWhiteSpace(City) &&
                        DocumentPath.HasValue;
            }
        }

    }


Die anderen Klassen sind

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
    public class CustomerContact
    {
        private static long _costumerContactId = 1;

        public CustomerContact()
        {
            CostumerContactId = _costumerContactId;
            _costumerContactId++;
        }

        public long CostumerContactId { get; set; }
        public string Authority { get; set; }
        public string Name { get; set; }
        public string Email { get; set; }
        public string Number { get; set; }
        public string Mobil { get; set; }
        public string Fax { get; set; }
    }

    public class CustomerTP
    {
        private static long _customerTpId = 1;

        public CustomerTP()
        {
            CostumerTpId = _customerTpId;
            _customerTpId++;
        }

        public long CostumerTpId { get; set; }
        public string TP { get; set; }
    }

    public class CustomerUnit
    {
        private static long _customerUnitId = 1;

        public CustomerUnit()
        {
            CostumerUnitId = _customerUnitId;
            _customerUnitId++;
        }

        public long CostumerUnitId { get; set; }
        public string Unit { get; set; }
    }


Nun möchte ich zu meinen Kunden die Ansprechpartner erfassen können in dem UserControl siehe Anlage.
Die erfassten Ansprechpartner sollen in dem DataGridView angezeigt werden und später in die Datenbank geschrieben

An das DataGridView habe ich die Property ListCustomerContact gebunden bei DataSource des DatagridViews
Daraufhin hat Visual Studio selbstständig eine neue BindingSource generiert, die ich bsListCustomerContact genannt habe.

Und beim Start des UserControl erzeuge ich schon mal eine Instanz von CustomerContact. Wenn ich nun die Daten ausfülle für den Ansprechpartner, werden diese auch im Datagridview angezeigt. Demnach sollten SIe doch auch in der ListCustomerCOntact Property sein.

Wenn ich nun aber versuche diese wieder auszulesen, oder zu gucken ob schon ein Eintrag vorhanden ist funktioniert dies nicht.
Es wirkt so als sei ListCustomerContact leer, während die BindingSource aber Daten hat.

Ich bin der Meinung ich hatte dies schonmal am Laufen und ich komme einfach nicht da hinter.

Ich poste hier mal relevanten Code des UserControls und hoffe auf nicht zu kryptische Antworten :-(

Danke

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
        long employee = 0;
        Customer newCustomer = new Customer();

        public KundeNeuUserControl(long uebergabe)
        {
            InitializeComponent();
            employee = uebergabe;
        }

        private void KundeNeuUserControl_Load(object sender, EventArgs e)
        {
            bsCustomer.DataSource = newCustomer;
            bsListCustomerContact.DataSource = new CustomerContact();
            txtAnsprech.Select();

            try
            {
                cmbDocument.DataSource = CustomerMethods.GetAllForms();
                cmbDocument.DisplayMember = "name";
                cmbDocument.ValueMember = "vorlagengrundid";
                cmbDocument.SelectedIndex = -1;
            }
            catch (Exception ex)
            {
                MySqlError.SetError(ex.Message, this.ToString(), Global.GetCurrentFunctionName());
                MsgAusgabe.ShowError(ex.Message);
            }
        }


Und hiermit wollte ich es testen

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
        private void btnContactErfassen_Click(object sender, EventArgs e)
        {
            CustomerContact contact = bsListCustomerContact.Current as CustomerContact;
            
            //ZUm Test wollte ich mir die Namen mal ausgeben lassen
            foreach (CustomerContact customerContact in newCustomer.ListCostumerContact)
            {
                MsgAusgabe.ShowInformation(customerContact.Name.ToString());
            }
        }


Ich hoffe dies ist einigermaßen verständlich.

Gruß
Daniel
Einloggen, um Attachments anzusehen!
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Sa 29.11.14 10:43 
Hallo,

wenn du schon nicht durchsteigst, dann wird es für uns noch schwieriger. ;-)

Zu deinem Code:
ausblenden C#-Quelltext
1:
2:
bsCustomer.DataSource = newCustomer;
bsListCustomerContact.DataSource = new CustomerContact();

An welches Control ist jetzt welche BindingSource gebunden?
Und warum bindest du an die bsListCustomerContact ein neues einzelnes CustomerContact-Objekt?

Ich weiß nicht, ob du schon dieses Tutorial kennst: A Detailed Data Binding Tutorial ?

Ein etwas kürzeres Tutorial gibt es unter Data Binding in .NET / C# Windows Forms (vllt. ist das etwas verständlicher für dich - du mußt insbesondere bei der BindingSource den CurrencyManager verstehen, welcher die aktuelle Position innerhalb der gebundenen Datenliste verwaltet).

Am besten fängst du damit an, daß du schon mal Daten in deiner Customer.ListCostumerContact hinterlegst und dann ersteinmal diese Liste anzeigst und bei Wechsel der Selektion dann links im Fenster die Detailinformationen angezeigt werden.
Und erst wenn das einwandfrei funktioniert, dann solltest du dich mit dem Hinzufügen eines neuen Datensatzes beschäftigen (bzw. dem Löschen eines vorhandenen).

Im Abschnitt Hierarchical data binding wird auf das Anlegen neuer Datensätze eingegangen (beachte den Hinweis zu AllowNew).

Edit: Ich glaube jetzt deinen Gedankenfehler verstanden zu haben. Du versuchst bisher (aus dem Nichts) bei dem UserControl neue Datensätze anlegen zu wollen (mittels Speichern). Data Binding funktioniert aber andersherum, d.h. du mußt erst eine Liste (bzw. Objekt) haben, damit du deren Eigenschaften verändern kannst!!!

PS:
Talemantros hat folgendes geschrieben:
Ich hatte vor einiger Zeit zu meinem Testprojekt mal folgenden Threat gehabt
Bedroht haben wir uns noch nicht gefühlt ;-)

PPS: Der Titel sollte vllt. eher "Probleme mit Data Binding bei einer List<Modellklasse>" heißen.
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Sa 29.11.14 14:20 
Zitat:
An das DataGridView habe ich die Property ListCustomerContact gebunden bei DataSource des DatagridViews
Daraufhin hat Visual Studio selbstständig eine neue BindingSource generiert, die ich bsListCustomerContact genannt habe.


Die beiden BindingSourcen stehen in Beziehung. bsListCustomerContact.DataSource/DataMember verweist dann auf die ListCustomerContact Property des Objects in bsCustomer.
Durch bsListCustomerContact.DataSource = new CustomerContact(); machst du diese Beziehung aber kaputt. Zumindest diese Zeile muss also weg. Mal davon abgesehen das du dort wohl eher auch eine Liste von CustomerContact und nicht nur ein einzelnes Object wolltest.

Wenn du solche strukturierten Modelle hast die du binden willst ist es üblicherweise am geschicktesten so vorzugehen wie es der Designer auch macht die Wurzel Modelklasse an eine BindingSource hängen (bsCustomer) für die weiteren Elemente ListCostumerContact, ListCostumerTP, ListCostumerUnit dann entsprechende weitere BindingSourcen erzeugen die über die DataSource/DataMember Property zu bsCustomer in Beziehung stehen und sich entsprechend updaten wenn sich das Object in bsCustomer ändert.

Nebenbei empfinde ich es auch merkwürdig ein KundeNeuUser Control zu haben (insbesondere wenn das zu bearbeitende Objekt Customer heißt und intern auch mal Employee genannt wird :shock: ). Hast du auch ein KundeEditUserControl? Ein Control sollte eher ein dummes Ding sein da geht was rein und da kommt am Ende was raus. Bei einer TextBox geht Text rein und es kommt Text raus. Egal was das für ein Text ist ober ob er neu oder alt oder was auch immer ist. Das würde ich auch bei UserControls versuchen durchzuhalten. Insofern würde ich erwarten das du zum erstellen und bearbeiten nur 1 UserControl hast dem das zu bearbeitende Customer Object übergeben wird. Ob das neu erzeugt oder eins zum bearbeiten aus irgendeiner Quelle ist sollte dem UserControl egal sein. Es ist nur relevant für den Nutzer des UserControls.
Talemantros Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 444
Erhaltene Danke: 2

Win7 Proff 64bit
C# (VS2013)
BeitragVerfasst: Sa 29.11.14 16:13 
Danke.
Ich lese mir nachher alles in Ruhe durch inkl. der Tutorials und melde mich dann wieder.

Gruß
Daniel
Talemantros Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 444
Erhaltene Danke: 2

Win7 Proff 64bit
C# (VS2013)
BeitragVerfasst: So 30.11.14 23:00 
Hallo,
also neuer Versuch neues Glück :-)

Durch die Tutorials arbeite ich mich noch.
Muss die glaube noch 2-3 x lesen...
Ich versuche mich aber schon einmal daran und hoffe auf eure Geduld.

Was ich jetzt erstmal gemacht habe:
Da ich wirklich dachte ich benötige für jede Aufgabe ein eigenes UserControl hatte ich tatsächlich noch ein "KundeEditUserControl" in Planung.
Für andere Aufgaben hatte ich dies auch schon so umgesetzt. Werde ich aber dem Hinweis folgend noch ändern.

Ich habe nun folgende Modellklasse


ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
    public class Customer
    {
        public Customer()
        {
            ListCostumerContact = new List<CustomerContact>();
        }
        
        public long Id { get; set; }
        public long CustomerId { get; set; }
        public string CompanyName { get; set; }
        public string InvoiceName { get; set; }
        public string Charge { get; set; }
        public string Street { get; set; }
        public string Postale { get; set; }
        public string City { get; set; }
        public int ChargeBegin { get; set; }
        public int ChargeEnd { get; set; }
        public int HasTp { get; set; }
        public int HastUnit { get; set; }
        public int Active { get; set; }
        public long? DocumentPath { get; set; }
        public List<CustomerContact> ListCostumerContact { get; set; }
    }


Bei der Modellklasse CustomerContact habe ich nun den Konstruktor verändert.

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
    public class CustomerContact
    {
        private static long _costumerContactId = 1;

        public CustomerContact(string authority, string name, string email, string number, string mobil, string fax)
        {
            CostumerContactId = _costumerContactId;
            _costumerContactId++;

            Authority = authority;
            Name = name;
            Email = email;
            Number = number;
            Mobil = mobil;
            Fax = fax;
        }

        public long CostumerContactId { get; set; }
        public string Authority { get; set; }
        public string Name { get; set; }
        public string Email { get; set; }
        public string Number { get; set; }
        public string Mobil { get; set; }
        public string Fax { get; set; }
    }


Im UserControl generiere ich eine neue Instanz der Modellklasse (employee steht hier für etwas anders)

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
    public partial class KundeUserControl : UserControl
    {
        long employee = 0;
        Customer newCustomer = new Customer();

        public KundeUserControl(long uebergabe)
        {
            InitializeComponent();
            employee = uebergabe;
        }

        private void KundeNeuUserControl_Load(object sender, EventArgs e)
        {
            bsCustomer.DataSource = newCustomer;
            txtAnsprech.Select();
        }


Die anderen Properties der Modellklasse sind an Controls im UserForm gebunden.
Nun habe ich eine neue BindingSource hinzugefügt, die ich "bsCustomerContact" genannt habe.

Die Eigenschaft dieser neuen BindingSource habe ich wie folge geändert.

DataSource auf die bsCustomer gesetzt.
DataMember auf die Property ListCustomerContact
AllowNew auf True

Dann habe ich die Eigenschaft DataSource des DataGridViews an die neue "bsCustomerContact" gebunden.
Daraufhin erschienen im DataGridView die Properties als Spalten zur Entwicklungszeit.

Nun wollte ich die Liste füllen.
Gedacht, war es so, dass der User die Textfelder füllt und dann den Button Speichern drückt.

Die Liste füllen wollte ich nun mit folgendem Code analog zu dem neuen Kontruktor der Modellklasse
ausblenden C#-Quelltext
1:
2:
3:
4:
        private void btnContactErfassen_Click(object sender, EventArgs e)
        {
            newCustomer.ListCostumerContact.Add(new CustomerContact(txtZustaendig.Text, txtAnsprech.Text, txtEmail.Text, txtFestNetz.Text, txtMobil.Text, txtFestNetz.Text));
        }


Leider werden die dadurch erfasstem Daten zwar in der Liste gespeichert, aber nicht über das DataGrid an dem die BindingSource hängt, angezeigt.

Wenn ich mir die Liste zum Test ausgeben lasse sind die Daten anscheinend schon mal richtig drin

ausblenden C#-Quelltext
1:
2:
3:
4:
            foreach (CustomerContact customerContact in newCustomer.ListCostumerContact)
            {
                MsgBox.MsgAusgabe.ShowInformation(customerContact.Authority.ToString());
            }


Ich bin auf eure Kommentare gespannt. Hoffe ich habe wenigstens grob die richtige Richtung.

Tausend Dank

Gruß
Daniel

Edit:

MIt folgendem Code kann ich sowohl die ListCustomerContact auslesen als auch in dem DataGridView anzeigen

Statt

ausblenden C#-Quelltext
1:
2:
            
newCustomer.ListCostumerContact.Add(new CustomerContact(txtZustaendig.Text, txtAnsprech.Text, txtEmail.Text, txtFestNetz.Text, txtMobil.Text, txtFestNetz.Text));


diesen hier:

ausblenden C#-Quelltext
1:
            bsCustomerContact.Add(new CustomerContact(txtZustaendig.Text, txtAnsprech.Text, txtEmail.Text, txtFestNetz.Text, txtMobil.Text, txtFestNetz.Text));					


Jetzt schaue ich mal weiter, wegen leeren der txtFelder und bin dennoch gespannt, ob ihr mir einen anderen Weg empfehlt.
Einloggen, um Attachments anzusehen!
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: So 30.11.14 23:47 
Zitat:
bsCustomerContact.Add(new CustomerContact(txtZustaendig.Text, txtAnsprech.Text, txtEmail.Text, txtFestNetz.Text, txtMobil.Text, txtFestNetz.Text));


Sieht irgendwie falsch aus.

Ich denke mal du hast für Contacts auch ein UserControl das DataBinding benutzt? Dem übergibst du einen Contact und von dem bekommst du einen bearbeiteten Contact zurück. Voraussichtlich wird das bsCustomerContact.Current den du an das UserControl hängst. Und ein neuer Contact wäre dann einfach ein neues CustomerContact Object mit irgendwelchen Defaults das du der Liste zuweist und dann Current der BindingSource so setzt das dieses neue Object das aktuelle ist. Wenn du Probleme hast die verschiedenen gebundenen Controls zu synchronisieren ändere mal List<T> in BindingList<T>. BindingList<T> bringt ein wenig mehr Intelligenz bezüglich DataBinding mit.
Talemantros Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 444
Erhaltene Danke: 2

Win7 Proff 64bit
C# (VS2013)
BeitragVerfasst: Mo 01.12.14 10:22 
Guten Morgen,
also dass Modul soll so aufgebaut sein, dass man einen neuen Kunden anlegen kann.
Im Ersten Tab, die Stammdaten und dann wenn man diese erfasst hat, soll man zu diesem neu anlegten Kunden die Ansprechpartner erfassen.
Die Stammdaten nutzen die Modellklasse Customer und die Felder sind über DataBinding angebunden. Diese kann ich auch sauber in die Datenbank speichern.

Ich habe mal 2 Bilder in der Anlage eingefügt.

Leider ist mir durch den letzten Eintrag noch nicht ganz klar, ob ich völlig falsch liege und wenn ja in welche Richtung und wie es zu ändern wäre um am Ende ein anständiges Modul mit DataBinding zu haben.
Einloggen, um Attachments anzusehen!
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mo 01.12.14 14:22 
Zitat:
Leider ist mir durch den letzten Eintrag noch nicht ganz klar, ob ich völlig falsch liege und wenn ja in welche Richtung und wie es zu ändern wäre um am Ende ein anständiges Modul mit DataBinding zu haben.


Das kann auch nicht sagen ob du falsch liegst.Mir ist nur aufgefallen das du von Databinding sprichst, eine BindingSource benutzt aber dort ein CustomerContact Object hinzufügst für das du die Daten selbst aus den Controls geklaubt hast. Und das sieht nunmal falsch aus weil das eben nicht Databinding ist sondern eher selbstgemacht. Zumindest für CustomerContact.

Von deinem Screenshot her (der 2.te) würde ich sagen das das Ding wo Ansprechpartner drübersteht auch ein eigenes Usercontrol ist an das ein CustomerContact gebunden wird.
So stelle ich mir das zumindest vor. Da macht aber der 'neu' Button keinen großen Sinn mehr denn das UserControl soll nicht wissen ob das Ding was er bekommt neu ist oder nur bearbeitet werden soll. Es bekommt eben je nach Context nur ein entsprechendes Objekt untergejubelt. Genauso wie das löschen für mich nicht zum Grid gehört. Neu und löschen als Contextmenü auf das Grid oder die Buttons neben speichern (genauso wie ein abbrechen für den Fall das man gerade bearbeitet und das Unsinn ist).
Talemantros Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 444
Erhaltene Danke: 2

Win7 Proff 64bit
C# (VS2013)
BeitragVerfasst: Mo 01.12.14 22:38 
Hallo,
also irgendwie fühle ich mich wie der erste Mensch, der versucht dem User die Möglichkeit zu geben nach dem Ausfüllen der TextBoxen diese in einem List zwischenzu speichern und danach in eine Datenbank zu schreiben.

Irgendwie komme ich so nicht zu Rande. Könnten ihr mir mit ein wenig Code helfen? Vielleicht verstehe ich es dann?!

Also läge ich besser, wenn ich die TextBoxen an das DataBinding der BindingSource packe.
Dann einen Button Neu beim DataGridView habe der bsCustomerContact.Add(new CustomerContact());.
Wenn die Textfelder dann ausgefült werden, werden die Daten auch gleich im DataGridView angezeigt und wenn ich eine Zeile markiere, werden die Daten dort zum BEarbeiten angezeigt.

Wenn jemand eine Zeile erfasst hat und eine neue brauch drückt er wieder auf "Neu" würde eine neue Zeile bekommen in dem ich die Position auf das neue Objekt verschiebe?!

Eher so?!

Gruß
Daniel
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Di 02.12.14 00:06 
Ich hab mal ein Beispiel angehängt da mir die Worte ausgehen das zu erklären. Vielleicht kannst du dir das was du wissen willst da raus ziehen.
Einloggen, um Attachments anzusehen!
Talemantros Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 444
Erhaltene Danke: 2

Win7 Proff 64bit
C# (VS2013)
BeitragVerfasst: Mi 03.12.14 10:33 
Hallo,
vielen Dank für dein Beispielprojekt.
Ich habe mir das schon mal zu Gemüte geführt und hoffe ich bin ein wenig weiter im Kopf.
Werde ich heute mal antesten.

Folgende Fragen stellen sich mir aber noch:

1.) Du hattest in einem Post gesagt, du würdest auch ein Abbrechen Button machen. Wäre das dann auch nur ein löschen, der aktuellen Einträge? Oder gibt's für Abbrechen noch einen anderen Weg.
2.) In diesem Fall macht es wenig Sinn, aber für die Zukunft. Wie könnte ich verhindern, dass doppelte eingetragen werden? Also während der Eingabe bzw nach der Validierung?!
3.) Wenn jemand mehrmals auf Neu drückt, kommen neue Zeilen, die er vielleicht nicht ausfüllt, würde ich die nicht in die Datenbank schreiben wollen. Beim Speichern dann einfach prüfen auf Ungleich string.empty oder so ?!

Danke vielmals

Gruß
Daniel
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mi 03.12.14 11:26 
Zitat:
1.) Du hattest in einem Post gesagt, du würdest auch ein Abbrechen Button machen. Wäre das dann auch nur ein löschen, der aktuellen Einträge? Oder gibt's für Abbrechen noch einen anderen Weg.


Da kommt es drauf an wie granular du abbrechen willst und auf was sich abbrechen beziehen soll. Im Beispiel bin ich davon ausgegangen das ein Customer (zusammen mit seinen Contacts etc.) die kleinste speicherbare Einheit ist. Wenn du es feiner steuern willst Also z.b. Contacts zum Customer unabhängig vom Customer, wo du dann so Probleme lösen mußt das es den Customer vielleicht noch gar nicht in der DB gibt. Oder du das Hinzufügen eines Contacts zum Customer abbrechen möchtest, also etwas abbrechen das sich erstmal auf das Andern des Modells bezieht und noch nicht auf die DB was dann ansatzweise in Richtung eines Undo/Redo Patterns geht. Erst wenn du/wir wissen was abbrechbar sein soll kann man da einen Weg vorschlagen.

Zitat:
2.) Wie könnte ich verhindern, dass doppelte eingetragen werden? Also während der Eingabe bzw nach der Validierung?!


Definiere für deine Objekte was einen doppelten Eintrag auszeichnet und setzte einen entsprechenden Unique Index auf der Datenbank. Da was im Code zu basteln ist eher hoffnungslos. Würde nur funktionieren wenn du alle User durch eine gemeinsame Schicht jagst, also du irgendeine Form von Applikationsserver hast. Wenn es nur Clients und die Datenbank gibt mach es über Indexe in der Datenbank.

Zitat:
3.) Wenn jemand mehrmals auf Neu drückt, kommen neue Zeilen, die er vielleicht nicht ausfüllt, würde ich die nicht in die Datenbank schreiben wollen. Beim Speichern dann einfach prüfen auf Ungleich string.empty oder so ?!


Hast du nicht eh einen Validitätscheck (IsValid) in deinen Modellobjekten? Vor dem Speichern die durchgehen und prüfen. Wenn da was unvollständig ist dem User melden und der kann dann entscheiden ob er das betroffene Objekt löscht oder vervollständigt.
Talemantros Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 444
Erhaltene Danke: 2

Win7 Proff 64bit
C# (VS2013)
BeitragVerfasst: Mi 03.12.14 13:15 
Hallo,
also Abbrechen würde ich meinen, dass man das Hinzufügen eines Contacts zu einem Customer abbrechen kann. Ich gucke mal, was ich zu Undo/Redo finde.

Bei den doppelten Einträgen wird es glaube kniffliger (also für mich).
Wenn ich 2 Kunden habe. Könnte jeder einen Teilprozess "TP1" haben, aber nur einer pro Kunde. Wenn ich nun die Datenbank auf Unique stelle, könnte ich ja nur noch für einen Kunde einen solchen Teilprozess erfassen. Glaube dies müsste ich im Code erledigen, dass man es erst gar nicht dem Modell hinzufügen kann.

Die Klasse Customer hat eine Validierung.
Die Klasse CustomerContact bisher nicht

Würde ich dann wie folgt ändern

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
    public class CustomerContact
    {
        private static long _costumerContactId = 1;

        public CustomerContact()
        {
            CostumerContactId = _costumerContactId;
            _costumerContactId++;
        }

        public long CostumerContactId { get; set; }
        public string Authority { get; set; }
        public string Name { get; set; }
        public string Email { get; set; }
        public string Number { get; set; }
        public string Mobil { get; set; }
        public string Fax { get; set; }

        public bool IsValid
        {
            get
            {
                return !string.IsNullOrWhiteSpace(Name);
            }
        }
    }


Müsste dann irgendwie in der Foreach das prüfen!?

Passt das so?

Gruß
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mi 03.12.14 13:38 
Zitat:
Wenn ich nun die Datenbank auf Unique stelle, könnte ich ja nur noch für einen Kunde einen solchen Teilprozess erfassen.


Wenn dein Teilprozesse zu einem Kunden gehören hast du den Kunden sicher als Fremdschlüssel mit in der Tabelle (die CustomerId oder so) der gehört dann auch zum Index.

Zitat:
Müsste dann irgendwie in der Foreach das prüfen!?


Welcher foreach?

Die IsValid Methode von Customer sollte sicherlich die IsValid Methode der untergeordneten Objekte aufrufen und mitprüfen (Ein Customer mit ungültigem Contact ist ein ungültiger Customer) ob und wie du die einzeln von außen auch nochmal prüfst hängt davon ab was du willst. Reicht dir zu Wissen das Objekt ist ungültig (Customer) oder möchtest du das Objekt innerhalb von Customer Wissen das ungültig ist (Customer, Contact, Teilprozess etc.) oder möchtest du Wissen welche Property eines Objects ungültig ist (dann hilft dir IsValid nicht)?
Talemantros Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 444
Erhaltene Danke: 2

Win7 Proff 64bit
C# (VS2013)
BeitragVerfasst: Do 04.12.14 11:14 
Hallo,
die Fremdschlüssel in der Tabelle sind gesetzt.
Das mit Unique hat aber beim ersten Test nicht funtkioniert. Da schaue ich aber nochmal drüber. Danke für den Tip

Mit der ForEach war ein Gedankenfehler meinerseits.
Sorry :-) Manchmal bin ich zu voreilig.

Es funktioniert nun wie ich mir das vorstelle.
Als nächstes kommt bearbeiten eines Kunden.

Mal gucken, ob ich die Daten aus der Datenbank auch wieder anständig in die Liste bekomme :-)

Danke

Gruß
Daniel
Talemantros Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 444
Erhaltene Danke: 2

Win7 Proff 64bit
C# (VS2013)
BeitragVerfasst: Mi 10.12.14 16:54 
Hallo zusammen,
ich habe gerade einen Knoten im Kopf.
Die hier im Post gespeicherten Daten aus CustomerContact möchte ich nun wieder laden, damit sie wenn sie einer bearbeiten möchte wieder angezeigt werden.
Bekomme es aber nicht hin :-(

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
        public static List<CustomerContact> GetListCustomerContact(long uebergabe)
        {
            List<CustomerContact> myList = new List<CustomerContact>();
            strSQL = "Select * from kundekontakt where kundeid=?kundeid";

            using (MySqlConnection conn = new MySqlConnection(connStr))
            {
                using (MySqlCommand cmd = new MySqlCommand(strSQL, conn))
                {
                    conn.Open();

                    cmd.Parameters.AddWithValue("?kundeid", uebergabe);

                    MySqlDataReader dr = cmd.ExecuteReader();

                    while (dr.Read())
                    {
                        myList.Add(new CustomerContact());
                    }

                    conn.Close();
                }
            }

            return myList;
        }


So habe ich es probieren wollen.
Aber irgendwie weiß ich gerade nicht, wie ich die Daten aus der SQL Abfrage in die Klasse bei myList.add bekomme :-(
Also zum Beispiel das Feld dr.getstring("Ansprechpartner) und dr.getstring("email").

Könnt ihr mir bitte weiter helfen?

Danke

Gruß
Daniel
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mi 10.12.14 17:01 
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
while (dr.Read())
{
   var contact = new CustomerContact();
   contact.Ansprechpartner = dr.getstring("Ansprechpartner");
   // u.s.w.
   myList.Add(contact);
}
Talemantros Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 444
Erhaltene Danke: 2

Win7 Proff 64bit
C# (VS2013)
BeitragVerfasst: Mi 10.12.14 17:05 
Oh mann,
na klar :-(

Hatte jetzt noch

ausblenden C#-Quelltext
1:
                        myList.Add(new CustomerContact() { CostumerContactId = dr.GetInt64("kundekontaktid"), Authority = dr.GetString("zustaendig")  });					


testen wollen..

Danke
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mi 10.12.14 17:11 
Geht natürlich genauso. Nur eine Frage der Lesbarkeit die du für dich beantworten mußt.
Talemantros Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 444
Erhaltene Danke: 2

Win7 Proff 64bit
C# (VS2013)
BeitragVerfasst: Mi 10.12.14 22:34 
Ok
Danke

Meine Version war eine der ersten Google Ergebnisse

Deine finde ich besser.

Gruß