C#: listBox1.Items.Add

Gast #2148732
Lesenswert?

Habe folgendes Problem: Beim Erhalt einer Msg funktioniert die Ausgabe 
mittels Colsole.WriteLine sehr gut. Auch das listBox1.Items.Add 
funktioniert mit einem Button. Aber erhaltene Msg's in die Listbox 
setzen geht nicht... Woran liegt das?
1
  void OnCanData(ref CanMessage[] cmsgArray, ref Int32 entries)
2
        {
3
            for(int i = 0; i < entries; i++)
4
            {               
5
                setzen(cmsgArray[i].ToString());
6
            }
7
        }
8
    
9
  void setzen(string daten)
10
  {
11
    Console.WriteLine(daten);
12
    //listBox1.Items.Add("daten"); - Geht nicht!!
13
  }
14
    
15
  void Button2Click(object sender, EventArgs e)
16
  {
17
    listBox1.Items.Add("Test"); // - Das Funktioniert!!
18
  }
Gast #2148750
Lesenswert?

Das benutze ich bei der Funktion vom Button ja auch nicht. Da 
funktioniert es ja.


P.S.: Bei  //listBox1.Items.Add("daten"); - Geht nicht!!
sind die Einführungsstriche nur zum Test da, um zu sehen, ob auch eine 
Ausgabe als normaler String wie beim Button möglich ist. Es geht aber 
weder als String "daten" noch als Argument daten
#2148757
Lesenswert?

Hi,

bekommst du beim Ausführen eine Exception, wenn du die Daten hinzufügen 
willst?

Je nachdem, wodurch dein OnCanData ausgelöst wird, kann es sein, dass 
dies durch einen anderen Thread geschieht, der nicht direkt auf den 
Thread des Fensters zugreifen kann.

Dann musst du die Methode zum Anzeigen per Invoke aufrufen.
Gast #2148775
Lesenswert?

pegel schrieb:
> Bist Du sicher das ein Button Ereignis nicht automatisch ein neuzeichnen
> auslöst?

???

pegel schrieb:
> Bist Du sicher das ein Button Ereignis nicht automatisch ein neuzeichnen
> auslöst?

???

Sorry, aber bin in C# absoluter Neuling, habe bisher nur in C (nicht 
C++) erfahrung.

Wenn ich listBox1.Items.Add("daten"); hinter Console.WriteLine(daten); 
ausführe, kommt genau eine CAN-Message in der Konsole, in der ListBox 
aber nichts. Wenn ich Console.WriteLine(daten); auskommentiere, kommt 
zyklisch eine Message in der Konsole, wie es sein sollte. Die 
Add-Funktion scheint also irgendwie das Programm zu unterbrechen...
Gast #2148805
Lesenswert?

Sieh dir mal das Beispiel an:
http://msdn.microsoft.com/en-us/library/system.windows.forms.listbox.aspx

besonders das:
1
   // Shutdown the painting of the ListBox as items are added.
2
   listBox1.BeginUpdate();
3
   // Loop through and add 50 items to the ListBox.
4
   for (int x = 1; x <= 50; x++)
5
   {
6
      listBox1.Items.Add("Item " + x.ToString());
7
   }
8
   // Allow the ListBox to repaint and display the new items.
9
   listBox1.EndUpdate();
Gast #2148827
Lesenswert?

schon wenn ich  listBox1.BeginUpdate(); über meine Schleife einfüge, 
passiert nichts mehr. Auch wenn ich keine Ausgabe in der List habe, 
sondern nur in der Konsole:
1
    void OnCanData(ref CanMessage[] cmsgArray, ref Int32 entries)
2
    {
3
      listBox1.BeginUpdate();
4
      for(int i = 0; i < entries; i++)
5
         {
6
           Console.WriteLine(cmsgArray[i].ToString());
7
         }
8
      listBox1.EndUpdate();
9
    }
#2148874
Lesenswert?

