arlegermi Geschrieben 22. März 2018 Geschrieben 22. März 2018 (bearbeitet) Deine Fragen lassen sich ganz leicht beantworten: vor 5 Stunden schrieb Eleu: Darf eine Klasse nicht von Form1 erben? Doch. vor 5 Stunden schrieb Eleu: Wie kann ich aus einer Klasse heraus Methoden in der Form auslösen? So wie mit jedem anderen Objekt auch. Das hilft dir nur nicht. Daher kommt hier die Bitte (wiederholt), deinen gesamten Code mal zu zeigen, damit man dir erklären kann, wie du das, was du vorhast, am besten umsetzen kannst. Ich habe von dem, was du schreibst, so ein bißchen den Eindruck, als hättest du den Eindruck, die Form-Klasse sei irgendwas besonderes. Das ist sie nicht. Wenn du eine Methode eines Formulars aufrufen möchtest, brauchst du als allererstes einen Verweis auf das Objekt: Form1 myForm = new Form1(); Danach kannst du die öffentlichen Methoden dieses Objekts aufrufen: myForm.Focus(); Wenn du jetzt aus einer Klasse, wie bspw. dem ResultWriter auf dein Formular zugreifen möchtest, ist die einfachste Möglichkeit, dieses im Konstruktor zu übergeben: public ResultWriter(Form1 myForm) { this.form = myForm; } // und in einer anderen Methode dann: this.form.Focus(); // wobei du Focus() natürlich durch deine Methode ersetzt Bearbeitet 22. März 2018 von arlegermi Zitieren
Eleu Geschrieben 22. März 2018 Autor Geschrieben 22. März 2018 vor 1 Minute schrieb Whiz-zarD: Antwort auf welche Frage? Ich sehe aber hier keine Frage. Zitat Noch eine technische Frage: Wenn ich aus einer Klasse heraus in eine TextBox schreiben wollte, würde ich eine Methode dafür in der Form programmieren: public void TextAnzeigen() { textBox1.Text = "Der Text"; } Nun könnte ich ja in der Klasse einfach diese Methode aufrufen, wenn ich nun die Form1 als Basisklasse dort angebe public class ResultWriter : Form1 Die Methode ist in der Klasse dann auch aufrufbar, doch es funktioniert nicht. Ich bekomme beim Start der Anwendung diese Fehlermeldung: System.StackOverflowException: "Eine Ausnahme vom Typ "System.StackOverflowException" wurde ausgelöst." und zwar an dieser Stelle in der Form: ResultWriter b = new ResultWriter(); Danach hängt sich sogar das ganze Visual Studio auf und startet neu. Darf eine Klasse nicht von Form1 erben? Wie kann ich aus einer Klasse heraus Methoden in der Form auslösen? Zitieren
Whiz-zarD Geschrieben 22. März 2018 Geschrieben 22. März 2018 (bearbeitet) Die Frage wurde doch schon beantwortet. Was willst du denn noch? Wenn du es nicht verstehst, dann stelle weitere Fragen und lass uns an deinen Gedanken teilhaben und stelle nicht einfach Codeschnippsel rein, bei denen wir nicht wissen, was du damit vor hast. Bearbeitet 22. März 2018 von Whiz-zarD maestro impostor reagierte darauf 1 Zitieren
KeeperOfCoffee Geschrieben 22. März 2018 Geschrieben 22. März 2018 Wenn du unbedingt die Werte in der anderen Klasse ändern willst, dann mache es über Properties wie hier beschrieben... https://stackoverflow.com/a/5647064 Zitieren
Eleu Geschrieben 22. März 2018 Autor Geschrieben 22. März 2018 (bearbeitet) Den ganzen Code hier zu posten, wird etwas viel.... Aber ich kann den Fehler auch isoliert erzeugen: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace WindowsFormsApp1 { class Testklasse : Form1 { public void Ausführen() { TextAnzeigen2(); } } } Dann in der Form: public Form1() { InitializeComponent(); { } Testklasse ca = new Testklasse(); ... Und: public void TextAnzeigen2() { textBox15.Text = "Der Text"; } private void button6_Click(object sender, EventArgs e) { ca.Ausführen(); } Wenn ich Starte, erfolgt die Fehlermeldung (Siehe Anhang) Bearbeitet 22. März 2018 von Eleu Zitieren
KeeperOfCoffee Geschrieben 22. März 2018 Geschrieben 22. März 2018 Ganz einfach: Du hast in einer Form1 eine neue Instanz von Testklasse erstellt. Und zwar direkt in der Klasse... Da du deine Form1 Klasse an Testklasse vererbst, wird diese Instantiierung erneut ausgeführt. Du erstellst Testklasse, die von Form erbt und dadurch eine Testklasse erzeugt, welche auch von Form erbt, die eine Testklasse erzeugt usw. usw. Du musst versuchen das anders zu lösen, zB. indem du die Testklasse nur in der Methode instantiierst, in der du sie benötigst. Zitieren
Whiz-zarD Geschrieben 22. März 2018 Geschrieben 22. März 2018 vor 6 Stunden schrieb r4phi: (Ich bekomme die Zitat-box per Android nicht gelöscht) Die Frage wurde aber schon beantwortet. Du erzeugst eine Instanz von Form1. Die wiederum erzeugt eine Instanz von Testklasse und diese wieder von Form1, du wieder erzeugt eine Instanz von Testklasse, usw. usw. usw. Du erzeugst also unendlich viele Instanzen von Form1 und Testklasse. Irgendwann wir aber die Reißleine gezogen und das Programm schmeißt eine Stackoverflowexception Zitieren
Mttkrb Geschrieben 22. März 2018 Geschrieben 22. März 2018 (bearbeitet) Du hast dir mit dem Erben von Form1 eine Schleife gebaut. Der Konstruktor der Klasse Testklasse ist nicht extra definiert. Er existiert dennoch und dieser ist im Prinzip wie folgt definiert: public Testklasse() : base() {} Vom Ablauf her: Testklasse-Konstruktor ruft durch die Vereerbung den konstruktor von Form1 auf Form1-Konstruktor erstellt ein neues Objekt vom Typ Testklasse mit dem Konstruktor. (zurück zu 1) Edit: Da waren @KeeperOfCoffee und @Whiz-zarD etwas schneller. ;-) Bearbeitet 22. März 2018 von Mttkrb Zitieren
maestro impostor Geschrieben 22. März 2018 Geschrieben 22. März 2018 Was sich mir noch nicht ganz erschließt, was auch noch nicht beantwortet wurde und das Problem eigentlich löst: Warum zum Teufel ist deine Klasse TestKlasse() von Form1 abgeleitet?!?! Ja. Man darf von Forms ableiten. Gibt einige Szenarien wo das durchaus Sinn macht. Dieser Sinn ist hier aber in keinster Weise ersichtlich. KeeperOfCoffee reagierte darauf 1 Zitieren
Eleu Geschrieben 22. März 2018 Autor Geschrieben 22. März 2018 vor 19 Minuten schrieb KeeperOfCoffee: Du musst versuchen das anders zu lösen, zB. indem du die Testklasse nur in der Methode instantiierst, in der du sie benötigst. private void button6_Click(object sender, EventArgs e) { Testklasse ca = new Testklasse(); ca.Ausführen(); } public void TextAnzeigen2() { textBox15.Text = "Der Text"; } Diese Variante funktioniert nicht. Wenn ich den Button betätige, wird die Methode TextAnzeigen2 nicht ausgeführt, oder anders gesagt, es wird nichts in der TextBox15 angezeigt. Zitieren
Eleu Geschrieben 22. März 2018 Autor Geschrieben 22. März 2018 vor 8 Minuten schrieb r4phi: Was sich mir noch nicht ganz erschließt, was auch noch nicht beantwortet wurde und das Problem eigentlich löst: Warum zum Teufel ist deine Klasse TestKlasse() von Form1 abgeleitet?!?! Ja. Man darf von Forms ableiten. Gibt einige Szenarien wo das durchaus Sinn macht. Dieser Sinn ist hier aber in keinster Weise ersichtlich. Der Sinn der dahinter steht ist einzig und allein der, dass ich wissen möchte, ob es geht Zitieren
Whiz-zarD Geschrieben 22. März 2018 Geschrieben 22. März 2018 Natürlich kann Testklasse vom Form1 erben. Dann ist Testklasse ebenfalls eine Form. Dein Konstrukt funktioniert aber, aus den genannten Gründen, nicht. Zitieren
maestro impostor Geschrieben 22. März 2018 Geschrieben 22. März 2018 vor 35 Minuten schrieb Eleu: Der Sinn der dahinter steht ist einzig und allein der, dass ich wissen möchte, ob es geht Ja. Es geht. Aber nur weil es geht heißt es nicht das es Sinn macht. Zitieren
KeeperOfCoffee Geschrieben 22. März 2018 Geschrieben 22. März 2018 (bearbeitet) vor 56 Minuten schrieb Eleu: Diese Variante funktioniert nicht. Wenn ich den Button betätige, wird die Methode TextAnzeigen2 nicht ausgeführt, oder anders gesagt, es wird nichts in der TextBox15 angezeigt. Das liegt wohl daran, sofern mit den Zugriffsmodifiern alles passt, dass du nicht die textbox1 von Form1 änderst, sondern die textbox1 von Testklasse, die ja auch eine Form ist gib in Testklasse einfach mal this.ShowDialog ein, dann solltest du beide Dialoge sehen. In einem steht dann was in der Textbox. Oder anders gesagt: Ab Ausführen() änderst du Dinge in der Instanz der Testklasse und nicht in der Form1. Du vererbst Form1 an Testklasse, trotzdem sind Form1 und Testklasse zwei unterschiedliche Objekte. Bearbeitet 22. März 2018 von KeeperOfCoffee Zitieren
arlegermi Geschrieben 22. März 2018 Geschrieben 22. März 2018 Um das ganze mal grafisch anschaulich darzustellen, was da passiert: Du rufst über dein Program irgendwo ein new Testklasse() auf. Da Testklasse von Form1 abgeleitet ist, rufst du damit auch (implizit) ein new Form1() auf. Da du jetzt aber in Form1 auch immer eine neue Testklasse erzeugst (Testklasse ca = new Testklasse();), dreht sich das Programm im Kreis und es kommt zu dem von dir beobachteten Absturz. Zitieren
Eleu Geschrieben 23. März 2018 Autor Geschrieben 23. März 2018 vor 18 Stunden schrieb KeeperOfCoffee: gib in Testklasse einfach mal this.ShowDialog ein, dann solltest du beide Dialoge sehen. In einem steht dann was in der Textbox. Hallo KeeperOfCoffee, ja genauso verhält es sich dann. Wenn ich den Button betätige, wird die geerbte zweite Form (Testklasse) geöffnet und dort erscheint dann auch der Text in der TextBox. Grundsätzlich war eine Überlegung den FilsSystemWatcher in eine extra Klasse auszulagern. Das würde dann aber imho bedeuten, dass diese Klasse dann zyklisch durchlaufen muss, sonst würde der FileSystemWatcher ja nicht arbeiten können, oder? Normalerweise ist es ja so, dass mir die Instanz einer Klasse erst dann einen Rückgabewert einer Methode, in der Klasse liefert, wenn ich dieses über ein Ereignis abfrage. Momentan habe ich den FileSystemWatcher bei InitializeComponent() einprogrammiert. Ich verstehe es so, dass dieser Teil in der Form zyklisch abgearbeitet wird, genauso wie die Klasse Program. Also kann man den FileSystemWatcher nicht in einer extra Klasse unterbringen, weil diese eben statisch sind? Sehe ich das richtig? Gruß Eleu Zitieren
RipperFox Geschrieben 23. März 2018 Geschrieben 23. März 2018 vor 14 Minuten schrieb Eleu: Normalerweise ist es ja so, dass mir die Instanz einer Klasse erst dann einen Rückgabewert einer Methode, in der Klasse liefert, wenn ich dieses über ein Ereignis abfrage. Ich denke, Du bringst da verschiedene Sachen durcheinander. Schau Dir mal https://de.wikipedia.org/wiki/Ereignis_(Programmierung) an. Man könnte Dich noch mehr verwirren, wenn man Dir noch von Threads erzählt. Warum machen wir es aber nicht mal anders rum und fragen, was genau Du eigentlich genau ereichen willst und Du erzählst uns das dann Schritt für Schritt? Deine Ausführungen lesen sich momentan für mich so, als würdest du ausprobieren ob ein Elefant auch Rückwärts durch das Nadelöhr gezwängt werden kann - diese Vorgehensweise finde ich jetzt nicht sonderlich zielführend.. Zitieren
maestro impostor Geschrieben 23. März 2018 Geschrieben 23. März 2018 (bearbeitet) vor 29 Minuten schrieb Eleu: Grundsätzlich war eine Überlegung den FilsSystemWatcher in eine extra Klasse auszulagern. Das würde dann aber imho bedeuten, dass diese Klasse dann zyklisch durchlaufen muss, sonst würde der FileSystemWatcher ja nicht arbeiten können, oder? Nein. vor 29 Minuten schrieb Eleu: Normalerweise ist es ja so, dass mir die Instanz einer Klasse erst dann einen Rückgabewert einer Methode, in der Klasse liefert, wenn ich dieses über ein Ereignis abfrage. Der FileSystemWatcher arbeitet aber mit Events. Nicht mit Methoden. Das bedeutet das du nicht aktiv etwas abfragen musst. Der FileSystemWatcher meldet sich von selbst. vor 29 Minuten schrieb Eleu: Momentan habe ich den FileSystemWatcher bei InitializeComponent() einprogrammiert. Ich verstehe es so, dass dieser Teil in der Form zyklisch abgearbeitet wird, genauso wie die Klasse Program. Nein. Wie kommst du darauf? InitializeComponent() wird bei der Instanziierung deines Form Objekts aufgerufen. Selbiges gilt für die Klasse Program... warum sollte diese zyklisch aufgerufen werden? In einem normalen Forms Projekt sieht die Klasse so aus: /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } Warum sollte dieses Code den zyklisch aufgerufen werden? Setz einen Haltepunkt in dieser Klasse und schau wie oft dieser aufgerufen wird. Application.Run startet eine Standardnachrichtenschleife einer Anwendung für den aktuellen Thread und zeigt das angegebene Formular an. Diese Schleife ermöglicht es dass das Form Windows Messages erhält. Mausklicks, gedrückte Tasten etc. um eben die Interaktion des Benutzers zu ermöglichen. Wie der FileSystemWatcher funktioniert wurde doch in diesem Thread schon erklärt. vor 29 Minuten schrieb Eleu: Also kann man den FileSystemWatcher nicht in einer extra Klasse unterbringen, weil diese eben statisch sind? Doch... warum sollte das den nicht funktionieren? Ich verstehe auch nicht was du explizit am FileSystemWatcher auslagern möchtest. Es ist doch im Prinzip schon eine eigene Klasse. Bearbeitet 23. März 2018 von r4phi Zitieren
maestro impostor Geschrieben 23. März 2018 Geschrieben 23. März 2018 FileSystemWatcherWrapper using System; using System.IO; namespace WindowsFormsApplication1 { public class FileSystemWatcherWrapper { public Action OnSomethingHappend; FileSystemWatcher _instance; private FileSystemWatcherWrapper() { } public FileSystemWatcherWrapper(string pathToMonitor) { this._instance = new FileSystemWatcher(pathToMonitor); _instance.Changed += (sender, e) => somethingHappend(); _instance.Created += (sender, e) => somethingHappend(); _instance.Deleted += (sender, e) => somethingHappend(); _instance.Renamed += (sender, e) => somethingHappend(); _instance.EnableRaisingEvents = true; } private void somethingHappend() { this.OnSomethingHappend?.Invoke(); } } } Form1 using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form1 : Form { private FileSystemWatcherWrapper _fileSystemWatcher; public Form1() { InitializeComponent(); } public Form1(FileSystemWatcherWrapper fileSystemWatcher) : this() { this._fileSystemWatcher = fileSystemWatcher; fileSystemWatcher.OnSomethingHappend += () => MessageBox.Show("Something happend!"); } } } Zitieren
Eleu Geschrieben 23. März 2018 Autor Geschrieben 23. März 2018 Hallo r4phi, vielen Dank für den Code und ich habe ihn auch einmal einem ganz neuen Projekt ausprobiert. Ich bekomme aber in der Form eine Fehlermeldung (Siehe Anhang) Zitieren
arlegermi Geschrieben 23. März 2018 Geschrieben 23. März 2018 Du musst die Klasse FileSystemWatcherWrapper als public deklarieren. Zitieren
maestro impostor Geschrieben 23. März 2018 Geschrieben 23. März 2018 @Eleu Damit das ganze funktioniert musst du natürlich deine Program.cs anpassen und eine Instanz des Wrappers an deine Form übergeben: Application.Run(new Form1(new FileSystemWatcherWrapper(@"C:\temp"))); Zitieren
maestro impostor Geschrieben 23. März 2018 Geschrieben 23. März 2018 (bearbeitet) Damit das ganze mit dem Wrapper in dem Context auch einen Sinn macht kannst du deinem Wrapper auch einen Logger übergeben: Program.cs static class Program { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1(new FileSystemWatcherWrapper(@"C:\temp", new DebugLogger()))); } } ILog.cs public interface ILog { void Log(string logMessage); } DebugLogger.cs public class DebugLogger : ILog { public void Log(string logMessage) { Debug.WriteLine($"{DateTime.Now} :: {logMessage}"); } } FileSystemWatcherWrapper.cs public class FileSystemWatcherWrapper { public Action OnSomethingHappend; FileSystemWatcher _instance; ILog _logInstance; private FileSystemWatcherWrapper() { } public FileSystemWatcherWrapper(string pathToMonitor) : this(pathToMonitor, null) { } public FileSystemWatcherWrapper(string pathToMonitor, ILog logInstance) { this._instance = new FileSystemWatcher(pathToMonitor); _instance.Changed += (s, e) => somethingHappend(s, e); _instance.Created += (s, e) => somethingHappend(s, e); _instance.Deleted += (s, e) => somethingHappend(s, e); _instance.Renamed += (s, e) => somethingHappend(s, e); _instance.EnableRaisingEvents = true; this._logInstance = logInstance; } private void somethingHappend(string message) { this._logInstance?.Log(message); this.OnSomethingHappend?.Invoke(); } private void somethingHappend(object sender, FileSystemEventArgs args) { this.somethingHappend($"Changed file: {args.FullPath} Action: {Enum.GetName(typeof(WatcherChangeTypes), args.ChangeType)}"); } private void somethingHappend(object sender, RenamedEventArgs args) { this.somethingHappend($"File: {args.OldFullPath} renamed to: {args.FullPath}"); } } Debug Ausgabe 23.03.2018 14:29:17 :: Changed file: C:\temp\Neues Textdokument.txt Action: Created 23.03.2018 14:29:17 :: Changed file: C:\temp\Neues Textdokument.txt Action: Changed 23.03.2018 14:29:21 :: File: C:\temp\Neues Textdokument.txt renamed to: C:\temp\abc.txt 23.03.2018 14:29:24 :: Changed file: C:\temp\abc.txt Action: Deleted Vllt. wird es dadurch nun etwas klarer... Edit wrapper erweitert Bearbeitet 23. März 2018 von r4phi Zitieren
KeeperOfCoffee Geschrieben 23. März 2018 Geschrieben 23. März 2018 Definitiv das beste Thema um nochmal die Basics zu wiederholen *slowly clapping* Zitieren
Whiz-zarD Geschrieben 23. März 2018 Geschrieben 23. März 2018 (bearbeitet) @Eleu: Da du ja meinst, dass ein Hallo-Welt-Programm für dich zu langweilig ist, gebe ich dir mal eine Aufgabe: Ich gebe dir ein Stück Code vor und du erklärst jedes Schlüsselwort und jeden Begriff: using System; namespace ConsoleApp8 { class Program { static void Main(string[] args) { Console.WriteLine("Hallo Welt"); } } } Also was beutet using und namepace? Was heißt class? Was ist eine Klasse? Was ist ein Objekt? Wo liegt der Unterschied zwischen Klasse und Objekt? Was bedeutet static? Wo ist der Unterschied zwischen static und non-static? Was bedeutet void? Wieso heißt die Methode Main? Kann man sich auch anders benennen? Was bedeutet "string[] args"? Was bedeuten die geschweiften Klammern? Was ist Console? Was ist WriteLine? Was ist "Hallo Welt"? Ich bin mir sicher, dass du die meisten Fragen nicht beantworten kannst und daher bist du bei einem "Hallo Welt"-Programm gut aufgehoben. Bei solchen Programmen geht es nicht nur, um zu sehen, wie "Hallo Welt" auf der Konsole ausgegeben wird, sondern um auch die Basics einer Sprache kennenzulernen und daher ist es wichtig, sich auch mit diesem Programm intensiv auseinanderzusetzen. Du behauptest zwar, dass du vor 20 Jahren mit VB6 gearbeitet hast aber ich bezweifel dies, denn offenbar hast du keinerlei Kenntnisse über Objektorientierung, geschweige denn über die Programmierung. Ich bin hier auch nun raus, da ich keine Lust habe, jemanden das Programmieren beizubringen, der nicht mal Eigeninitiative zeigt und bei jeder Kleinigkeit sofort ein Post schreibt, anstatt sich selber mal um eine Antwort zu bemühen. Angeblich hast du ja ein Buch. Also dann lese es auch bitte. Ansonsten hast du ja noch Zugang zum Internet und google kennst du ja wohl auch. Auch unsere Fragen, was du da eigentlich vor hast, kannst du auch nicht mal beantworten. Bearbeitet 23. März 2018 von Whiz-zarD Mttkrb und maestro impostor reagierten darauf 2 Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.