Autor Beitrag
frenchcancan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 27



BeitragVerfasst: Do 30.06.11 12:00 
Hallo!
ich habe mir die Einträge über eigene events angeguckt und steige ich nicht ganz durch, ob es für meine Aufgabe nützlich wäre.
Ich erwarte Daten auf eine serieller Schnittstelle. Dafür gibt es ein Thread.
Je nachdem, wer Daten angefordert hat ist die Form1(configurationsdaten) oder die Form2(Processe) aktiv. Beide enthalten ein Treeview, der allmählich aufgebaut wird.
Diese Form1 und Form2 haben verschieden Klassen mit eigenen lokalen Variablen und Funktionen.
Die Klasse Treeview habe ich auch erweitert (Klasse MyTreeview), damit ich definieren kann, was passiert, wenn man einen Node anklickt udn verschiedenen anderen Funktionen hinzufügen konnte.

Jedenfalls möchte ich folgendes:
Wenn ich in dem Treeview einen Node anklicke, soll in der aufrufender Form ein Event ausgelöst werden, der ein neues Control erstellt.

Meine Frage sind:
1) In welcher Klasse definiere ich MyEvent?In Form1 und in Form2 oder nur in MyTreeview? oder in einer extra Klasse?
2) wie und wo löse ich dieses Event aus? von Dem Treeview aus, in der überschriebenen OnAfterSelect(TreeViewEventArgs e) Funktion?
3) ist ein eigenes Event überhaupt die richtige Lösung?

Zusammenfassung:
MyForm1 Form1 enthält ein Treeview1 der Klasse MYTreeview
MYForm2 Form2 enthält ein Treeview2 der Klasse MYTreeview

in der Klasse MyTreeview, möchte ich, dass ein Klicken auf einen Node in der aufrufenden Form ein ereignis auslöst.

Kann mir jemand ein kurzes Beispiel geben?
Danke schön

frenchcancan
norman2306
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 222
Erhaltene Danke: 16

Win XP, Win 7 64-Bit
C# 4.0 (VS2010)
BeitragVerfasst: Do 30.06.11 13:05 
Im TreeView gibt es bereits ein Event, welches ausgelöst wird, wenn man auf ein Item klickt. Es heißt: SelectedItemChanged.

Wenn du ein eigenes Event definieren möchtest, dann macht es in deinem Listener-Object Sinn, wo du die serielle Schittstelle abhörst. Dort könntest du ein DataReceived-Event deklarieren. Um dir die Funktion von Event mal ein bissl näher zu bringen, hier mal ein Beispiel:

Pseudo Code:

ausblenden volle Höhe 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:
    
    
public delegate void MSLDataReceived(object sender, MyMSLEventArgs e); //hier definierst du die Form, die dein Eventaufruf haben soll
    
public class MyMSLEventArgs : EventArgs  //hier kannst du eigene EventArgs definieren, also Infos die beim Auslösen mit übergeben werden
{
  hier kann man irgendwelche Felder definieren, die man gerne 
}
    
public class MySerialListener //Das ist mal ein Pseudobespiel für einen Listener-Object (wenn du sauber programmiert hast, ist dein Serial-Listener Thread nicht in deinem Fenster, sondern in einer separaten Klasse
{
   public event MSLDataReceived DataReceived; // hier sagen wir, dass dein Serial-Listener ein sichtbares Event enthalten soll, das man registrieren kann

   //Pseudofunktion, die den SerialPort abhorcht und ein Event schmeißt, wenn neue Daten kommen, die Funktion muss bei Initialisieren der Klasse natürlich erst aufgerufen werden und kann bzw. sollte ggf. in einen Thread verpackt werden
   private void Listen()
   {
      while(!dispatch)
      {
          ÜberwachenDesPortes

          if(neue Daten vorhanden)
          {
             //Event Auslösen:
             if(DataReceived != null//wenn Event registiert ist
             {
                DataReceived(thisnew MyMSLEventArgs()); // Dann auslösen.
             }
          }
      }
   }

}
    
public class MyForm : Form
{
   MySerialListener listener;

