Laden...

Von Klasse auf Form zugreifen

Erstellt von gelöschtem Konto vor einem Jahr Letzter Beitrag vor einem Jahr 866 Views
Gelöschter Account
vor einem Jahr
Von Klasse auf Form zugreifen

Hi zusammen.

Ich habe da mal ein Problem für euch.

Folgende Problemstellung. Ich habe eine Form, halt so wie sie sein soll, mit Statusbar. So weit, so unspektakulär.
Jetzt habe ich eine Klasse, mit der ich eine CSV-Datei einlesen will. Diese CSV-Datei kann auch in einzelnen Zeilen fehlerhaft sein. Auch das ist kein Problem.

Nun möchte ich aber, dass die Klasse zum Einlesen der CSV halt zählt, wie viele Zeilen fehlerhaft waren und dies soll und der Statusbar während des Einlesens als Zahl sichtbar werden. Also habe ich eine integer variable ErrorCount erstellt, die bei jeder negativen Prüfung, ob es eine gültige Zeile ist halt hoch zählt.

Diese Zahl möchte ich im Falle eines Errors dann sofort, also beim Auftreten, in der Statusbar anzeigen.

Und ich wollte das dann per Event/Delegate lösen. Also das irgendwo in der Statusbar das Label so aussieht:


        private void OnErrorOccured(object sender, EventArgs e)
        {
            tsSLErrors.Text = $"Einlesefehler: {e.ErrorCount}";
        }

Allerdings verstehe ich das mit Events und Delegate offensichtlich nicht so ganz und auch mit EventArgs usw. Ich habe da schon zig Beschreibungen und Tutorials gefunden im Internet, aber keins funktioniert so richtig. Die meisten beziehen sich auch auf Senden von einer Form an eine andere Form. Gut, eine Form ist auch nur eine Klasse, aber irgendwie habe ich es nicht hinbekommen, dies an meine Bedürfnisse anzupassen.

Ich würde ja gerne hier reinstellen, was ich bisher gemacht habe. Allerdings würde da eh keiner mehr etwas erkennen, weil 1000-mal geändert und ausprobiert.

Nun zur eigentlichen Frage.

Kan nmir irgendjemand, mit wirklichen einfachen Worten und Beschreibungen, erklären, wie das mit Events, EventArgs und Delegates funktioniert, einmal in meiner CSV-Klasse und das Binding in die Form? Vielleicht dann auch so, dass ich verstehe wie es funktioniert wie man mehrere Eventargs hinzufügt, denn erweiterbar ist ein Projekt ja immer. Vielleicht noch "eingelesene Zeilen" oder so? Wäre dann ja wohl ein anderes EventArg, zumindest so wie ich es bisher verstanden habe.

4.942 Beiträge seit 2008
vor einem Jahr

Hallo und willkommen,

schau in [FAQ] Eigenen Event definieren / Information zu Events (Ereignis/Ereignisse).
Oder auch detailliert in meinem Artikel Kommunikation von 2 Forms (in "Lösung: Verwendung von Eigenschaften (Properties) und Ereignissen (Events) / 2. Ereignisse" - die SubForm entspricht dabei dann deiner Klasse).

Gelöschter Account
vor einem Jahr

Also der letzte Link ist ja das was ich schon meinte, von Form an Form.

Und der erste Link ist ja auch recht chaotisch. Nicht sehr schön zu lesen, wenn man es erlernen möchte. Mal ist es mit Args, mal empfohlen, mal nicht empfohlen, mal ohne Args, empfohlen, nicht empfohlen und immer wieder sind es Ausschnitte die auf irgendeinen vorherigen Code aufbauen.

Die habe ich logischerweise ja auch schon durch. Zum Teil ist es auch die schriftliche Version von dem, was ich schon als Videotutorial gesehen habe.

