Zweite,dritte,... Form erstellen mithilfe einer Methode

  • C#
  • .NET (FX) 4.5–4.8

Es gibt 17 Antworten in diesem Thema. Der letzte Beitrag () ist von nogood.

    Zweite,dritte,... Form erstellen mithilfe einer Methode

    Hi,

    ich bekomme es nicht hin eine Klasse zu schreiben, die eine Methode beinhaltet die eine Form "instanziiert" und dann anzeigen kann.

    Folgender TestCode funktioniert und besteht aus Form1.cs und Form2.cs. Beim Klick auf den Button in Form1 soll Form2 entweder erzeugt, angezeigt oder wiederhergestellt werden.


    C#-Quellcode

    1. using...
    2. namespace SecondForm
    3. {
    4. public partial class Form1 : Form
    5. {
    6. public Form1()
    7. {
    8. InitializeComponent();
    9. }
    10. //Instanziieren vomn f2
    11. Form2 f2 = new Form2();
    12. //Bei Kick auf den Button soll sich die 2te Form öffnen
    13. private void BtOpenSecFrm_Click(object sender, EventArgs e)
    14. {
    15. if (f2 == null || f2.IsDisposed) f2 = new Form2();
    16. if (!f2.Visible) f2.Show();
    17. if (f2.WindowState == FormWindowState.Minimized) f2.WindowState = FormWindowState.Normal;
    18. f2.Show();
    19. f2.Focus();
    20. }
    21. }
    22. }​



    Das geht auch alles, nur müsste ich das ja immer wieder neu schreiben wenn ich eine Form3,Form4, ... erzeugen möchte. Kann ich nicht eine Klasse inkl. Methode schreiben, die als Argument die zu erzeugende "Form3" annimmt? Im Grunde soll alles das was in der Methode BtOpenSecFrm_Click steht in eine Methode die ein Argumente annimmt.

    Pseudo Code:

    C#-Quellcode

    1. public Form f3 = new Form3();
    2. OpenNewForm(f3)​;
    3. public void OpenNewForm(Form frmNext)
    4. {
    5. if (frmNext == null || frmNext.IsDisposed)
    6. frmNext = new Form(); // <------ Das geht aber nicht da Form ja nicht richtig ist es müsste immer die Klasse da stehen die der Form zu Grunde liegt z.B. Form3
    7. if (!frmNext.Visible)
    8. frmNext.Show(frmNext);
    9. if (frmNext.WindowState == FormWindowState.Minimized)
    10. frmNext.WindowState = FormWindowState.Normal;
    11. frmNext.Focus();
    12. }




    Tltr : Ich suche nach einer Möglichkeit Forms zu erzeugen/anzuzeigen mithilfe einer Methode die als Argument die Klasse oder das Objekt einer Form aus dem Solution Explorer anerkennt !?
    codewars.com Rank: 4 kyu
    mit Generica:

    C#-Quellcode

    1. public Form f3 = new Form3();
    2. OpenNewForm(f3);
    3. public void OpenNewForm(TForm frmNext) where TForm:Form,new
    4. {
    5. if (frmNext == null || frmNext.IsDisposed)
    6. frmNext = new TForm(); // <------ Das geht - weil TForm ist ein TypParameter
    7. if (!frmNext.Visible)
    8. frmNext.Show(frmNext);
    9. if (frmNext.WindowState == FormWindowState.Minimized)
    10. frmNext.WindowState = FormWindowState.Normal;
    11. frmNext.Focus();
    12. }
    So ungefähr. Über die richtige C#-Syntax von TypParameter mit TypEinschränkungen musste dich selbst informieren, ich weiss das nur in VB.

    ErfinderDesRades schrieb:

    So ungefähr
    Ausprobiert:

    C#-Quellcode

    1. public void OpenNewForm<T>(T frmNext) where T : Form
    2. {
    3. if (frmNext == null || frmNext.IsDisposed)
    4. frmNext = default(T); // <------ Das geht - weil TForm ist ein TypParameter
    5. if (!frmNext.Visible)
    6. frmNext.Show(frmNext);
    7. if (frmNext.WindowState == FormWindowState.Minimized)
    8. frmNext.WindowState = FormWindowState.Normal;
    9. frmNext.Focus();
    10. }
    und

    C#-Quellcode

    1. public Form3 f3 = null;
    2. OpenNewForm<Form3>(f3);
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @ErfinderDesRades und @RodFromGermany Super! Danke Euch! Hatte da schon die wildesten Konstrukte gefrickelt.

    @RodFromGermany Ich bekomme leider noch einen Fehler in Zeile 32 (frmNext war "null" ) (das entspricht deiner Zeile 5). Es scheint als ob Zeile 4 kein Objekt erzeugt.

    Im SolutionExplorer hab ich Form1.cs (siehe Spoiler Code) und Form2.cs (leer).
    In Form1 (Designer) hab ich einen Button.



    Spoiler anzeigen

    C#-Quellcode

    1. ​using System;
    2. using System.Collections.Generic;
    3. using System.ComponentModel;
    4. using System.Data;
    5. using System.Drawing;
    6. using System.Linq;
    7. using System.Text;
    8. using System.Threading.Tasks;
    9. using System.Windows.Forms;
    10. namespace SecondForm
    11. {
    12. public partial class Form1 : Form
    13. {
    14. public Form1()
    15. {
    16. InitializeComponent();
    17. }
    18. public Form2 f2 = null;
    19. private void BtOpenSecFrm_Click(object sender, EventArgs e)
    20. {
    21. OpenNewForm<Form2>(f2);
    22. }
    23. public void OpenNewForm<T>(T frmNext) where T : Form
    24. {
    25. if (frmNext == null || frmNext.IsDisposed)
    26. frmNext = default(T);
    27. if (!frmNext.Visible)
    28. frmNext.Show(frmNext);
    29. if (frmNext.WindowState == FormWindowState.Minimized)
    30. frmNext.WindowState = FormWindowState.Normal;
    31. frmNext.Focus();
    32. }
    33. }
    34. }
    codewars.com Rank: 4 kyu
    Mit den generischen Typen hab ich es nicht ganz geschafft. Wenn man den Button 2x drückt wird eine neue Instanz der Form2 erzeugt und zusätzlich angezeigt. Es soll aber wenn die Form2 noch existiert keine neue erzeugt werden.

    C#-Quellcode

    1. public Form2 f2=null;
    2. private void BtOpenSecFrm_Click(object sender, EventArgs e)
    3. {
    4. OpenNewForm<Form2>(f2);
    5. }
    6. public void OpenNewForm<T>(T frmNext) where T:Form, new()
    7. {
    8. if (frmNext == null || frmNext.IsDisposed)
    9. frmNext= new T();
    10. if (!frmNext.Visible)
    11. frmNext.Show();
    12. }


    LSG auch gerne in VB Syntax


    codewars.com Rank: 4 kyu

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „nogood“ ()

    nogood schrieb:

    Es soll aber wenn die Form2 noch existiert keine neue erzeugt werden.
    Solch gehört in den Eröffnungpost.
    Ganz einfach mit ref:

    C#-Quellcode

    1. public Form2 f2 = null;
    2. private void button1_Click(object sender, EventArgs e)
    3. {
    4. OpenNewForm<Form2>(ref f2);
    5. }
    6. public void OpenNewForm<T>(ref T frmNext) where T : Form, new()
    7. {
    8. if (frmNext == null || frmNext.IsDisposed)
    9. frmNext = new T();
    10. if (!frmNext.Visible)
    11. frmNext.Show();
    12. }
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @ErfinderDesRades Danke für den Tipp
    @RodFromGermany Perfekt Danke Dir. Jetzt wo ich das lese ... Ist das mit ref natürlich sonnenklar. Wäre ich mit meinen Skills aber nicht drauf gekommen. Danke

    Zusatzfrage:
    Kann man ein und dieselbe Methode mal mit ref und mal mit "value" aufrufen? Man muss ja leider auch in der Methode ref angeben.
    (wie vermeide ich es, dass ich 2mal die gleiche Methode schreiben muss (1x ref 1x value); wenn ich beide Funktionalitäten (nur immer eine Form öffnen oder eben immer eine neue Instanz erzeugen) zur Verfügung haben möchte)

    Grundsätzlich wundert es mich das zum Thema Multipel Forms nicht mehr im Internet zu finden ist (ich hab da jedenfalls nicht viel gefunden). Das ist doch ein absolutes Standardproblem.
    Jetzt könnte man die Methode ja noch verfeinern mit showDialog, FensterPosition beim Aufruf, ... . Danke noch mal und ich hoffe ich komme erstmal ohne Nachfragen weiter (=bis gleich ;)).
    codewars.com Rank: 4 kyu

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „nogood“ ()

    nogood schrieb:

    Kann man ein und dieselbe Methode mal mit ref und mal mit "value" aufrufen?
    Gib ihr einen Boolean-Parameter, der sagt, ob Du die Instanz zurück haben willst:

    C#-Quellcode

    1. public void OpenNewForm<T>(ref T frmNext, bool flag) where T : Form, new()
    2. {
    3. T frm = frmNext;
    4. if (frm == null || frm.IsDisposed)
    5. frm = new T();
    6. if (!frm.Visible)
    7. frm.Show();
    8. if (flag)
    9. frmNext = frm;
    10. }
    ungetestet
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @nogood Mein Code funktioniert leider nicht.
    Probierma dies:
    Spoiler anzeigen

    C#-Quellcode

    1. public Form2 f2 = null;
    2. public Form2 f3 = null;
    3. private void button1_Click(object sender, EventArgs e)
    4. {
    5. OpenNewForm<Form2>(ref f2);
    6. }
    7. private void button2_Click(object sender, EventArgs e)
    8. {
    9. Form2 f3_2 = f3;
    10. OpenNewForm<Form2>(ref f3_2);
    11. }
    12. public void OpenNewForm<T>(ref T frmNext) where T : Form, new()
    13. {
    14. if (frmNext == null || frmNext.IsDisposed)
    15. frmNext = new T();
    16. if (!frmNext.Visible)
    17. frmNext.Show();
    18. }

    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RodFromGermany Danke, dass Du dir das nochmal angesehen hast. Ich hab in der Zeit den Ansatz von ErfinderDesRades verfolgt. Kontrollieren, ob die zu erzeugende Form schon erzeugt ist mit ​System.Windows.Forms.Application.OpenForms:


    C#-Quellcode

    1. public Form2 f2 = null;
    2. private void BtOpenSecFrm_Click(object sender, EventArgs e)
    3. {
    4. OpenNewForm<Form2>(f2, false);
    5. }
    6. public void OpenNewForm<T>(T frmNext, Boolean multiFrm) where T : Form, new()
    7. {
    8. if (frmNext == null || frmNext.IsDisposed)
    9. frmNext = new T();
    10. foreach (var item in System.Windows.Forms.Application.OpenForms)
    11. {
    12. if ((frmNext.Name == item.GetType().Name) && !multiFrm)
    13. return; // Falls schon erzeugt return ohne .Show()
    14. }
    15. if (!frmNext.Visible)
    16. frmNext.Show();
    17. }


    1.
    Was hältst Du/Ihr davon, kann ich das so in meinen nächsten Projekten benutzen (oder ist Dein Ansatz mit ref besser)?

    2.
    Eine Kleinigkeit hab ich noch die mich an dem Code stört. Im Fall das die Form schon erzeugt ist und nicht neu erstellt wird soll der Focus auf diese schon vorhandene Form gelegt werden. Das bekomme ich nicht hin. Wie bekomme ich das Objekt aus der List "raus" um .Focus() benutzen zu können?

    C#-Quellcode

    1. if ((frmNext.Name == item.GetType().Name) && !multiFrm)
    2. {
    3. //item.Focus(); // ToDo Focus auf die schon erzeugte Form setzen <-- Wie geht das item.GetType().???Focus()
    4. return;
    5. }
    codewars.com Rank: 4 kyu
    @nogood OpenForms ist hier der falsche Ansatz.
    Bevor Du hier 1000 Snippets probierst, beschreibst Du bitte mal etwas detaillierter, was Du eigentlich machen bzw. erreichen willst.
    Dann lässt es sich einfacher helfen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Mein Zeil ist es eine Klasse zu schreiben, die ich immer benutze falls ich eine neue Form öffnen/anzeigen möchte.

    Bei der Instanzierung kann man verschiedene Flags angeben, die entscheiden welche Eigenschaften die Form haben soll.
    Show as Dialog Yes//No , Position der Form,... . Und ob die Form falls sie schon vorhanden ist nur wieder in den Focus kommen soll oder ob eine zweite Instanz erzeugt werden soll.

    ​public void OpenNewForm<T>(T frmNext, Boolean showAsDialogeNewFrm, Boolean multiFrm, Boolean centerNewFrm, etc. ) ...

    ---
    Zur Sicherheit mal ein Beispiel:
    Form1->Kundenkartei mit einem Button "Neuen Kunde anlegen" 1. click-> Form2 wird geöffnet Maske Kundendaten Name, ...

    Zwei Möglichkeit falls der Button in Form 1 nochmal gerückt wird bevor die Form2 geschlossen ist:
    1. Form2 wird der Focus gegeben (kein neues Fenster erzeugt)
    2. Es wird eine 2te From2 angezeigt
    codewars.com Rank: 4 kyu
    @nogood etwas überladen.
    Um die Position sollte sich der Dialog selbat kümmern, gib ihm dazu ne geeignete Basisklasse.
    Falls Du mit
    Show as Dialog Yes//No
    meinst, ob der Dialog modal oder nicht modal angezeigt werden soll:
    Trenne das auf für modale und nicht modale Dialoge.
    Ich habe noch nie erlebt, dass eine Form sowohl modal als auch nicht modal angezeigt werden soll.
    Und:
    Deutsch wäre:
    2. Es wird eine 2. From2 angezeigt ;)
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    1. Position sollte sich der Dialog selber kümmern mit einer geeigneten Basisklasse. Bedeutet das, dass ich eine Klasse erstelle soll, die sich um die Positionierung von Forms kümmert?

    2. Show as Dialog = ja sollte heißen: zeige Form entweder Modal oder eben nicht modal.

    3. (Modal j/n) Ist das nicht okay, wenn ich das bei der Instanzierung festlege. Es soll ja eine allgemein gültige Klasse zur Forms-Erzeugung sein. Die Klasse kann halt Forms erzeugen die Modal sind oder eben welche die nicht Modal angezeigt werde. Ich wollte die Klasse für 99% der Fälle benutzen wo ich eine neue Form benötige.

    4ter Punkt ;)

    -----------
    Ist die Idee so eine Klasse zu coden einfach nicht gut? Oder wie macht man sowas?
    codewars.com Rank: 4 kyu
    @nogood Basisklasse mit FormShown und FormClosing und ner shared XML-Tabelle.
    Wenn Deine Klasse alles können soll, dann lass sie auch gleich die Temperatursteuerung Deines Kühlschrankes übernehmen. ;)
    Mach einfach mal ne Aufstellung, welche Dialoge was brauchen und trenne dann das ganze ggf. auf in eine Basisklasse und je eine abgeleitete Klasse für modale und nicht modale Dialoge.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!