   public MyForm()
   {
      InitializeComponents();
      
      listener = new MySerialListener();
      
      //In der Form Event registrieren:
      listener.DataReceived += new MSLDataReceived(listener_DataReceived);
   }
  
   void listener_DataReceived(object sender, MyMSLEventArgs e)
   {
      tue was mit den Daten in Listener gerade empfangen hat.
   }
}
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4805
Erhaltene Danke: 1061

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Do 30.06.11 14:22 
Hallo norman2306,

beim TreeView unter WinForms heißt das Ereignis AfterSelect (und evtl. ist auch noch BeforeSelect interessant), bei WPF gibt es aber das SelectedItemChanged-Ereignis.


Und hallo frenchcancan,

so wie ich deinen Text verstehe benötigst du zwei Events, einmal von deiner Klasse, welche die serielle Schnittstelle ausliest (so wie norman2306 es beschrieben hat) und einmal in deinem TreeView (aber dafür kannst du das oben genannte Standard-Ereignis AfterSelect benutzen - außer du benötigst noch zusätzliche Daten).
frenchcancan Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 27



BeitragVerfasst: Fr 01.07.11 08:05 
Hallo! danke schön an beide.
Ein Event, der durch die Serielle Schnittstelle ausgelöst wird, habe ich schon. Ich hatte es gemacht mit

ausblenden C#-Quelltext
1:
deviceComPort.DataReceived += this.copo_readDataFromSerialPort;					
da wird automatisch die Funktion "copo_readDataFromSerialPort()" ausgeführt.
Das Funktioniert auch ganz gut.

In der Treeview Klasse habe ich ebenfalls schon den Event AfterSelected überschrieben:
in der Funktion
public class myTreeView : TreeView
{
.....
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
protected override void OnAfterSelect(TreeViewEventArgs e)
{
     Control currControl = e.Node.TreeView;
     TreeNode parentNode = null;
     TreeNode node = null;

     if (!(e.Node is TreeNode))
           return;
     else
        node = (TreeNode)e.Node;
// rausfinden, wer der aufrufende Formular ist
    cfg_linkedForm = (deviceConfigForm)e.Node.TreeView.FindForm();
    // first delete the current controls in the flowPanel
    cfg_linkedForm.flpPolosConfig.dflp_clearFlp();
....
}

Mein Problem ist nur, dass ich nicht weiß, von welcher Klasse der aufrufenden Formular ist, bzw. dass es verschiedene sein können. Die flowlayoutpanels und Listboxen dort haben verschiedene Namen.
Und ich dachte, dass es besser ist, wenn die Funktion AfterSelect der Klasse MyTreeview gar nichts vom aufrufenden Formular weiß, sondern nur dort ein Ereignis auslöst, dass der Formular selbst seine Controls verändert.

Sonst müsste ich ind er Klasse myTreeview Folgendes schreiben:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
if   (cfg_linkedForm == Form1)
  cfg_linkedForm.Form1.dflp1_clearFlp();
else
{
  if   (cfg_linkedForm == Form1)
      cfg_linkedForm.Form2.flp2_clearFlp();
}

und das ist wirklich nicht schön

Vielleicht hat jemand einen Tip, wie man es elegant löst
Danke schön
norman2306
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 222
Erhaltene Danke: 16

Win XP, Win 7 64-Bit
C# 4.0 (VS2010)
BeitragVerfasst: Fr 01.07.11 08:53 
Übergib in der Funktion als Parameter deine Form.
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4805
Erhaltene Danke: 1061

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Fr 01.07.11 09:12 
Hallo frenchcancan,

besser ist es, wenn der TreeView überhaupt nichts von der Form weiß, sondern du abonnierst einfach von der entsprechenden Form-Klasse aus das TreeView.AfterSelect-Ereignis und behandelst dann dort das Erstellen des Controls.
Und wie schon geschrieben: nur wenn du weitere Daten für das Ereignis benötigst, solltest du im TreeView.OnAfterSelect ein eigenes Ereignis werfen, das dann von der Form-Klasse behandelt wird (ich sehe anhand deines bisherigen Codes jedoch keine Notwendigkeit dafür).