Aber es hilft jemandem, der sich damit nicht so auskennt, nicht unbedingt dazu bei weniger verwirrt zu sein, eher im Gegenteil. Das mag vielleicht auch dem geschuldet sein, dass sich im Laufe der Zeit so einiges geändert hat, aber es wäre schön, wenn es mal ein komplettes Beispiel gäbe, welches nicht im Laufe der Zeit zig mal angepasst wurde, sondern eben halt, wo man gleich sehen kann wie sowas aufgebaut ist, mit Args, Events, Delegates usw.

Deswegen sieht mein Code ja so aus, wie er derzeit aussieht, eben halt, weil ich solche Ergänzungen immer wieder ausprobiert habe.

4.942 Beiträge seit 2008
vor einem Jahr

Dann zeige mal deinen Code in deiner CSV-Klasse, wie du das Ereignis dort definierst und aufrufst.

PS: Fertigen C&P-Code für Events wirst du nicht finden, da dieser immer an die eigenen Bedürfnisse angepaßt werden muß (insb. die EventArgs).
Und wie du schon erkannt hast, ist eine Form auch nur eine Klasse, daher kann hierfür der Code aus meinem Artikel genauso übernommen werden (mit entsprechender Namensänderung und Anpassung der EventArgs).

Gelöschter Account
vor einem Jahr

Na um fertigen C&P Code geht es ja nicht. Ich werde es ja so oder so immer an mein Projekt anpassen müssen. Und das ist halt auch gar nicht das Problem. Ich benutze C# zwar nur sporadisch, aber ein wenig weiß ich halt trotzdem. Nur Events und Delegates, und natürlich auch die Fachbegriffe, machen mir natürlich Schwierigkeiten.

Aber hier halt mal das, was ich bisher in der Eventklasse gemacht habe. Allerdings, wie schon geschrieben, unter Vorbehalt, weil ich halt recht viel gelöscht, hinzugeschrieben und umbenannt habe, weil ich, bevor ich mich entschlossen habe, meine Frage mal hier reinzusetzen, gerade dabei war noch einmal was Neues zu probieren.


    public event ErrorOccured(int errorCount);
    public class CSVErrorCount : EventArgs
    {
        public int errorCount;

        public static event EventHandler<CSVErrorCount> ErrorCountOccured;
        public CSVErrorCount() { }
        public CSVErrorCount(int ErrorCount)
        {
            errorCount = ErrorCount;
        }

        protected virtual void OnErrorCount( CSVErrorCount error )
        {
            ErrorCountOccured?.Invoke(this, error);
        }

        public void SendErrorCount(int intErrorCount )
        {
            OnErrorCount(new CSVErrorCount(intErrorCount))
        }
    }

Ich dachte halt auch daran, eine Eventklasse zu erstellen und diese dann in die Form und die CSV-Klasse einzubinden. Von wegen, dass ich da auch mal ein wenig Struktur und Übersicht reinbekomme und nicht immer alles zerschieße, wenn ich etwas ändern oder hinzufügen will. Aber vielleicht erkennst du ja trotzdem ungefähr, worauf ich hinaus will. Weil wie ich es letztendlich in die Form implementieren will, habe ich oben ja schon geschrieben.

4.942 Beiträge seit 2008
vor einem Jahr

So hast du ein bißchen zuviel in die eigene EventArgs-Klasse gepackt.

Die EventHandler-Variable (aber ohne static !) sowie die beiden Methoden gehören in die CSV-Klasse (und die Form-Klasse abonniert dann dieses Event, da sie ja die CSV-Klasse kennt).
Und dann entspricht dies genau dem Beispiel in meinem Artikel.

Der Member event ErrorOccured(...) ist hier außerdem überflüssig (und dürfte so auch gar nicht kompilieren).

Gelöschter Account
vor einem Jahr

Wie gesagt, die Klasse war gerade in Arbeit. Natürlich kompiliert sie nicht.

