Entwickler-Ecke

WinForms - form wird dauernd initialisiert


yndaso - Di 23.12.08 12:08
Titel: form wird dauernd initialisiert
Hallo zusammen,

da ich c# Anfänger bin, steh ich nun an einem Problem an dem ich nicht mehr weiterkomme.
Ich hoffe mir kann hier


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:
namespace Konfigurator
{
  
  public partial class Form1 : Form
    {
           public Form1()
            {
              InitializeComponent();
              this.lstOutput.Items.Add("text:");
              MyClass _variable = new MyClass();
              _MyClass.Aktion();
            }
  
   private void btnSave_Click(object sender, EventArgs e)
          {
    ...
         }
  public void methode
    {
    ...
    }
   }

class MyClass
{
...
}


Ich möchte/muss jetzt in MyClass die Methode "methode" aus der Hauptklasse form1 aufrufen.
Wenn ich direkt in MyClass die Methode aufrufe sagt der Comiler "Methode im Kontext nicht vorhanden"
was ja eigentlich auch stimmt.
So nun habe ich gedacht ich vererbe einfach die methode mit "class myClass : Form1".
Der Compiler meckert jetzt nicht mehr und ich kann auf die methode zugreifen, allerdings baut sich
mein Fenster nun nicht mehr auf. Im Einzelstep habe ich gesehen, dass ich in einer Endlosschleife
bin und immer "InitializeComponent()" ausgeführt wird.

Soo nun meine ich mal gelesen zu haben, dass man auch einen 2. Konstruktor anlegen kann, indem fall eben ohne
"InitializeComponent();".
Aber wie vererbt, bzw. selektiert man dann den 2. Konstruktor?

Bitte um Hilfe, grübel und googel bereits schon seit Stunden!

Danke im Voraus!

Moderiert von user profile iconKha: C#-Tags hinzugefügt


JüTho - Di 23.12.08 13:06

Hallo,

Du solltest Dich wohl erst einmal mit Grundbegriffen befassen (hier stark vereinfacht und dadurch ungenau):

Klasse ist die Definition einer Art von Dingen, enthaltend interne Elemente sowie öffentliche Eigenschaften und Methoden, die es bei dieser Art immer gibt.

Ein Objekt/Instanz ist ein spezielles Ding dieser Art. Normalerweise kann mit den (öffentlichen) Eigenschaften und Methoden nicht über die Klasse gearbeitet werden, sondern nur für ein spezielles Objekt.

Eine Klasse ist in der Regel public deklariert und wird mit dem Namen der Klasse angegeben, ggf. mit dem Namen einer Klasse, von der sie abgeleitet hat (d.h. deren öffentliche Elemente ebenfalls gelten sollen):

C#-Quelltext
1:
2:
3:
4:
//  nur abgeleitet von object:
public class Automobile { ... }
//  abgeleitet von Automobile:
public class Truck : Automobile { ... }

Alles, was zu dieser Klasse gehört, muss innerhalb des Blocks {...} stehen.

Ein internes Element und eine dazugehörige Eigenschaft werden z.B. so deklariert:

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
  private int numberOfWheels = 4;   //  default-Wert
  private Color color;
  public int NumberOfWheels {
    get { return numberOfWheels; }
    set { if (value >= 3) numberOfWheels = value;
          else throw new ArgumentOutOfRangeException("Ein Auto hat mindestens 3 Räder"); }
  }


Eine Methode wird gekennzeichnet durch die runden Klammern, in denen Argumente stehen, und einen Rückgabewert, der auch void sein kann:

C#-Quelltext
1:
2:
3:
  public void ChangeColor(Color value) {
    this.Color = value;
  }


Ein Konstruktor ist eine spezielle Methode ohne Rückgabewert (denn es wird eine Instanz der betreffenden Klasse zurückgegeben):

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
  //  Standard-Konstruktor ohne Argumente:
  public Automobile() {
    this.Color = Color.Black;
  }

