How to Make a Button Do Another Action When Pressed Again Vbnet
It's straightforward to wire upwardly event handlers to HTML events like onClick in your Blazor components, just how tin y'all pass additional information and unlike types of arguments?
Let'south say you desire to perform an activity when a button is clicked in Blazor.
This is straightforward to do using Blazor's event handling syntax.
Y'all can wire upwardly a method to an HTML chemical element event and Blazor will invoke that method every bit an upshot handler for said result.
@page "/sayHello" <button @onclick = "GreetMe" > Click me! </button > @Message @lawmaking { string Message { get; set; } void GreetMe() { Message = "Hullo"; } } Blazor volition invoke GreetMe when the button is clicked, and the user will come across a friendly (if somewhat unimaginative) greeting.
Your onclick event handler can optionally take a MouseEventArgs parameter which Blazor volition automatically include when information technology invokes the handler.
@code { string Message { get ; prepare ; } void GreetMe (MouseEventArgs args) { if (args.AltKey) Message = "Greetings" ; else Message = "Hullo" ; } } Now we can easily access extra details near the button click, for instance whether the user held downward the ALT key when they clicked, in this case displaying a different greeting if and so.
Different events will include different types of issue args—bank check out official docs for a complete list.
Passing Additional Information to your Event Handlers
Then far and so good, but what if y'all need to pass boosted data to your upshot handlers?
For instance, you might need to loop through a collection and render buttons for each item.
@page "/todoList" @using System.Diagnostics @foreach (var todo in Todos) { <p > @todo.Text </p > <!-- delete button goes here --> } @lawmaking { Listing <Todo > Todos { go; prepare; } = new List <Todo > { new Todo {Id = 1, Text = "Exercise this"}, new Todo {Id = 2, Text = "And this"} }; void Delete(Todo todo) { Debug.WriteLine($"Deleting {todo.Id}"); } private class Todo { public int Id { go; set; } public string Text { get; set; } } } This instance iterates over a list of Todos and shows text for each one.
Just what if nosotros desire to delete a Todo? We need a style to bespeak which Todo should be removed when we click a button for that specific Todo.
The standard way of calling an EventHandler won't work because we can't pass boosted arguments.
<button @onclick = "Delete" > 10 </push > Delete would have no idea which Todo to delete!
The answer is to utilize a lambda which will so consul to our Event Handler.
@foreach (var todo in Todos) { <p > @todo.Text </p > <button @onclick = "() => Delete(todo)" > X </button > } We've told Blazor to invoke an anonymous expression (represented here using the lambda syntax) which in turn calls Delete, passing the electric current Todo instance along for the ride.
Our Delete method will receive the relevant instance of Todo and can have whatever activity it deems necessary.
void Delete (Todo todo) { Debug. WriteLine ($"Deleting {todo.Id}" ) ; // hit the database and delete the todo } What if You Need the Original EventArgs besides?
What if you need both the original event args (such equally MouseEventArgs) and your own arguments (such as which Todo to delete).
For this, you can reference the original consequence args in your lambda and forward them forth.
<button @onclick = "args => Delete(todo, args)" > 10 </button > This finer frontward the arguments from the original event to your event handler, where you can do with them as you please.
void Delete (Todo todo, MouseEventArgs args) { Debug. WriteLine ($"Alt Key pressed: {args.AltKey} whilst deleting {todo.Id}" ) ; } Gotcha—Loops and Lambdas
Using lambdas inside forEach loops in your Blazor components volition more often than not work every bit you lot'd expect, but watch out if you decide to use a regular for loop with a loop variable instead.
@page "/loops" @using Organization.Diagnostics @for (int i = 0; i < five; i++) { <button @onclick = "()=>Log(i)" > @i </button > } @code { void Log(int i) { Debug.WriteLine($"Logging: {i}"); } } In this example we're merely looping from 0 to 5 and rendering a push button each time.
When you lot click the push you'll see the value of the loop variable i logged out in the debug console (in your IDE when you debug your app).
Now, interruption for a moment and consider what yous'd look to see when you run this code and click whatever of the buttons…
You'd exist forgiven for expecting to run into different numbers when you click different buttons.
Merely in reality you'll see…
…a whole load of 5s!
Whichever button y'all click, the debug output tells you i is always 5.
Foreign huh?!
This isn't a Blazor affair, only really the way bearding expressions and loops work in C#.
If y'all simply want to solve this and move on with your day, capturing i in a local variable inside the loop will do the trick.
@page "/loops" @using System.Diagnostics @for (int i = 0; i < 5; i++) { var j = i; <push @onclick = "()=>Log(j)" > @i </button > } @code { void Log(int i) { Debug.WriteLine($"Logging: {i}"); } } Here we capture the value of i in j, then employ j in our lambda expression.
To empathise why this happens requires a detour into the secret world of your C# compiler!
Understanding C# Loops and Lambdas
Here's a pseudo-code representation of the compiled C# code that volition be executed for our Blazor component. Typically nosotros don't demand to pay much attending to this, but in this example it'due south useful to see what's actually going on "under the hood".
[ Route ( "/loops" ) ] public class Loops : ComponentBase { void BuildRenderTree (RenderTreeBuilder _builder) { Loops.DisplayClass displayClass = new Loops.DisplayClass ( ) ; displayClass. this = this ; for (displayClass.i = 0 ; displayClass.i < 5 ; displayClass.i++ ) { _builder. openElement ( 'button' ) ; _builder. AddAttribute<MouseEventArgs> ( "onclick" , new Action (displayClass.handle) ) ; _builder. closeElement ( 'button' ) ; } } private void Log ( int i) { Debug. WriteLine ( string . Format ( "Logging: {0}" , ( object ) i) ) ; } [CompilerGenerated] private sealed course DisplayClass { public int i; public Loops this ; internal void handle ( ) { this . Log (i) ; } } } I've removed some particular and simplified the bodily lawmaking to keep this readable, but the gist is as follows.
The compiler generates a BuildRenderTree method for your component.
When this component is rendered, this method creates a single instance of something chosen DisplayClass.
Notation how BuildRenderTree just creates i case of this form (outside the loop), then references this single instance inside the loop.
Every time it goes round the loop, information technology will add a push to the RenderTreeBuilder and add together an onclick aspect for this button pointing to an Action.
Crucially, each action points to the same single instance of DisplayClass.
DisplayClass.i is and then incremented and we go around the loop again.
Past the time nosotros've been effectually the loop 5 times, the final number stored in i in the brandish class will be 5.
At present, when you run the app and click any of the buttons, all the deportment are pointing to the single instance of DisplayClass containing the value i (5 in this example).
So it'southward not surprising you see a lot of 5s for every push button click!
The pull a fast one on to overcome this is to capture the value of i into a local variable inside the for loop.
@page "/loops" @using Arrangement.Diagnostics @for (int i = 0; i < five; i++) { var j = i; <push @onclick = "()=>Log(j)" > @i </button > } In the resulting compiled code, a new instance of DisplayClass will now be created every time round the loop.
void BuildRenderTree (RenderTreeBuilder _builder) { for ( int index = 0 ; alphabetize < 5 ; ++index) { Loops.DisplayClass displayClass = new Loops.DisplayClass ( ) ; displayClass. this = this ; displayClass.j = alphabetize; _builder. openElement ( 'button' ) ; _builder. AddAttribute<MouseEventArgs> ( "onclick" , new Action (displayClass.handle) ) ; _builder. closeElement ( 'push' ) ; } } [CompilerGenerated] individual sealed class DisplayClass { public int j; public Loops this ; internal void handle ( ) { this . Log (j) ; } } This avoids the shared i value problem, and clicking the buttons works as yous would expect.
In Summary
Blazor enables you to handle HTML events such every bit onClick events via event handlers.
Yous can use lambdas to capture values (for case in a loop) and pass them on to your result handlers.
Dissimilar events pass different types of event args and then bank check out the official docs for details.
Scout out for those pesky for loops; if you employ the loop variable without capturing it to a local variable inside the loop yous'll fall foul of the C# compiler and see behavior you probably don't want or expect!
hardwickprehopecon.blogspot.com
Source: https://www.telerik.com/blogs/how-to-pass-arguments-to-your-onclick-functions-blazor
0 Response to "How to Make a Button Do Another Action When Pressed Again Vbnet"
Postar um comentário