EventArgs hatte ich auch gerade aus einem anderen Beispiel etwas hinzugefügt, deswegen habe ich ja immer wieder drauf hingewiesen, dass die Klasse ein totales Chaos ist. Eben halt ein Grund, warum ich das mal sauber sehen wollte, was man nun braucht und wie. Weil sonst schaue ich mir ein Tutorial nach dem anderen an und am Ende ist es immer chaotischer. Wobei ich dachte, dass man durchaus mehrere unterschiedliche Args in eine Klasse packen kann, heißt ja eigentlich Args und nicht Arg. Aber gut, damit könnte ich leben. das ist kein Problem. War ja, wie gesagt, nur einmal ausprobieren.

Welches der Beispiele meinst du denn eigentlich, wo meine Problematik am besten besprochen wird?

16.842 Beiträge seit 2008
vor einem Jahr

Wie gesagt, die Klasse war gerade in Arbeit. Natürlich kompiliert sie nicht.

Mh.... Du willst Hilfe und Feedback zu (D)einem Problem, und klatscht den Leuten Code vor, der nicht kompiliert.
Glaube niemand kann hier an Deinem Text erkennen, dass das "natürlich nicht kompiliert", weil es "in Arbeit" ist.

Irgendwie seltsam, dass man als Helfer damit rechnen soll, dass derjenige, der das programmiert hat, nicht mal kompilierfähigen Code zeigt, nich?

Wobei ich dachte, dass man durchaus mehrere unterschiedliche Args in eine Klasse packen kann, heißt ja eigentlich Args und nicht Arg

Der Satz zeigt eigentlich ziemlich deutlich, dass Dir einfach Grundlagen fehlen 🙂

Ein Event hat eine EventArgs Klasse, wobei eine EventArgs-Klasse durchaus aus verschiedenen Events mitgegeben werden kann.
Klassische 1-n Relation.
Soll Dein Event verschiedene Args werfen, dann stimmt einfach vorn und hinten das Design nicht.
Standard .NET event patterns

Weil sonst schaue ich mir ein Tutorial nach dem anderen an und am Ende ist es immer chaotischer.

Persönlicher Tipp, nett gemeint: geh strukturiert an die Sache ran, lern die Grundlagen. Wende das erlernte an.
So wirkt das zumindest auf mich als Leser, dass das rumgestochere ist. Das kann doch nicht zufriedenstellend sein, oder?
Mag nicht der Realität entsprechen, weiß ich nicht - aber es wirkt so.

Welches der Beispiele meinst du denn eigentlich, wo meine Problematik am besten besprochen wird?

Ich sehe nur ein Beispiel, das er Dir gegeben hat - und da wird das eigentlich ausführlich erklärt.
Hast halt leider nicht umgesetzt, also nicht mal im Ansatz.

Warum ist das Event Handling teil der Event Args?
Das wird nirgends gezeigt. Nicht in seinem Link, nicht in den Docs. Das kann nicht funktionieren.

Daher kann man auf die Frage, welches Beispiel er meint, irgendwie auch nur antworten: na das, was er Dir verlinkt hat.

Gelöschter Account
vor einem Jahr

Mh.... Du willst Hilfe und Feedback zu (D)einem Problem, und klatscht den Leuten Code vor, der nicht kompiliert.
Glaube niemand kann hier an Deinem Text erkennen, dass das "natürlich nicht kompiliert", weil es "in Arbeit" ist.

Wie oft sollte ich denn deiner Meinung nach noch vorher schreiben, dass ich die Klasse mehrfach umgeschrieben habe und sie deswegen ein wenig Chaotisch ist und ich sie deswegen eigentlich nicht anfügen wollte? Also wie oft hätte ich das noch machen sollen, bevor nicht so ein Spruch kommt?

Wobei ich dachte, dass man durchaus mehrere unterschiedliche Args in eine Klasse packen kann, heißt ja eigentlich Args und nicht Arg