  //  zweiter Konstruktor mit Angabe einer Farbe:
  public Automobile(Color defaultColor) {
    this.Color = defaultColor;
  }


So, und jetzt vergleiche einmal die Konstruktion Deiner Klassen, nämlich von Form1 und MyClass, wozu gehört Methode, wo ist die Methode Aktion, und wie wird sie aufgerufen? Wozu dient die Variable _variable? Was willst Du eigentlich an welcher Stelle machen? (Konkrete Beschreibung, ggf. mit Pseudo-Code, wäre nützlich.)

Zur ausführlichen Einführung verweise ich auf OpenBook Visual C# [http://openbook.galileocomputing.de/visual_csharp/].

Gruß und Frohe Weihnachten! Jürgen

PS. Bitte gewöhne Dir von Anfang aussagekräftige Bezeichner an. Namen wie MyClass und _variable gehören verboten; spätestens in zwei Wochen weißt auch Du nicht mehr, worum es geht (wobei mir klar ist, dass das bei einem solchen Anfangsbeispiel unwichtig ist).


yndaso - Di 23.12.08 13:20

user profile iconJüTho hat folgendes geschrieben Zum zitierten Posting springen:
PS. Bitte gewöhne Dir von Anfang aussagekräftige Bezeichner an. Namen wie MyClass und _variable gehören verboten; spätestens in zwei Wochen weißt auch Du nicht mehr, worum es geht (wobei mir klar ist, dass das bei einem solchen Anfangsbeispiel unwichtig ist).

Ups! Die wirklichen Bezeichnungen sind anders, ich habe sie für den Beitrag hier nur abgeändert um es einfacher zu machen. Ist mir auch klar, dass ich bei den Bezeichnungen morgen nicht mehr weiß was gemeint ist..

Bei umbenennen ist mir ein Fehler unterlaufen, es heißt natürlich :


C#-Quelltext
1:
2:
     MyClass _variable = new MyClass();
              __variable.Aktion();


Aber das ändert nichts an der Tatsache, dass sich die Anwendung nicht aufbaut



Moderiert von user profile iconKha: Zitat gekürzt.
Moderiert von user profile iconChristian S.: C#-Tags hinzugefügt


JüTho - Di 23.12.08 13:28

user profile iconyndaso hat folgendes geschrieben Zum zitierten Posting springen:
Aber das ändert nichts an der Tatsache, dass sich die Anwendung nicht aufbaut

Sorry, das hatte ich vergessen zu erwähnen: Weil der Code zu Aktion() und Methode() und zum Aufruf von Form1 fehlt, kann ich zu dieser "Hauptfrage" noch gar nichts sagen, nur viel und dumm rumraten.

Jürgen


yndaso - Di 23.12.08 13:47

user profile iconJüTho hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconyndaso hat folgendes geschrieben Zum zitierten Posting springen:
Aber das ändert nichts an der Tatsache, dass sich die Anwendung nicht aufbaut

Sorry, das hatte ich vergessen zu erwähnen: Weil der Code zu Aktion() und Methode() und zum Aufruf von Form1 fehlt, kann ich zu dieser "Hauptfrage" noch gar nichts sagen, nur viel und dumm rumraten.

Jürgen


Ich poste hier mal alles und diesmal tu ich auch nichts umeditieren:


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:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
namespace Konfigurator
{
  
  
  public partial class Form1 : Form
    {
           public Form1()
            {
              InitializeComponent();
              this.lstOutput.Items.Add("Found drives on sercos address:");
              ScanSercos _SercAddr = new ScanSercos();
              _SercAddr.ScanDrives();
            }
     
      private void btnSave_Click(object sender, EventArgs e)
      {
       // Noch nichts, kommt aber noch
      }

      public void _opcSubscription_DataChanged(object subscriptionHandle, object requestHandle, ItemValueResult[] values)
      {
 
          if (this.InvokeRequired)
          {
              this.BeginInvoke(new DataChangedEventHandler(_opcSubscription_DataChanged), new object[] { subscriptionHandle, requestHandle, values });
              return;
          }
      }

    }

    class ScanSercos : Form1
    {
   
                
        private Opc.Da.Server _opcServer = null;
        private Opc.Da.Subscription _opcSubscription = null;