1. ListBox.Add zeichnet nach hinzufügen automatisch neu
2. BeginUpdate braucht man nicht, ist aber empfehlenswert bei mehreren 
Adds

Woher kommt das OnCanData Ereignis? Von dir? Wenn ja musst du mit Invoke 
das Event nochmal aufrufen.
Hast du EnableIllegalCrossThread = false gesetzt? Das sollte man nie 
machen, denn es ist Pfusch und führt manchmal zu komischen Fehler. 
Invoke ist der richtige Weg.

Schau dir zu Invoke mal das an: 
http://www.mycsharp.de/wbb2/thread.php?threadid=33113
Gast #2148903
Lesenswert?

Das hat mich jetzt schon ein ganzes Stück weitergebracht (auch wenn ich 
noch nicht ganz verstehe, warum ich das so machen muss...)

mit
1
    void OnCanData(ref CanMessage[] cmsgArray, ref Int32 entries)
2
        {
3
      for(int i = 0; i < entries; i++)
4
      {
5
        setzen(cmsgArray[i].Identifier.ToString());
6
        Console.WriteLine(cmsgArray[i].ToString());
7
      }
8
        }
9
    
10
    void versuch ()
11
    {
12
      listBox1.Items.Add("Text");
13
    }
14
    
15
    void setzen(string daten)
16
    {
17
      Console.WriteLine(daten);
18
      listBox1.Invoke (new MethodInvoker (versuch));
19
    }

funktioniert es, dass bei jeder Msg der String "Text" in der Listbox 
eingefügt wird, allerdings bekomme ich es nicht hin, dass die Funktion 
versuch() mit einem Argument, nämlich den daten aufgerufen wird. Da 
kommt es immer zu fehlern.:
1
    void versuch (string daten)
2
    {
3
      listBox1.Items.Add("Text");
4
    }
5
    
6
    void setzen(string daten)
7
    {
8
      Console.WriteLine(daten);
9
      listBox1.Invoke (new MethodInvoker (versuch(daten)));
10
    }
#2148960
Lesenswert?

Thomas Eckmann schrieb:
> Nur weil es OnCanData heisst, ist es kein Eventhandler. Das ist eine
> ganz normale Funktion.

Klar, aber irgendwie wird sie auch aufgerufen. Und da das mit Invoke 
funktioniert war es auch ein anderer Thread.

Ein Event ist übrigens "nur" eine Liste von Methoden.

Du musst natürlich auch den String übergeben.
1
    void versuch (object o, EventArgs e)
2
    {
3
      listBox1.Items.Add(o);
4
    }
5
    
6
    void setzen(string daten)
7
    {
8
      Console.WriteLine(daten);
9
      listBox1.Invoke (new EventHandler(versuch), new object[]{daten, null});
10
    }
Gast #2148994
Lesenswert?

Samuel K. schrieb:
> Du musst natürlich auch den String übergeben.

mit deiner Lösung kommt der Fehler

Keine Überladung für "versuch" stimmt mit dem Delegaten 
"System.Windows.Forms.MethodInvoker" überein. (CS0123) - 
C:\Users\Marcel\Documents\SharpDevelop 
Projects\canuir\canuir\MainForm.cs:59,21
#2149006
Lesenswert?

bei mir klappt es:

Form mit Backgroundworker und listbox
1
        private void listBox1_Click(object sender, EventArgs e)
2
        {
3
            backgroundWorker1.RunWorkerAsync();
4
        }
5

6
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
7
        {
8
            listBox1.Invoke(new EventHandler(Set), new object[] { "Hallo", null });
9
        }
10

11
        void Set(object o, EventArgs e)
12
        {
13
            listBox1.Items.Add(o);
14
        }

Versuch muss so aussehen: void XXX(object XXX, EventArgs XXX)
Gast #2149050
Lesenswert?

eine Frage habe ich doch nochmal:
1
    void OnCanData(ref CanMessage[] cmsgArray, ref Int32 entries)
2
    {
3
      for(int i = 0; i < entries; i++)
4
      {
5
        setzen(cmsgArray[i]);
6
      }
7
    }