Ja OK, der geht auf meine Kappe. Nicht jeder versteht Humor. Ich habe halt viel hin und her geschrieben und zu dem Zeitpunkt stand es halt so da, weil ich explizit gefragt wurde, ob ich es hier einfügen könnte.

Persönlicher Tipp, nett gemeint: geh strukturiert an die Sache ran, lern die Grundlagen. Wende das erlernte an.
So wirkt das zumindest auf mich als Leser, dass das rumgestochere ist. Das kann doch nicht zufriedenstellend sein, oder?
Mag nicht der Realität entsprechen, weiß ich nicht - aber es wirkt so.

Bisher hat noch niemand auf meine Frage geantwortet, mal ganz einfach klipp und klar, mit Kommentierung was, was ist, was wo aufgerufen werden muss und warum man es so macht. Es gibt nur Beispiele, die nach und nach zusammengewürfelt wurden, stellenweise noch nicht einmal kommentiert Und ja, nachdem ich vieles ausprobiert habe stochere ich natürlich auch. Aber da mir keiner bisher eine ganz einfache klipp und klare Antwort geben konnte kann ich doch nur sagen, ihr habt es doch selber nicht verstanden.

Es sieht dann zwar wichtig aus, weil jemand, der sich damit nicht auskennt, versteht es nicht so richtig, und wenn er trotzdem weiter fragt kann man ja noch nachschieben, dass er erstmal die Grundlagen lernen soll. Danke.

Ja Sorry, absolut mein Fehler. Ich dachte ja, dass so ein Forum halt dafür da ist, wenn jemand etwas nicht versteht, dass man es dann erklärt bekommt, auch wenn vielleicht bereits vorhandenes Material unverständlich ist oder so. Aber offensichtlich war das ein sehr großer Irrtum. Für diesen Irrtum entschuldige ich mich natürlich aufrichtig.

16.842 Beiträge seit 2008
vor einem Jahr

Nicht jeder versteht Humor. Ich habe halt viel hin und her geschrieben und zu dem Zeitpunkt stand es halt so da, weil ich explizit gefragt wurde, ob ich es hier einfügen könnte.

Niemand kann hier raus lesen, was Du als Humor meinst und was nicht. Es kennt Dich niemand.
Wir können das leider nicht riechen. Sachlich bleiben ist daher für alle Beteiligten immer am einfachsten.

Bisher hat noch niemand auf meine Frage geantwortet, mal ganz einfach klipp und klar, mit Kommentierung was, was ist, was wo aufgerufen werden muss und warum man es so macht.

Es wurde Dir doch ein vollständiges Tutorial gegeben. Dazu kopiere ich Dir folgenden Code:


class SubForm : Form
{
  // ...

  public class TextEventArgs : EventArgs
  {
    public TextEventArgs(string text)
    {
      Text = text; // Eigenschaft setzen
    }

    public string Text { get; set; } // Text als Eigenschaft definieren
  }

  public event EventHandler<TextEventArgs> UpdateText; // Ereignis deklarieren

  void button_Click(object sender, EventArgs e)
  {
    // ...
    
    OnUpdateText(new TextEventArgs("Test")); // Ereignis-Methode aufrufen
  }

  protected virtual void OnUpdateText(TextEventArgs e)
  {
    EventHandler<TextEventArgs> ev = UpdateText;
    if (ev != null)
      ev(this, e); // abonnierte Ereignismethode(n) aufrufen
  }
}

  • der Code ist strukturiert; zB ist der Event Handler Teil der Form und nicht Teil der Args - bei Dir schon
  • es wird gezeigt wie man auf den Event lauscht
  • es wird gezeigt wie der Event geworfen wird
  • ... und dazu ist alles dokumentiert

Damit das auf Deinen Fall passt hat Dir Th69 noch den Hinweis gegeben:

die SubForm entspricht dabei dann deiner Klasse).

