I define a button like this:
Button info = new Button();
info.Command += Button_Command;
info.CommandName = "handleinfoclick";
info.CommandArgument = id;
And I tried to write a command handler here:
private void Button_Command(object sender, CommandEventArgs e)
{
Debug.WriteLine("HERE IN BUTTON COMMAND");
}
But the command handler is not being called. I have worked on this for a while and I haven't been able to find a solution. The button has to be defined in the codebehind because it is on a dynamic table and the function it calls will need the commandargument to interact with that row's data.
If it is web forms, then assigning server events dynamically will no work. I think the best approach is to assign events statically in your code and use some variables to define specific status. Then you can set the variables values and process them inside event and make decision to do some work.
Related
I'm having problems adding an event to an ImageButton. I have to create a set of buttons depending on a selected option from a DropDownList. The buttons are created successfully with Database data, but I'm can't attach the OnClick functionality.
The created buttons must share the same Handler.
protected void cmbServ_SelectedIndexChanged(object sender, EventArgs e) {
ServiceID = cmbServ.SelectedValue.ToString();
ServiceName = cmbServ.SelectedItem.ToString();
DataTable dtFirstTab = new DataTable();
dtFirstTab = mySQLConn.getTable(qryCarry); // LOAD DATA FROM DB
foreach (DataRow row in dtFirstTab.Rows) {
FTabBtn = "btn"+(Convert.ToInt32(row["SKU_Credito"])).ToString();
FTabIconURL = row["SKU_Icon"].ToString();
Panel dvFirstTab = new Panel();
dvFirstTab.CssClass = "col-xs-2";
ImageButton IB = new ImageButton();
IB.ID = FTabBtn;
IB.ImageUrl = FTabIconURL;
IB.Click += new ImageClickEventHandler(btnX_click); // <-- PROBLEM
dvFirstTab.Controls.Add(IB);
pnlIcons.Controls.Add(dvFirstTab); // pnlIcons exists in HTML
}
protected void btnX_click(object sender, ImageClickEventArgs e) {
string Obj = ((ImageButton)sender).ClientID;
Cantidad = Convert.ToInt32(Obj.Substring(3, (Obj.Length) - 3));
txtMonto.Text = "$" + Cantidad.ToString();
}
All the buttons appear correctly, but when I click on them they just fire a "submit" action, acting like there's no OnClick assigned.
No CodeBehid example:
If I add this line in HTML (I removed asp tags)
ImageButton ID="btn10" runat="server" ImageUrl="MontoLogo_10ST.png" OnClick="btnX_click"
It does work as intended.
Any ideas? Thanks a lot!
Creating controls dynamically in ASP.NET webforms usually seems easy at the beginning, but problems are very common when it comes to handling events. Even if you assign your event handler correctly, the event handler is not run in a postback until you re-create all the dynamic controls early in page lifecycle. This explains why the sample with the ImageButton on the ASPX works whereas the dynamically created buttons don't.
See this page for details on creating controls dynamically. The most important part is the warning that basically says: if you need to add dynamic controls, better don't.
Usually you can find a way to create all the necessary controls in markup, for instance using a Repeater control. The big advantage of the repeater is that you have control about the markup that is created.
The following sample outlines the necessary steps:
Place a repeater on your aspx-page. If pnlIcons serves no other purpose than being the container for the dynamically created buttons, substitute it by the repeater. Use the Header- and FooterTemplate properties to add the markup that surrounds the ImageButtons (e.g. the div for dvFirstTab).
Think about which data you need to assign to the image button. In your case, the fields "SKU_Credito" and "SKU_Icon" seem to be required.
Place the Image button in the ItemTemplate of the repeater and bind the properties "Id" and "ImageUrl" to the corresponding fields.
Add a Command event handler and bind the CommandArgument property to a value that helps you discern between the image buttons.
In the command event handler, you can use the CommandArgument to discover which button has been clicked. Add the appropriate code that handles the command.
In the SelectedIndexChanged event handler, read the data from the database and bind the repeater to the result. This creates the rows in the repeater with the ImageButtons.
Ok, I've found the reason. The event handling must be assigned in Page_Load event, so I moved everything inside a method and called it from Page_Load, calling it from "SelectedIndexChanged" doesn't work . It's working now.
Thanks!
So, I would double click here on my designer
and it should create me the code, but well it doesn't. And there is no value changed event in the events either.
So if anyone knows how to fix this, it would be nice. (I doubt it) so how would I get around this? How would I go on about creating the code myself that should be created when I double click on it?
Click the form or control that you want to create an event handler for.
In the Properties window(F4), click the Events button
In the list of available events, click the event that you want to create an event handler for.
In the box to the right of the event name, type the name of the handler and press ENTER.
Add the appropriate code to the event handler.
To create an event handler in the code editor
Switch to the code editor by using one of the following techniques:
Create a new method like:
private void buttonName_Click(object sender, EventArgs e) { ... }
In the file YourFormName.Designer.cs find your button and add
this.buttonName.Click += new System.EventHandler(this.buttonName_Click);
I have dynamically created button in C# using XAML.
The XAML:
<Grid Name="mainGrid" Grid.Row="1"></Grid>
and I had created button with this code in C#:
Button dugme = new Button();
dugme.Content = "tap me";
dugme.Tapped += dugme_Tapped;
mainGrid.Children.Add(dugme);
How can I now change button Content (text) from "tap me" to "tapped ok" in this event.
void dugme_Tapped(object sender, TappedRoutedEventArgs e)
{
//should I use binding?
}
Just as you set the Content property to "tap me" when you create the button, so too can you set it in the event handler:
void dugme_Tapped(object sender, TappedRoutedEventArgs e)
{
((Button)sender).Content = "tapped ok";
}
That said, you ask in a code comment "should I use binding?" and, since this is WPF, the default answer is "yes". But how exactly you would do that here is difficult to say, given the lack of context. It's not clear why you are adding the Button instance programmatically (doing which is itself non-idiomatic in WPF).
If guess if you feel you have a very good reason to eschew XAML-based initialization and binding for the creating of the Button instance, you may as well continue that approach for setting the Content property. In that case, the above example should work for you.
If you would like a more XAML-centric approach, you probably should ask a different question, starting with explaining clearly your scenario and asking how to initialize the button in a more WPF-like manner, as well as how to maintain the state of the Content property of that button.
As to whether you should use binding, this being XAML, almost certainly, it makes your code a lot easier to maintain by keeping the view and model separate, though you might have a good reason.
As to changing the text, you can just set the content property of your button in the event handler.
By default, the object that fired the event is passed as the 'sender' parameter of you function, so all you need is this:
void dugme_Tapped(object sender, TappedRoutedEventArgs e)
{
(sender as Button).Content = "tapped ok";
}
As your event handler.
I'm working on a project and I'm in a situation where the administrator needs to accept new users into the system. I've got a form that only admins can access, which shows a list of all the waiting applicants. I've found out how to create buttons at run time and how to add an event handler for the click event, but the handler requires a method by the same name to run.
Obviously I can't just put code for a method inside a for loop, unless I'm mistaken. How would I give the program the ability to support an potentially infinite amount of applicants?
void AcceptUsersAdminLoad(object sender, EventArgs e)
{
//FOR LOOP - To be finished. Will read an xml file to find out # to loop.
Button newButton = new Button();
newButton.Click += new System.EventHandler(newButtonClick);
newButton.Text = "Accept";
Panel1.Controls.Add(newButton);
}
private void newButtonClick (Object sender, System.EventArgs e){
}
This works, but as I've said, only for one button. As relatively painless as it would be to copy the method and append it's name with a number a hundred times, I'd prefer to find a way with support for more.
You can use that same method for all of your buttons! The sender parameter will tell you which button is the source, simply cast it to a button. You can store an ID of some sort in the .Tag() property of the button so you know who you are working with (when you create them, assign it).
private void newButtonClick (Object sender, System.EventArgs e){
Button btn = (Button)sender;
// ... do something with "btn" in here ...
}
Answer to the titular question: You don't create methods in a loop. You will occasionally create anonymous methods in a loop, but save that for later :).
To do what you want though: When you generate these buttons, they should all be pointing to the same event handler. The logic you want to run is the same, but the data is different.
How you get the data to the function is not trivial, one (hackish) way to do it is to store the related object (or its index) in the Tag property of the button, which you can then retrieve via the sender argument of the event handler.
I am new to C# and I am following this C# tutorial at the moment. In this tutorial I came across the exercise to develop a calculator.
A C# .Net Calculator - Design Stage
In the solution given in the exercise, each digit button was given a btn*_click method which can be generalized pretty easily.
(source: homeandlearn.co.uk)
How can we write the code, so that we can generalize these 10 functions? I though it can be done by modifying initializeComponent(), but comment about it says it should not be modified using code editor.
How can this problem be tackled.
You can tie all buttons to the same click event handler, and use sender to get the text:
private void btnAnyButton_Click(object sender, EventArgs e)
{
Button theButton = sender as Button;
txtDisplay.Text += theButton.Text;
}
The tutorial you posted is using the visual editor in visual studios. By default the designer will generate code with the convention {controlname}_{eventname} you can explicitly assign a different event name in the properties window, and all the buttons could share the same event method.
And then it looks like you could refactor this like:
private void btn_click(object sender, EventArgs e)
{
Button btn = sender as Button;
if(btn != null)
txtDisplay.Text += btn.Text;
}
I hope that helps.
You could generate these buttons dynamically from the code and assign them some value in the tag attribute. From there, you can hook them all up to the same event handler (we're talking about the number buttons, as in 0,1,2,3,4...). In the onClick event handler you would get the tag value of the caller and do what you have to do.
Pseudocode:
void onClick(Button caller){
int btnNb = (int) caller.Tag;
//do what you have to do
}
The tag attribute is not necessary but I find it cleaner than getting the button text and converting to an int.