Verwendung von "sender" und "e"

  • VB.NET

Es gibt 35 Antworten in diesem Thema. Der letzte Beitrag () ist von Artentus.

    Verwendung von "sender" und "e"

    Hi,

    Der Aufruf von Prozeduren zum Verarbeiten von Ereignissen, verwendet zwei Parameter, "sender" und "e". Für die Textbox "Tb" z.B.:

    VB.NET-Quellcode

    1. Private Sub Tb_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)
    2. Debug.Print("sender: " & sender.ToString & " e: " & e.ToString)
    3. ...


    Ich erhalte die folgende Ausgabe:

    sender: System.Windows.Forms.TextBox, Text: 7 e: System.EventArgs

    Dabei ist "7" etwa der Eingabewert in das Text Feld Tb.

    Dabei ist es vollkommen gleich WIE das Feld befüllt wurde, etwa durch Eingabe von der Tastatur oder durch einen Move in einer anderen Prozedur. Die Ausgabe ist immer die gleiche!

    Ich möchte aber wissen, wie das Feld befüllt wurde! Weil ein über die Tatatur eingegebener Wert verarbeitet werden muss, während ein Move das nicht auslösen darf (z.B damit keine unerwünschte Rekursion auftritt!).

    Welche Informationen enthalten denn die Variablen "sender" und "e"? Wie kann man diese Informationen extrahieren (abgesehen von .ToString)? Kann man damit meine o.a. Fragestellung lösen?

    Ich hab mir die Klassen "System.Object" und "System.EventArgs" im Objektkatalog (= Object Explorer?) angesehen. Aber irgendwie hilft mir das auch nicht weiter.

    LG
    Peter
    sender ist das Object bzw. Control welches das Event oder Prozedur aufruft. Weil du kannst ja mehrere Handles auf eine Prozedur legen und mittels des senders kannst du das Control bekommen was sie ausgelöst hat um ggf. an den Text Inhalt zu kommen.

    Das diese Prozedur aber auch bei einem Move Event ausgelöst wird, kann eigentlich nicht sein, außer du hast selbst den Handler für Move auf diese Prozedur gelegt.
    Normal sieht die von dir gezeigte Zeile auch anders aus, wenn sie vom Designer generiert wird

    VB.NET-Quellcode

    1. Private Sub Tb_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Tb.TextChange
    2. Debug.Print("sender: " & sender.ToString & " e: " & e.ToString)
    3. ...


    Damit wird nämlich definiert dass sie nur auf das TextChange Event reagieren soll.

    Peter329 schrieb:

    Weil ein über die Tatatur eingegebener Wert verarbeitet werden muss, während ein Move das nicht auslösen darf (z.B damit keine unerwünschte Rekursion auftritt!).

    Dann behandele eben die entsprechenden Ereignisse und nicht nur TextChanged. Entweder direkt im KeyDown und Move (eins wird verarbeitet und anderes nicht), oder du setzt in diesen beiden Ereignissen einen Flag (ein "Dim Flag as Boolean=False", klassenweit definiert), in KeyDown Flag auf True und in Move auf False. Und im "TextChanged"-Ereignis verarbeitest du alles nur, wenn Flag auf True gesetzt ist (und danach wieder auf False setzen).

    Was EventArgs enthalten, erfährst du, wenn du im Code "e." machst und dir die Auswahl anschaust, die IDE gibt dir sogar für jede Eigenschaft/Methode eine Beschreibung, wenn du mit der Maus draufgehst. Was e.ToString bewirken soll, entschließt sich mir nicht, nicht mal bei meiner sonst blühenden Phantasie.

    @Dodo
    Warum soll das Move den Event nicht ausgelöst haben, wenn dadurch der Text geändert wurde?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „sonne75“ ()

    @Dodo

    Jau, auf Tb liegen mehrere Handler:

    VB.NET-Quellcode

    1. Dim Tb As New TextBox
    2. Tb.Location = New Point(xt + ww * x, yt + ww * y)
    3. a.Width = ww
    4. ...
    5. AddHandler Tb.Click, AddressOf Tb_Click
    6. AddHandler Tb.DoubleClick, AddressOf Tb_DoubleClick
    7. AddHandler Tb.TextChanged, AddressOf Tb_TextChanged
    8. Me.Controls.Add(Tb)


    Für "Move" habe ich keinen Handler angefügt. Aber das Event TextChanged wird ausgelöst, wenn ich etwa Tb.Text = "7" ausführe. Die daraus resultierende Rekursion fange ich zur Zeit mit einem Schalter ab.

    @Sonne75

    Mhh, ich könnte schon statt TextChanged etwa KeyPress verwenden. Dann müsste ich mir aber den Inhalt des Feldes nach jeder Änderung "gemerkt" haben, damit ich feststellen kann, ob sich der Wert geändert hat! Da kann ich doch gleich mit einem Schalter arbeiten.

    Mit "e." kriege ich die Methoden von "e" angezeigt.

    sonne75 schrieb:

    Was e.ToString bewirken soll, entschließt sich mir nicht, nicht mal bei meiner sonst blühenden Phantasie.


    Die Methode .ToString benötige ich, um das Ding mit Debug.Print auszugeben! Die Anweisung Debug.Print(e) liefert die Fehlermeldung:

    Fehler 1 Der Wert vom Typ "System.EventArgs" kann nicht in "String" konvertiert werden.

    Peter329 schrieb:

    Dann müsste ich mir aber den Inhalt des Feldes nach jeder Änderung "gemerkt" haben, damit ich feststellen kann, ob sich der Wert geändert hat!

    Deswegen der zweite Vorschlag, dass du im KeyPress (o.ä.) nur die Erlaubnis setzt, die du im TextChanged prüfst.

    Peter329 schrieb:

    Die Methode .ToString benötige ich, um das Ding mit Debug.Print auszugeben!

    Also so weit habe ich es mit meinen Überlegungen auch geschafft. :P Ich meinte, was du dir davon versprichst, eine .ToString-Methode auf eine KLASSE anzuwenden.

    sonne75 schrieb:

    Ich meinte, was du dir davon versprichst, eine .ToString-Methode auf eine KLASSE anzuwenden.


    Na, ich würde gern wissen, welche Information im Objekt e enthalten sind! Gibt es 'Felder' in e, die man anzeigen kann? Wie kann ich das Objekt auswerten?

    Peter329 schrieb:

    welche Information im Objekt e enthalten sind!
    Setz einen Haltepunkt in die Prozedur.
    Dann klickst Du drauf und drückst Shift+F9. :D
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    sonne75 schrieb:

    Dann frag auch einzelne Eigenschaften ab, die du brauchst.


    Und was für Eigenschaften sind das? Wenn ich "e." eingebe, dann erhalte ich folgende Auswahl angeboten:

    Empty
    Equals
    GetHashCode
    GetType
    ReferenceEquals
    ToString

    Empty stellt ein Ereignis ohne Ereignisdaten dar, Equals und ReferenceEquals fragen auf Gleichheit von Objekten ab, ToString wandelt das Objekt in einen String um. Bleiben also noch die Methoden GetHashCode und GetType:

    VB.NET-Quellcode

    1. Debug.Print("HashCode: " & e.GetHashCode().ToString)
    2. Debug.Print("Type : " & e.GetType.ToString)


    Als Ausgabe erhalte ich damit z.B.

    Quellcode

    1. HashCode: 26568931
    2. Type : System.EventArgs


    Sagt mit das jetzt mehr als e.ToString?

    Ich verstehe einfach nicht, welche Erkenntnis mir die Auswertung des Parameters e bringt. Für mein Problem scheint mir das nicht so sonderlich viel zu sein, weil eben immer die gleichen Inhalte geliefert werden.


    Dann klickst Du drauf und drückst Shift+F9. :D


    Bei mir erscheint da nur der Wert: "System.EventArgs"

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Peter329“ ()

    Peter329 schrieb:

    Sagt mit das jetzt mehr als e.ToString?
    Das geht ohne Code:
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    EventArgs ist eine Basisklasse, die nicht wirklich Informationen bereithält. D.h. in diesem Event bekommst du keine anderen Informationen. Bei anderen Events kann es schon ganz anders aussehen, da ist die Klasse der EventArgumente eine andere (von EventArgs aber abgeleitet), die noch zusätzliche spezifische Parameter bereithält, die man dann abfragen kann.

    Was willst du eigentlich in deinem Event erfahren? Den Text bekommst du ja über die TextBox selbst, du weißt doch, welche TextBox das Ereignis ausgelöst hat. Wenn du mehrere Textboxen mit einem Ereignis behandelst, dann kriegst du es über den sender raus: du konvertierst ihn in die TextBox (da du weißt, dass es nur eine TextBox sein kann) und fragst sie dann ab:

    VB.NET-Quellcode

    1. Dim tb=DirectCast(sender, TextBox)
    2. Dim a = tb.Text


    P.S. Da siehst du es, Rod nutzt ein anderes Ereignis (MouseMove) und da sind noch zusätzliche Eigenschaften in den Argumenten dabei.

    sonne75 schrieb:

    Was willst du eigentlich in deinem Event erfahren?


    Also, das ist doch ganz einfach!

    Wenn das Feld Tb über das Keyboard mit einem geänderten Wert befüllt wird, dann möchte ich die Ereignisprozedur "Tb_TextChanged" ausführen, um den eingegebenen Wert zu verarbeiten.

    Es gibt einen "UNDO" Button. Wenn ich den betätige, soll von einem "Log" der vorangehende Wert restauriert werden. Dies geschieht durch die Anweisung

    Tb.Text = txtBeforeImage

    Dieser Move ändert das Feld Tb und löst damit ebenfalls die Ereignisprozedur "Tb_TextChanged" aus. In diesem Fall soll die Ereignisprozedur aber vorzeitig verlassen werden, weil keine Verarbeitung mehr erfolgen darf.

    Das Ganze handle ich derzeit mit einem Schalter ab. Das funktioniert - aber es ist eben nicht sehr schön!

    Ich wollte nun wissen, ob es Möglichkeiten gibt, das ohne Schalter zu lösen. Ob man also in der Prozedur "Tb_TextChanged" irgendwie abprüfen kann, ob der Inhalt von Tb.Text durch eine Tastatureingabe oder durch einen Move verändert wurde.

    Ich hoffe, ich hab mein Problem verständlich machen können.
    @Peter329:: Du kannst Dir eigene Events mit eigenen EventArgs erzeugen:
    MyEventArgs

    VB.NET-Quellcode

    1. Public Class Form2
    2. Public Event MyEvent(ByVal sender As System.Object, ByVal e As MyEventArgs)
    3. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    4. RaiseEvent MyEvent(Me, New MyEventArgs("bla", 17))
    5. End Sub
    6. End Class
    7. Public Class MyEventArgs
    8. Inherits EventArgs
    9. Public Property Text As String
    10. Public Property Value As Integer
    11. Public Sub New(ByVal txt As String, ByVal val As Integer)
    12. Text = txt
    13. Value = val
    14. End Sub
    15. End Class
    Da kannst Du reinpacken, was immer geht, und jemand muss das Event abonieren, hier z.B. Form1. :D
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Peter329 schrieb:

    Dieser Move

    Ich glaube, da liegt das Verständnisproblem. Was ist für dich denn "Move"? Was wird da "bewegt"? Es ist eine explizite Wertzuweisung, warum gefällt dir meine Lösung mit Flag nicht?

    Überall, wo du im Code die TextBox selbst setzt, setzt du den Flag auf False und im Event fragst du ihn eben ab(und setzt danach auf True).

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „sonne75“ ()

    Peter329 schrieb:

    Wenn das Feld Tb über das Keyboard mit einem geänderten Wert befüllt wird, dann möchte ich die Ereignisprozedur "Tb_TextChanged" ausführen, um den eingegebenen Wert zu verarbeiten.
    du scheinst nicht zu wissen, in welcher Textbox-Property der eingegebene Wert drinne ist.

    Die .Tostring-Funktion gibt ihn offensichtlich nicht zurück.

    sonne75 schrieb:

    warum gefällt dir meine Lösung mit Flag nicht?


    Ganz einfach: weil ich eine funktionierende Lösung mit einem Schalter schon habe. Ich will das ja gerade ohne Schalter lösen!

    @RFG

    Das mit den eigenen Events werde ich mir mal genauer anschauen. Das braucht aber ein bissl Zeit.

    ErfinderDesRades schrieb:

    du scheinst nicht zu wissen, in welcher Textbox-Property der eingegebene Wert drinne ist.


    Doch, das weiß ich: der Wert ist in Tb.Text und er ist in sender.ToString. So sagt mir das jedenfalls mein Debugger.
    Ohne Flag? Obwohl das die effizienteste Methode ist?

    Nun, du könntest im Event den StackTrace auswerten (der wird aber in den übergebenen Parametern nicht mitgeliefert, den müsstest du dir selbst besorgen - siehe Online-Hilfe) und darin prüfen, ob dem TextChanged-Event ein UI-Event vorausging oder eine Methode deines Programms.
    Weltherrschaft erlangen: 1%
    Ist dein Problem erledigt? -> Dann markiere das Thema bitte entsprechend.
    Waren Beiträge dieser Diskussion dabei hilfreich? -> Dann klick dort jeweils auf den Hilfreich-Button.
    Danke.