Welche Infos fehlen Dir denn? Du hast doch damit sogar schon eine Copy-Paste-Vorlage.
Wir sehen nur Code, der nicht kompiliert und dazu leider nicht mal dem Beispiel aus dem Tutorial ähnlich sieht.

Was wir als Forum machen können ist, dass wir Dir sagen können wo die Infos stehen die Du brauchst und wie etwas funktioniert aber wir können nicht das Lernen für Dich übernehmen.
Geht halt nicht. Sorry.

Gelöschter Account
vor einem Jahr

Genau so habe ich angefangen, aber es funktionierte halt nicht. Ich weiß jetzt zwar nicht mehr genau die Fehlermeldung, weil ich versuche es ja schon eine ganze Weile.

Aber das ist ja einfach. Ich meine, das macht man ja ständig automatisch in C#, mit Buttons oder eigentlich allem was mit sender und eventargs aufgerufen wird. An der Stelle dachte ich ja auch, dass ich es verstanden habe, aber offensichtlich macht er es ja nicht. Wie gesagt, leider weiß ich nicht mehr genau, was es war. Ich glaube, das war die Stelle, wo kein Wert, sondern der Typ angezeigt wurde. Bin mir da aber nicht mehr ganz sicher.

Deswegen bin ich ja irgendwann auf delegates und invoke gestoßen, dass ist der Teil den ich halt nicht so ganz verstehe und was halt auch mal so gar nicht funktioniert.

Kannst du mir da die Unterschiede, bzw. Wirkungsweise von Delegates, den Nutzen von Invokes und wann man es an Stelle normaler Events verwendet mal erklären?

Gelöschter Account
vor einem Jahr

Moment, ich glaube ich weiß was ich die ganze Zeit falsch mache.

Sehe ich das richtig, dass die EventArgs-Klasse in der Form-Klasse ist?

Ich dachte, das geht gar nicht, bzw. ist nicht erlaubt?

Ist das so gewollt, oder ist das nur ein Fehler?

Gelöschter Account
vor einem Jahr

Also, ich habe es noch einmal wieder so umgeschrieben, wie du es vorgeschlagen hast. Das Ergebnis ist wie beim ersten Mal.

Jetzt ist ja wieder alles sauber, denke ich zumindest, deswegen kann ich ja mal einfügen.

Das steht im CSV-Parser


        public class TReadFailEventArgs : EventArgs
        {
            public TReadFailEventArgs(int readFailCount)
            {
                this.ReadFailCount = readFailCount;
            }
            public int ReadFailCount
            {
                get; set;
            }
        }

        public event EventHandler<TReadFailEventArgs> ReadFail;

        protected virtual void OnReadFail(TReadFailEventArgs e)
        {
            EventHandler<TReadFailEventArgs> ev = ReadFail;
            if (ev != null)
            {
                ev(this, e);
            }
        }

        OnReadFail(new TReadFailEventArgs(_readFailCount));

Ich habe mich in einigen Teilen auch an deine Benennung gehalten, also nicht, dass du dich wunderst.

In der aufrufenden Form steht folgedes:


        CSVParser parser = new CSVParser();
        parser.ReadFail += Parser_ReadFail;

        private void Parser_ReadFail(object sender, TReadFailEventArgs e)
        {
            tsSLErrors.Text = $"Einlesefehler: {e}";
        }

Als Ergebnis bekomme ich dann "CSVParser+TReadFailEventArgs".

Also irgendetwas muss ich da wohl noch übersehen.

Gelöschter Account
vor einem Jahr

Gefunden.

e.ReadFailcount war der Fehler.

Aber warum steht in sämtlichen Tuts immer nur e?

Und wenn man das explizit angeben kann, dann müsste man doch auch mehrere Args in die Klasse bauen können.

OK, das werde ich nicht ausprobieren. Bin ja erstmal froh, dass es funktioniert.

Danke für das Beispiel. Ohne genau dieses wäre ich wahrscheinlich gar nicht auf die Idee gekommen, das auch noch einmal auszuprobieren.