        public void ScanDrives()
        {
            Opc.URL oUrl = new Opc.URL("opcda://localhost/OPC.IwSCP.1");
            _opcServer = new Opc.Da.Server(new OpcCom.Factory(), oUrl);
            //Connect OPC
            try
                {
                    if (_opcServer != null && !_opcServer.IsConnected)
                        {
                           _opcServer.Connect();
                        }
                }
            catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }

            //Add Group
                try
                {
                    if (_opcServer.IsConnected)
                    {
                        Opc.Da.SubscriptionState state = new Opc.Da.SubscriptionState();
                        state.Active = true;
                        state.ClientHandle = 123;
                        state.Deadband = 0.0f;
                        state.Name = "ScanSercos";
                        state.UpdateRate = 1000;
                        _opcSubscription = (Opc.Da.Subscription)_opcServer.CreateSubscription(state);
                        _opcSubscription.DataChanged += new DataChangedEventHandler(_opcSubscription_DataChanged);
                    }
                    else
                    {
                        throw new Exception("No connection to OPC Server! Could not create Group!");
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                    if (_opcServer.IsConnected)
                    {
                        _opcServer.Disconnect();
                    }
   
                }
            //Add Items
                try
                  {
                    Opc.Da.Item[] opcItems = new Opc.Da.Item[2];

                    opcItems[0] = new Opc.Da.Item();
                    opcItems[0].ClientHandle = 1;
                    opcItems[0].Active = true;
                    opcItems[0].ItemName = "IndraMotion_MTX_P60,NC.MacodaParameter,100100001";
                    opcItems[0].ItemPath = "";
                    opcItems[1] = new Opc.Da.Item();
                    opcItems[1].ClientHandle = 1;
                    opcItems[1].Active = true;
                    opcItems[1].ItemName = "IndraMotion_MTX_P60,NC.MacodaParameter,105000004";
                    opcItems[1].ItemPath = "";

                    Opc.Da.ItemResult[] opcItemsResult = _opcSubscription.AddItems(opcItems);
                }
                catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                        if (_opcServer.IsConnected)
                        {
                            _opcServer.Disconnect();
                        }
                    }
                //Read Items
                try 
                    {
                        Opc.Da.Item[] opcItems = _opcSubscription.Items;
                        Array opcValueArray = null;
                        Array opcValueArray2 = null;
                        Opc.Da.ItemValueResult[] opcItemValueResult = _opcSubscription.Read(opcItems);
                        opcValueArray = opcItemValueResult[0].Value as Array;
                        opcValueArray2 = opcItemValueResult[1].Value as Array;
                    }
                catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                        if (_opcServer.IsConnected)
                        {
                            _opcServer.Disconnect();
                        }
                    }
        }        
    
    
    }

        
}

---------------------------------------------------------------------------------------------------
Ändere ich class ScanSercos : Form1
um auf class ScanSercos

So kommt eben die meldung das die Methode nicht vorhanden ist. Kommentier ich den aufruf auch noch aus, so startet das form dann schon, allerdings kann ich keine OPC items hinzufügen...


JüTho - Di 23.12.08 13:52

Ich werde erst dann genauer lesen, wenn der Code als C# markiert ist. Muss das denn immer ein Moderator nachholen? Bitte mitdenken und unter "Bereiche" das "C#" auswählen und den Plus-Button benutzen. Das kannst Du auch nachträglich erledigen! Jürgen


yndaso - Di 23.12.08 13:56

user profile iconJüTho hat folgendes geschrieben Zum zitierten Posting springen:
Ich werde erst dann genauer lesen, wenn der Code als C# markiert ist. Muss das denn immer ein Moderator nachholen? Bitte mitdenken und unter "Bereiche" das "C#" auswählen und den Plus-Button benutzen. Das kannst Du auch nachträglich erledigen! Jürgen

Versteh schon, erzieherische Maßnahme. mach ich bei meinen Kindern auch so :-)
Aber als Neuling muss man das erstmal finden...
Habs geändert


JüTho - Di 23.12.08 17:39

