VB.NET Button Click auslösen
Inhaltsverzeichnis
- 1 VB.NET Button Click auslösen
- 2 Sei gewarnt
- 3 Code – VB.NET Button Click auslösen
- 4 Der komplette Code – VB.NET Button Click auslösen
- 5 Downloads
VB.NET Button Click auslösen
In diesem Beitrag erkläre ich Dir, wie Du in VB.NET ein Button Click auslösen kannst – und zwar via Code!
Falls Du noch gar nicht mit dem Button-Steuerelement gearbeitet hast, kannst Du Dir unter folgendem Link meinen allgemeinen Beitrag zum Button Beispiel anschauen.
Wie Du in VB.NET einen Button zur Laufzeit erstellst, kannst Du in diesem Beitrag hier lernen.
Wir waren alle schonmal da
Ich glaube jeder .NET Entwickler kam zu Beginn seiner Entwickler-Karriere irgendwann an diesen Punkt.
Man hat etwas Tolles in seinen Button gecoded und es lief rund und ohne Fehler.
Nun kommt der Punkt, an dem man diese Funktionalität – versteckter Tipp löl – nun von anderer Stelle aus aufrufen möchte.
Kreative Spielereien
Im Laufe meiner Tätigkeit als Softwareentwickler im Bereich von VB.NET habe ich schon so Einiges gesehen.
Ein lustiges Beispiel war ein völliger VB.NET-Anfänger – daher seid in Gedanken nicht zu hart zu Ihm –, Welcher per codeorientierter Mausbewegung, etc. einen Button anklicken wollte 😂.
Zum Glück muss man nicht auf solche wirklich komplizierte Methoden zurückgreifen, wo kämen wir denn da hin!
Sei gewarnt
Ich möchte an dieser Stelle schonmal direkt den Spoiler erwähnen, dass das, was Du vorhast, nicht das Gelbe vom Ei ist!
Schreib Dich nicht ab, lern‘..
Ebenfalls möchte ich Dir hier aber keinen Vorwurf machen, denn Du wusstest es vermutlich einfach nicht besser, als Du danach gesucht hast.
Ich selbst kenne diese Problematik aus meiner Anfangszeit als .NET-Entwickler!
Selbstverständlich bin ich froh, dass Dich Deine Suche auf meine Seite und somit zu mir geführt hat 😊.
Meine Erfahrung – häufige Billligung
Umso lustiger wird es – zumeist – nachher, wie man den Wald vor lauter Bäumen nicht sehen konnte.
Manchmal ist es leider jedoch nicht unbedingt so lustig, vor allem, wenn gewisse Aktionen Folgen in: Wartung, Verständnis und mehr nach sich ziehen.
„Leider“ musste ich schon oft die Erfahrung machen, dass ehemalige Nachhilfe-Schüler, Internetforen-Nutzer, jedoch auch Kunden, etc. bewusst den falschen Weg wählten.
Oft hieß es: „Ja, ich weiß, dass das so nicht gut ist, aber das ist jetzt einfacher so!“
Code – VB.NET Button Click auslösen
Vorwort
Um das Beispiel nicht zu verkomplizieren habe ich auf tiefgehendere Sachen wie die z. B. die Dependency-Injection verzichtet.
Das Beispiel dürfte ohnehin Aufgrund der zusätzlichen Klassen für Anfänger schon etwas schwieriger sein.
Insgesamt hängt das natürlich vom individuellen Fortschritt in VB.NET und dem Verständnis dafür ab.
Manueller Aufruf der Handler-Sub – Erster Anlauf
Der erste deinerseits versuchte Anlauf könnte ungefähr wie folgt, ausgesehen haben, bzw. aussehen.
Du versuchst die Dir bekannte Sub des Button-Click Ereignishandlers einfach händisch, also via Code aufzurufen.
btnSearchBills_Click()
Doch während Du die Zeile fast fertig tippst, fällt Dir vermutlich auf, dass da was fehlt 🙈.
Die Sub, die Du aufrufen wolltest, erwartet nämlich zwei Parameter, Welche Dich eventuell vor die Frage stellen: „Wo bekomme ich Diese her?“.
sender As Object, e As EventArgs
In der Theorie ist die „Lösung“ ganz einfach – zumindest, wenn man weiß wie 😂:
sender As Object
Der „sender“ ist ja letztendlich nichts anderes, als das Objekt, Welches das Ereignis ausgelöst hat, worauf der Ereignishandler dann reagiert.
Da wir ja wissen, dass der Button letztendlich das Ereignis auslösen würde, können wir Diesen ja schonmal übergeben und machen somit Signatur-technisch nichts verkehrt.
e As EventArgs
Der andere fehlende Parameter, also der Zweite, ist da etwas komplizierter, obwohl ich auch schon beim Ersten sagen kann: „Wenn Du schon beim Sender auf die Lösung gekommen bist – Respekt!“
Die EventArgs-Klasse bietet ein „Shared-Readonly-Feld“ namens „Empty“ an.
Wie der Name schon verrät, handelt es sich bei dem dahinterstehenden „Wert“ praktisch um „leere EventArgs„, Welche wir dann mitliefern können, falls wir keine Event-Daten an sich benötigen.
btnSearchBills_Click(btnSearchBills, EventArgs.Empty)
PerformClick – Der einfache Ansatz
Im Endeffekt müssen wir es uns gar nicht so kompliziert wie oben machen.
Das Rumschlagen mit Parametern und das manuelle Aufrufen der Ereignishandler-Sub ist nicht notwendig, da der Button von Haus aus eine Möglichkeit bietet.
Die Methode, die wir suchen heißt *Trommelwirbel*: PerformClick:
btnSearchBills.PerformClick()
VB.NET Button Click auslösen – Der Richtige Ansatz
Im letzten und größten Abschnitt des Beitrages, kommen wir zum „richtigen“ Ansatz.
Ich halte die vorherigen Ansätze für einen schlechten Stil, bzw. für falsch, weil Sie meiner Meinung nach falsche Absichten widerspiegeln.
Wenn man möchte, dass ein Button Click via Code ausgelöst wird, dann möchte man nicht wirklich den Button auslösen, sondern den Code, der dahinter steckt!
Benötigte Steuerelemente
DataGridView
In dem DataGridview zeigen wir die für das Beispiel genutzten Testdaten in Form von Rechnungsdaten an.
2 Labels
Um die Textboxen optional mit Informationen zu bestücken
TextBox
Eine Textbox für die Suche nach einer Rechnung via Id.
TextBox
Dann noch eine weitere Textbox für die Suche nach Rechnungen via Kunden-Name.
Button
Einen Button für den Reset der Suchfelder
Button
Die Suchfunktion auszulösen wird von diesem Button gesteuert.
Eigenschaften
billService
Der Rechnungsservice ist – wie für Services bei Dependency Injection üblich, aber in diesem Fall nicht verwendet – eine „Private Property“.
Bills
Bei „bills“ handelt es sich um die Rechnungsdaten, die wir für dieses Beispiel testweise erstellen, laden und anzeigen werden.
Konstruktoren
New
Wir brauchen in unserem Fall nur den Standard-Konstruktor, Welchen wir für die Vorbereitung unseres Services und z. B. dem DataGridView nutzen.
Sub New() InitializeComponent() ' should be done with dependency injection like things ' just for displaying puporses.. billService = New BillService() Bills = New List(Of Bill) ConfigureBillDataGrid() End Sub
Methoden
ConfigureBillDataGrid
Ich denke diese Methode ist relativ selbsterklärend.
Private Sub ConfigureBillDataGrid() With dgvBills .AllowUserToAddRows = False .AllowUserToDeleteRows = False .AllowUserToResizeRows = False .AllowUserToOrderColumns = False .AllowUserToResizeColumns = False .ReadOnly = True .SelectionMode = DataGridViewSelectionMode.FullRowSelect .BackgroundColor = Color.White .RowHeadersVisible = False ' columns being added in visual designer.. End With End Sub
btnSearchBills_Click
Das ist die Click-Ereignishandler-Sub für den Button.
Private Sub btnSearchBills_Click(sender As Object, e As EventArgs) Handles btnSearchBills.Click SearchBills() End Sub
SearchBills
Das ist der Star des Tages, denn diese Sub ist die letztendliche Alternative zum „Button.PerformClick()“.
ShowBillsInDataGrid
Hier kommt der Code rein, der notwendig ist, um die Rechnungen anzuzeigen.
Private Sub ShowBillsInDataGrid(bills As List(Of Bill)) ' could/should be done with BindingList which supports AddRange ' but thats part of another tutorial :) ' so this is it for now dgvBills.DataSource = Nothing Me.Bills.Clear() Me.Bills.AddRange(bills) dgvBills.DataSource = Me.Bills End Sub
btnClearSearchFields_Click
Das ist der Ereignishandler für das Klick-Ereignis des Reset-Buttons für die Suchfelder.
Private Sub btnClearSearchFields_Click(sender As Object, e As EventArgs) Handles btnClearSearchFields.Click tbBillId.Clear() tbBillCustomer.Clear() ' or ' tbBillCustomer.Text = "" End Sub
SearchBox_KeyDown
Das ist die Methode, die auf die KeyDown-Ereignisse der 2 Suchfelder reagiert.
Wenn in einem der Suchfelder die Escape-Taste gedrückt wird, nehmen wir das als Befehl dafür, dass die Felder zurückgesetzt werden sollen.
Bei der Verwendung der Enter-Taste, lösen wir die Suche der Rechnungen erneut aus.
Private Sub SearchBox_KeyDown(sender As Object, e As KeyEventArgs) Handles tbBillId.KeyDown, tbBillCustomer.KeyDown If e.KeyCode = Keys.Escape Then Dim theTextBox = CType(sender, TextBox) theTextBox.Clear() ElseIf e.KeyCode = Keys.Enter Then SearchBills() End If End Sub
Bill-Klasse
Diese Klasse spiegelt eine einzelne Rechnung wieder.
Die Id ist denke ich selbstredend..
Der Customer wurde hier bewusst als String, statt als Objekt gewählt, um das Beispiel einfacher zu halten und den Fokus nicht zu verschieben.
Public Class Bill Public Property Id As Integer ' should be an object but for this example, made easier Public Property Customer As String Sub New() End Sub Sub New(id As Integer) Me.Id = id End Sub Sub New(id As Integer, customer As String) Me.Id = id Me.Customer = customer End Sub End Class
BillService-Klasse
Diese Klasse spiegelt einen Service für die Aktionen bezüglich der Rechnungen wieder.
Wenn eine neue Instanz der BillService-Klasse erzeugt wird, lade ich im Konstruktor deren Testdaten, ansonsten würden Diese natürlich aus einer Datenbank o. Ä. kommen.
Sie bietet eine Funktion an, um eine Rechnung via Id zu suchen.
Zusätzlich gibt es eine Funktion, um Rechnungen anhand des Kundennamens zu finden.
Um die Parameter dynamisch zu halten, habe ich ein Dictionary verwendet.
Wenn in Diesem ein Schlüssel namens „customer“ drin ist, wird der dahinter stehende Wert als Such-Name verwendet – Großschreibung nicht beachtend.
Public Class BillService Private bills As List(Of Bill) Sub New() bills = New List(Of Bill) MockupData() End Sub Private Sub MockupData() With bills .Add(New Bill(1, "John Doe")) .Add(New Bill(2, "Jane Doe")) .Add(New Bill(3, "Maximilian Maximum")) .Add(New Bill(4, "Jesus Christ")) .Add(New Bill(5, "Michael Jackson")) End With End Sub Public Function FindById(id As Integer) As Bill Return bills.SingleOrDefault(Function(x) x.Id = id) '' or the selfmade long version: 'For Each bill In bills ' If bill.Id = id Then ' Return bill ' End If 'Next 'Return Nothing End Function Public Function FindAllBy(criteria As Dictionary(Of String, String)) As List(Of Bill) Dim filteredBills = New List(Of Bill) ' first put all in filteredBills.AddRange(bills) ' filter for example by name If criteria.ContainsKey("customer") Then Dim customer = criteria.Item("customer").ToLower() filteredBills = filteredBills.Where(Function(x) x.Customer.ToLower().Contains(customer)).ToList() End If ' add more filtering.. Return filteredBills End Function End Class
Der komplette Code – VB.NET Button Click auslösen
In diesem Abschnitt findest du den kompletten Code zum Thema: VB.NET Button Click auslösen.
Public Class Form1 Private Property billService As BillService Public Property Bills As List(Of Bill) Sub New() InitializeComponent() ' should be done with dependency injection like things ' just for displaying puporses.. billService = New BillService() Bills = New List(Of Bill) ConfigureBillDataGrid() End Sub Private Sub ConfigureBillDataGrid() With dgvBills .AllowUserToAddRows = False .AllowUserToDeleteRows = False .AllowUserToResizeRows = False .AllowUserToOrderColumns = False .AllowUserToResizeColumns = False .ReadOnly = True .SelectionMode = DataGridViewSelectionMode.FullRowSelect .BackgroundColor = Color.White .RowHeadersVisible = False ' columns being added in visual designer.. End With End Sub Private Sub btnSearchBills_Click(sender As Object, e As EventArgs) Handles btnSearchBills.Click SearchBills() End Sub Private Sub SearchBills() Dim givenIdText = tbBillId.Text.Trim() Dim billId As Integer Dim bills As List(Of Bill) = New List(Of Bill) If Integer.TryParse(givenIdText, billId) Then Dim bill = billService.FindById(billId) If bill IsNot Nothing Then bills.Add(bill) End If ShowBillsInDataGrid(bills) ' OpenDetailForm() – Maybe? Return End If Dim searchCriteria = New Dictionary(Of String, String) Dim customerName = tbBillCustomer.Text.Trim() If Not String.IsNullOrWhiteSpace(customerName) Then searchCriteria.Add("customer", customerName) End If Dim searchResults = billService.FindAllBy(searchCriteria) bills.AddRange(searchResults) ShowBillsInDataGrid(bills) End Sub Private Sub ShowBillsInDataGrid(bills As List(Of Bill)) ' could/should be done with BindingList which supports AddRange ' but thats part of another tutorial :) ' so this is it for now dgvBills.DataSource = Nothing Me.Bills.Clear() Me.Bills.AddRange(bills) dgvBills.DataSource = Me.Bills End Sub Private Sub btnClearSearchFields_Click(sender As Object, e As EventArgs) Handles btnClearSearchFields.Click tbBillId.Clear() tbBillCustomer.Clear() ' or ' tbBillCustomer.Text = "" End Sub Private Sub SearchBox_KeyDown(sender As Object, e As KeyEventArgs) Handles tbBillId.KeyDown, tbBillCustomer.KeyDown If e.KeyCode = Keys.Escape Then Dim theTextBox = CType(sender, TextBox) theTextBox.Clear() ElseIf e.KeyCode = Keys.Enter Then SearchBills() End If End Sub End Class Public Class Bill Public Property Id As Integer ' should be an object but for this example, made easier Public Property Customer As String Sub New() End Sub Sub New(id As Integer) Me.Id = id End Sub Sub New(id As Integer, customer As String) Me.Id = id Me.Customer = customer End Sub End Class Public Class BillService Private bills As List(Of Bill) Sub New() bills = New List(Of Bill) MockupData() End Sub Private Sub MockupData() With bills .Add(New Bill(1, "John Doe")) .Add(New Bill(2, "Jane Doe")) .Add(New Bill(3, "Maximilian Maximum")) .Add(New Bill(4, "Jesus Christ")) .Add(New Bill(5, "Michael Jackson")) End With End Sub Public Function FindById(id As Integer) As Bill Return bills.SingleOrDefault(Function(x) x.Id = id) '' or the selfmade long version: 'For Each bill In bills ' If bill.Id = id Then ' Return bill ' End If 'Next 'Return Nothing End Function Public Function FindAllBy(criteria As Dictionary(Of String, String)) As List(Of Bill) Dim filteredBills = New List(Of Bill) ' first put all in filteredBills.AddRange(bills) ' filter for example by name If criteria.ContainsKey("customer") Then Dim customer = criteria.Item("customer").ToLower() filteredBills = filteredBills.Where(Function(x) x.Customer.ToLower().Contains(customer)).ToList() End If ' add more filtering.. Return filteredBills End Function End Class