8
    
9
    void versuch (object o, EventArgs e)
10
    {
11
      listBox1.Items.Add(o);
12
    }
13
    
14
    void setzen(CanMessage daten)
15
    {
16
      listBox1.Invoke (new EventHandler(versuch), new object[]{daten, null});
17
    }

Das Array daten wird jetzt als Objekt übergeben, ist aber vom Typ 
CanMessage. Kann ich das als solchen übergeben, damit ich mir in 
versuch() aussuchen kann, welchen teil ich von cmsgArray[i] übergebe? Es 
gibt da z.b. .ID, .len, .data etc...
Gast #2149122
Lesenswert?

kann es sein, dass wir verschidene IDE's benutzen? Ich habe SharpDevelop 
und es kommen diese Fehler Fehler:

"int" enthält keine Definition für "Identifier", und es konnte keine 
Erweiterungsmethode "Identifier" gefunden werden, die ein erstes 
Argument vom Typ "int" akzeptiert (Fehlt eine Using-Direktive oder ein 
Assemblyverweis?). (CS1061)

Nur assignment-, call-, increment-, decrement- und "new 
object"-Ausdrücke können als Anweisung verwendet werden. (CS0201)

(Ich habe das von Samuel K. mit dem casting probiert)
#2149139
Lesenswert?

Thomas Eckmann schrieb:
> Schwachsinn.

Dann erklär mir mal was hier passiert:
1
using System;
2
namespace ConsoleApplication1
3
{
4
    class Program
5
    {
6
        static void Main(string[] args)
7
        {
8
            Test += new EventHandler(Test1);
9
            Test += new EventHandler(Test2);
10

11
            Test.Invoke(null, null);
12

13
            foreach (Delegate d in Test.GetInvocationList())
14
                Console.WriteLine(d.Method);
15
        }
16
        static event EventHandler Test;
17
        static void Test1(object o, EventArgs e)
18
        {
19
            Console.WriteLine("Test1");
20
        }
21
        static void Test2(object o, EventArgs e)
22
        {
23
            Console.WriteLine("Test2");
24
        }
25
    }
26
}
Komischerweise kann man alle Methoden namentlich aus dem Event 
rausholen.

*GAST* schrieb:
> kann es sein, dass wir verschidene IDE's benutzen? Ich habe SharpDevelop
> und es kommen diese Fehler Fehler:

Ja, das sollte dem Compiler aber egal sein.

Ich hab eine Klammer vergessen. Füg mal noch eine nach Add ein.
#2149274
Lesenswert?

Samuel K. schrieb:
> Das Event Test ist vom Type EventHandler. Und von diesem kann ich mir
> ein Array zurückgeben lassen, dass alle registrierte Methoden enthält.

Auch wenn es von der Deklaration her so aussieht, aber "Test" ist kein 
event vom Typ "EventHandler", sondern einfach nur ein Event.
"EventHandler" ist der Delegate, der die Verbindung herstellt zwischen 
dem Event "Test" zum Eventhandler (Test1(object o, EventArgs e)), also 
der Funktion, die mit dem Event aufgerufen wird.
Bisschen blöde Namensgebung.
Vielleicht hätten sie den Delegate nicht "EventHandler" sondern 
"DefaultDelegate" nennen sollen.

Damit weiss das Betriebssystem dann, wie mit dem aufgetretenen Event zu 
verfahren ist. Nämlich woher und mit welchen Daten wohin.

.NET Framework-Entwicklerhandbuch, Ereignisse und Delegaten  :

Ein Ereignis ist eine Meldung, die von einem Objekt gesendet wird, um 
das Auftreten einer Aktion zu signalisieren. Die Aktion kann durch 
Benutzerinteraktionen wie einen Mausklick oder durch andere 
Programmlogik ausgelöst worden sein. Das Objekt, das das Ereignis 
auslöst, wird als Ereignissender bezeichnet. Das Objekt, das das 
Ereignis abfängt und darauf reagiert, wird als Ereignisempfänger 
bezeichnet.


