Forum: PC-Programmierung C#: listBox1.Items.Add


von *GAST* (Gast)


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
  }

von pegel (Gast)


Lesenswert?

Kenne C# zwar nicht, aber kann es sein das ein listBox1 
update/neuzeichnen nötig ist?

von *GAST* (Gast)


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

von pegel (Gast)


Lesenswert?

Bist Du sicher das ein Button Ereignis nicht automatisch ein neuzeichnen 
auslöst?

von Chris R. (hownottobeseen)


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.

von pegel (Gast)


Lesenswert?


von *GAST* (Gast)


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...

von pegel (Gast)


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();

von *GAST* (Gast)


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
    }

von pegel (Gast)


Lesenswert?

Dann kann es ja eigentlich nur mit der Übergabe von object und event an 
die Funktion zu tun haben, denke ich mal.
Mehr fällt mir leider auch nicht ein....

von *GAST* (Gast)


Lesenswert?

pegel schrieb:
> Übergabe von object und event

was kann ich denn da ändern?

von Sam .. (sam1994)


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

von *GAST* (Gast)


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
    }

von Thomas E. (thomase)


Lesenswert?

*GAST* schrieb:
> CanMessage[]

Was verbirgt sich denn dahinter?

> Console.WriteLine(daten);
>     //listBox1.Items.Add("daten"); - Geht nicht!!

Und warum schreibst du in einer Forms-Anwendung auf die Konsole?

mfg.

von Thomas E. (thomase)


Lesenswert?

Samuel K. schrieb:
> Woher kommt das OnCanData Ereignis? Von dir? Wenn ja musst du mit Invoke
>
> das Event nochmal aufrufen.

Nur weil es OnCanData heisst, ist es kein Eventhandler. Das ist eine 
ganz normale Funktion.

mfg.

von Sam .. (sam1994)


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
    }

von *GAST* (Gast)


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

von Sam .. (sam1994)


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)

von *GAST* (Gast)


Lesenswert?

jo, das funktioniert. danke

von *GAST* (Gast)


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...

von Sam .. (sam1994)


Lesenswert?

Als Objekt kann man alles übergeben.
Nur: Wenn du das schreibst
1
listBox1.Items.Add(o);
wird intern die Object.ToString()-Methode aufgerufen und das als Text 
angezeigt.
Um die ID z.b. anzuzeigen musst du das Object casten:
1
listBox1.Items.Add((CanMessage)o).ID);

von Thomas E. (thomase)


Lesenswert?

Samuel K. schrieb:
> Ein Event ist übrigens "nur" eine Liste von Methoden.

Schwachsinn.

mfg.

von *GAST* (Gast)


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)

von eugler (Gast)


Lesenswert?

Thomas Eckmann schrieb:

> Und warum schreibst du in einer Forms-Anwendung auf die Konsole?

Für Debug Zwecke ist das doch OK. Wird halt in der VS Console 
ausgegeben.

von Sam .. (sam1994)


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.

von Thomas E. (thomase)


Lesenswert?

Samuel K. schrieb:
> Dann erklär mir mal was hier passiert:

Ich denke gar nicht dran.

Samuel K. schrieb:
> Komischerweise kann man alle Methoden namentlich aus dem Event
> rausholen.

Sehr komisch.
Aus dem Event kannst du gar nichts rausholen. Sondern aus EventArgs.

mfg.

von Sam .. (sam1994)


Lesenswert?

Thomas Eckmann schrieb:
> Sehr komisch.
> Aus dem Event kannst du gar nichts rausholen. Sondern aus EventArgs.

EventArgs ist leider der Basiscontainer für Ereignisdaten.

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

von Thomas E. (thomase)


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.

von Sam .. (sam1994)


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.

von Thomas E. (thomase)


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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.