user profile iconyndaso hat folgendes geschrieben Zum zitierten Posting springen:
Versteh schon, erzieherische Maßnahme. mach ich bei meinen Kindern auch so :-)

Es geht doch nicht um eine erzieherische Maßnahme. Du möchtest Hilfe, aber erschwerst diese durch unleserliche Texte.

Auch jetzt passen die Einrückungen noch nicht richtig; aber das passiert auch durch das Kopieren vom Code-Editor in den Forums-Editor.

Wenn Du die Klasse ScanSercos von Form1 ableitest, passiert dieses: Application.Run erzeugt eine Instanz von Form1. Diese Instanz erzeugt eine Instanz von ScanSercos; dies ist eine Ableitung von Form1, also wird zuerst InitializeComponent von Form1 (als Basis von ScanSercos) aufgerufen, dann wird eine weitere (abhängige) Instanz von ScanSercos erzeugt. Auch diese Instanz ist eine Ableitung von Form1, also wird ... usw. Als Skizze:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
Program.cs
  Form1  
  =>  InitializeComponents()
    new ScanSercos : Form1
    =>  InitializeComponents()
      new ScanSercos : Form1
      =>  InitializeComponents()
        new ScanSercos : Form1

Verstehst Du jetzt dieses Problem?

Eine Ableitung von Form1 ist also zwangsläufig ein falsches Vorgehen.

Es bleibt also meine frühere Frage: Was sollen Methode() und Aktion() machen? Danach ist zu entscheiden, wohin sie gehören und wie die Zusammenarbeit zwischen ScanSercos und Form1 stattfinden soll. Klar ist momentan nur eins: ScanSercos darf nichts über Form1 wissen (insbesondere nicht über die ListBox oder was das ist); und Form1 holt "interne Informationen" aus der ScanSercos-Instanz vorzugsweise über Eigenschaften. Mehr möchte ich dazu aber noch spekulieren.

Gruß und Frohe Weihnachten! Jürgen


miniC# - Di 23.12.08 18:31

ich blicke durch den code da oben kaum durch, mir zu wirr :) allerdings glaube ich das problem verstanden zu haben, vielleicht hat user profile iconJüTho es schon geschrieben, aber der walloftext hier ist mir zu arbeitsintenisv in dieser besinnlichen zeit.

wenn du zwischen den beiden instanzen der beiden klassen (instanz von form und instanz von ScanSercos ) kommunizieren möchtest, dann solltest du der entsprechenden klasse einfach die instanz mitgeben :). ein guter ort dafür wäre der konstruktor. ein etwas sinnfreies beispiel :


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:
namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            r = new Random();
            _myObj = new myClass(this);// hier wird dein fensterli übergeben
        }
        private myClass _myObj; // die instanz deiner klasse
        private Random r;

        public void setCol()// eine etwas beknackte methode zum setzen der hintergrundfarbe der form über den umweg deiner klasse
        {
            _myObj.setBackColor (Color.FromArgb (255,(byte) r.Next (0,255),
                                                     (byte) r.Next (0,255),
                                                     (byte) r.Next (0,255)));
        }

        private void button1_Click(object sender, EventArgs e)
        {
            this.setCol();
        }
    }

    public class myClass
    {
        public myClass(Form parent) // der konstruktor deiner klasse nimmt die aktuelle fensterinstanz entgegen
        {
            _parent = parent;
        }

        private Form _parent;

        public void setBackColor(Color color)
        {
            _parent.BackColor = color;
        }
    }
}


JüTho - Di 23.12.08 18:41

user profile iconminiC# hat folgendes geschrieben Zum zitierten Posting springen:
wenn du zwischen den beiden instanzen der beiden klassen (instanz von form und instanz von ScanSercos ) kommunizieren möchtest, dann solltest du der entsprechenden klasse einfach die instanz mitgeben :).

Nein, bloß nicht! Was soll eine "sachbezogene Klasse" mit den Controls eines Formulars anfangen?

Ausführliche Erklärungen dazu stehen unter Kommunikation zwischen 2 Forms [http://www.mycsharp.de/wbb2/thread.php?threadid=5960] und den dortigen Hinweisen.

Jürgen