.NET Framework-Klassenbibliothek, EventHandler-Delegat

Das Ereignismodell von .NET Framework basiert auf dem Vorhandsein eines 
Ereignisdelegaten, der ein Ereignis mit dem entsprechenden Handler 
verbindet. Zum Auslösen eines Ereignisses werden zwei Elemente benötigt:

Ein Delegat, der die Methode identifiziert, mit der auf das Ereignis 
reagiert wird.

Eine Klasse, die die Ereignisdaten enthält.

Der Delegat ist ein Typ, der eine Signatur definiert, also den Typ des 
Rückgabewerts und die Typen der Parameterliste für eine Methode. Sie 
können den Delegattyp zum Deklarieren einer Variablen verwenden, die auf 
eine beliebige Methode verweisen kann, die die gleiche Signatur wie der 
Delegat aufweist.

In der Standardsignatur eines Ereignishandlerdelegaten wird eine Methode 
definiert, die keinen Wert zurückgibt. Der erste Parameter der Methode 
ist vom Typ Object und verweist auf die Instanz, die das Ereignis 
auslöst. Der zweite Parameter ist vom Typ EventArgs abgeleitet und 
enthält die Ereignisdaten. Wenn das Ereignis keine Ereignisdaten 
generiert, ist der zweite Parameter einfach eine Instanz von EventArgs. 
Andernfalls ist der zweite Parameter ein benutzerdefinierter Typ, der 
vom Typ EventArgs abgeleitet ist und alle Felder oder Eigenschaften 
bereitstellt, die zum Speichern der Ereignisdaten benötigt werden.

EventHandler ist ein vordefinierter Delegat, der eine spezielle 
Ereignishandlermethode für ein Ereignis darstellt, das keine Daten 
generiert. Wenn Ihr Ereignis Daten generiert, müssen Sie einen 
benutzerdefinierten Ereignisdatentyp bereitstellen und entweder einen 
Delegaten erstellen, bei dem der Typ des zweiten Parameters Ihrem 
benutzerdefinierten Typ entspricht, oder die generische 
EventHandler-Delegatklasse verwenden und den Parameter für den 
generischen Typ durch den benutzerdefinierten Typ ersetzen.

Um das Ereignis der Ereignisbehandlungsmethode zuzuordnen, fügen Sie dem 
Ereignis eine Instanz des Delegaten hinzu. Der Ereignishandler wird bei 
jedem Eintreten des Ereignisses aufgerufen, sofern der Delegat nicht 
entfernt wird.

mfg.
#2149325
Lesenswert?

Thomas Eckmann schrieb:
> Auch wenn es von der Deklaration her so aussieht, aber "Test" ist kein
> event vom Typ "EventHandler", sondern einfach nur ein Event.

Test.GetType() liefert allerdings System.EventHandler.
Entweder ist hier Mist gebaut worden oder Test ist doch vom Type ein 
EventHandler.

Im Text steht zwar nichts darüber, aber das trotzdem müssen intern alle 
registrierten Methoden aufgerufen werden.

Bleiben wir bei der ursprünglichen Frage: Warum kann man ein Event nicht 
als eine Art Liste bezeichnen?
Dafür spricht, dass man Methoden hinzufügen und entfernen und alle 
Methoden abrufen kann.
#2149351
Lesenswert?

Samuel K. schrieb:
> Warum kann man ein Event nicht
> als eine Art Liste bezeichnen?

Natürlich kannst du das als "eine Art Liste" bezeichnen. Zur 
Veranschaulichung mag das ja auch nützlich sein. Aber exakte Definition 
ist das nicht.

"EventHandler" ist der Standard-Delegate. Mit diesem Delegate, oder auch 
einem selbstdefinierten, wird der Event verbunden und wird mit dessen 
Eigenschaften auf Wanderschaft geschickt. Der Event bleibt aber ein 
Event und wird nicht zum Delegate.

mfg.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren