Blöde Frage: Wie teile ich mein Projekt in MS VisualStudio auf mehrere Code-Dateien auf ?



  • Hi Leuts

    Ich habe hier ein "kleines" Problem, welches ich (warum auch immer) nicht gelöst kriege.

    Das Visual Studio von MS erstellt bei einer Windowsanwendung mitunter eine Datei mit dem Namen "Hauptfenster.cs".

    using SYSTEM;
    
    namespace Taschenrechner
    {
        public partial class Hauptfenster : Form
        {
            public Hauptfenster()
            {
                InitializeComponent();
            }
    
    //Hier beginnt mein Code
    ...
    ...
    ...
    

    Bisher habe ich diese Datei genommen um mein Programm darin zu schreiben.
    Leider wird das aber irgendwann ziemlich unüberlichtlich.
    Deshalb wollte ich eine zweite Datei erstellen, in der ich z.B. nur meine erstellten Methoden abspeichere, also z.B. "Methoden.cs".

    Meine beiden Probleme:

    1. Ich schaffe es nicht von einer Datei zugriff auf die variablen bzw. Methoden der anderen Datei zu erhalten. Könnte mir jemand mal bitte nen kurzes Codesegment geben wie die Datei "Methoden.cs" im Kopf aussehen müßte damit das klappt? Soweit ich gelesen habe ist das mit "partial Class" möglich, irgendwie funzt das bei mir aber nicht, ich scheine noch einen anderen Fehler zu machen.

    2. Wenn ich z.B. eine andere Klasse benutze und auf eine Checkbox in "Hauptfenster" zugreifen will dann klappt das zwar, es wird aber immer nur ein "False" für den Checked übergeben, egal ob die Checkbox aktiviert ist, oder nicht. Ich kann aus einer anderen Klasse zwar auf direkt die Checkbox zugreifen (ist auf public gesetzt), aber die erhaltenen Werte stimmen nicht.

    Vielen Dank

    MFG
    Marco



  • Du programmierst prozedural statt objektorientiert in einer rein objektorientierten Sprache. Das kann nicht gut gehen.

    Informiere dich zum Thema OOP.

    MfG SideWinder



  • Der gezeigte Quellcode zeigt keine prozedurale Vorgehensweise.

    @Op:
    Stimmt der Namensraum ? Bitte Fehlermeldung des Compilers angeben. Geht nicht gibts nicht.

    namespace Taschenrechner
    {
        public partial class Hauptfenster : Form
    
        public void Methode1(){}
        public void Methode2(){}
        public void Methode3(){}
    }
    

    Zu 2: Beispiel zeigen (und am sinnvollsten ein Property erstellen oder eine Methode, aber kein UI Element nach außen geben.)



  • Noch als Nachtrag: Du kannst Knuddlbaer's Beispiel in Deine Methoden.cs packen, der Compiler verkraftet mehr als zwei Dateien per partial class. Aber ein passender Name wäre nett.



  • So, also mal ein einfaches Testprojekt ... damits übersichtlich bleibt.

    Vielleicht sollte ich noch einen Schritt weiter zurück gehen. Die Grundlagen für ordentliches Programmieren sind leider nicht so ganz einfach zu verstehen.
    Ich denke einmal das das der noch bessere Weg ist ...

    Wie gesagt, ich möchte eine Windows Fensteranwendung mit Visual Express 2008 erstellen (bzw. mein bereits funktionierendes Programm übersichtlicher gestalten).

    Also:
    Grundlage ist hier als Beispiel ein einfaches Fenster mit einer einzelnen Checkbox, nichts weiter:

    Programm.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Windows.Forms;
    
    namespace Testbeispiel
    {
        static class Program
        {
            /// <summary>
            /// Der Haupteinstiegspunkt für die Anwendung.
            /// </summary>
            [STAThread]
            static void Main()
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }
        }
    }
    

    Form1.cs

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    
    namespace Testbeispiel
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
        }
    }
    

    Form1.Designer.cs

    namespace Testbeispiel
    {
        partial class Form1
        {
            /// <summary>
            /// Erforderliche Designervariable.
            /// </summary>
            private System.ComponentModel.IContainer components = null;
    
            /// <summary>
            /// Verwendete Ressourcen bereinigen.
            /// </summary>
            /// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
            protected override void Dispose(bool disposing)
            {
                if(disposing && (components != null))
                {
                    components.Dispose();
                }
                base.Dispose(disposing);
            }
    
            #region Vom Windows Form-Designer generierter Code
    
            /// <summary>
            /// Erforderliche Methode für die Designerunterstützung.
            /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
            /// </summary>
            private void InitializeComponent()
            {
                this.checkBox1 = new System.Windows.Forms.CheckBox();
                this.SuspendLayout();
                // 
                // checkBox1
                // 
                this.checkBox1.AutoSize = true;
                this.checkBox1.Location = new System.Drawing.Point(25, 26);
                this.checkBox1.Name = "checkBox1";
                this.checkBox1.Size = new System.Drawing.Size(90, 17);
                this.checkBox1.TabIndex = 0;
                this.checkBox1.Text = "testcheckbox";
                this.checkBox1.UseVisualStyleBackColor = true;
                // 
                // Form1
                // 
                this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
                this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
                this.ClientSize = new System.Drawing.Size(131, 64);
                this.Controls.Add(this.checkBox1);
                this.Name = "Form1";
                this.Text = "Form1";
                this.ResumeLayout(false);
                this.PerformLayout();
    
            }
    
            #endregion
    
            private System.Windows.Forms.CheckBox checkBox1;
        }
    }
    

    Programmiert habe ich bisher immer in der "Form1.cs", also in der Klasse "public partial class Form1 : Form". Da funktioniert natürlich alles genauso wie ich es brauche ... ist aber dafür unübersichtlich, was ich ja nun gerne ändern würde.

    Für mich stellt sich jetzt als NOOB die Frage, wie ich überhaupt weiter vorgehen soll. Ich muß ja nunirgendwo meinen "Programmablauf" reinschreiben.

    Wenn ich das richtig verstanden habe, sollte man in der "Form1.cs" alles verfassen, was letztendlich das Fenster, die Schaltflächen und Buttons beeinflußt, steuert oder miteinander kommunizieren läßt. Also quasi wenn ich einen Button drücke soll dort bestimmt werden das dann z.B. sich ein anderes Element in dem Fenster (z.B. eine Textbox) inaktiv schaltet ... Also quasi nur die Kommunikation der Fensterelemente untereinander (schwer zu erklären ...) 😞

    Gehe ich richtig in dieser Annahme ? Wenn ja: Dann brauche ich ja eine neue Datei bzw. Klasse für meinen eigentlichen Programmablauf.

    Also, wie gehts jetzt am sinnvollsten weiter ?

    MFG
    Marco



  • Überlege Dir, ob Du Programmlogik von der GUI trennen solltest. Alles was mit dem Form zusammen passieren soll, z.B. Enablen/Disablen von Schaltflächen abh. vom Formstatus kannst Du ja in Form.cs packen. Alles was evtl auch ohne diesem Form laufen können soll (z.B. Stapelverarbeitung) würde ich in einer extra Klasse kapseln.



  • Sofern ich das richtig verstanden habe ist das am "besten" die Programmlogik von der GUI abzutrennen.

    Ich wollte es eigentlich genau so trennen damits übersichtlicher bleibt.

    Als Beispiel hier z.B.

    Ich möchte ein Programm erstellen, welches mir eine Messagebox ausgibt, die den Status anzeigt, ob die Ckeckbox1 aktiviert ist, oder nicht. Die Messagebox soll erscheinen wenn der Status der Ckeckbox1 verändert wird (also vom Benutzer angeklickt wird). Das kann man zwar direkt durch das Häckchen der box an sich erkennen, aber es soll hier ja nur ein einfaches Beispiel sein.

    Das geht zwar auch mit dem ?? Eventhändler ?? direkt aus der Form1.cs heraus, ich möchte diese Prozedur aber aus einer anderen Klasse aus einer anderen Codedatei heraus realisieren. Von dort aus soll halt aber auch die Checkbox1 angesteuert werden können (also z.B. aktivieren/deaktivieren oder "Checken/Unchecken).

    MFG
    Marco



  • Für diese (einfache) Aufgabe reicht wirklich die Form-Klasse und der Event-Handler für die Checkbox aus.
    Formulare sollten untereinander sowenig wie möglich auf einander zugreifen.
    Eine Ausnahme sind modale Dialoge (Aufruf mittels ShowDialog()), z.B. für Optionsfenster oder Auswahlfenster mittels einer Liste etc.
    Hier sollte die Übergabe dann über Methoden bzw. Eigenschaften (Properties) erfolgen, aber niemals direkt über die GUI-Elemente. Falls man von außen einen Event-Handler ansprechen (abonnieren) möchte, so sollte man dafür ein eigenes Event definieren und dann einfach innerhalb des Formulars den Aufruf weiterleiten.

    Generell sollte es bei größeren Projekten immer eine Trennung zwischen GUI und Logik geben, d.h. das Hauptformular verwaltet das Logik-Objekt und reicht die Berechnungen daran weiter.
    Beispiel:

    // logic.cs
    
    public class Logic
    {
      public Logic(); // evtl. noch Initialisierungsparameter
    
      // Eigenschaften
    
      public int Count
      {
         get { return count; }
      }
    
      // Methoden
    
      public int Calculate(int x, int y)
      {
        return x*x + y*y;
      }
    
      // private Member
    
      private int count;
    }
    
    // mainform.cs
    
    public class MainForm
    {
      public MainForm()
      {
        logic = new Logic(); // hier auch evtl. Parameter angeben
      }
    
      public void Button1_Click(object Sender, EventArgs e)
      {
        int z = logic.Calculate(42, 14);
    
        textbox1.Text = z.ToString();
      }
    
      private Logic logic;
    }
    

    Sollte jetzt ein Unterformular auch die Logik-Daten benötigen, so gibt man das Objekt dann z.B. im Konstruktor weiter, d.h. es gibt immer nur genau 1 Instanz der Logik-Klasse (bei manchen Projekten kann es natürlich auch mehrere Logik-Objekte geben, z.B. in Form einer Liste, jedoch sollte dies eher die Ausnahme sein).



  • @TH69:

    Vielen Dank für die schöne Erklärung. 👍
    Das hat mir sehr geholfen, das deckt sich exakt mit dem überein, was ich meine schon in Erfahrung gebracht zu haben. Ich glaube ich habe das Prinzip nun endlich grundlegend verstanden und kann die Puzzelteile zusammensetzen.

    Das Ganze fungiert als riesige Kette, was ich etwas "unübersichtlich" finde, zumindest jetzt noch, wahrscheinlich aber auch nur, weil mir noch viele weitere Grundlagen fehlen ...).

    MFG
    Marco


Anmelden zum Antworten