in asp.net we can handle the RowDataBound event of the GridView control. this event fires when every row is added to the gridview.
i want to be able to handle this event in the gridview in a winforms application but i cannot find a similar event. my question is what is the event name that allows me to do the same as RowDataBound in asp.net?
The DataGridView doesn't have the same event handling as in ASP.NET.
What you could do is handle RowsAdded event, but note that more than one row can be added when this event fires. An example:
private void dataGridView1_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
{
for (int i = e.RowIndex; i < e.RowCount + e.RowIndex; i++)
{
Console.WriteLine("Row " + i.ToString() + " added");
}
}
Also, this event is a bit 'buggy' - at the moment when it's databound it may fire more than once for each row, but afterwards it behaves correctly - when you add a new row to data source, it's fired only once.
But, I should probably mention (even if that's not your original question), that if you used this event in ASPX to handle output formatting, than here an equivalent would actually be CellFormatting event - this event is called whenever the cells needs to display it's value.
There's no exact counterpart of the RowDataBound event for the WinForms
DataGridView. But if you'd like to change the displayed text before the
value of a cell is rendered, you could handle the CellFormatting event of
the DataGridView .
Related
I have an asp.net page with a list box on it. Multiple event handlers subscribe to its OnSelectedIndexChanged event.
When I change the SelectedIndex programmatically none of the events get fired.
Now a hack for this is to call each event handler, but this has already caused bugs since people didn't know they had to do this when adding a new event handler.
I can do this in a Winforms app and even when SelectedIndex is changed in code the events fire. Has anyone seen this before?
Take a look at the source code of the ListBox class and its base - ListControl. You will notice that the OnSelectedIndexChanged method is called from the RaisePostDataChangedEvent method. This means, that the SelectedIndexChanged event is only raised if the selected index was changed on the client side and the value stored in the ViewState does not equal data comes with the PostData. So, this event should not be raised if the SelectedIndex was changed in the server code.
As a workaround, I change data in database and complete events releated, then reload data with JavaScript.
Scenes: ASPxGridView control dtgRepair delete row, at the same time, ASPxComboBox value changed programmatically.
Server:
protected void dtgRepair_CustomCallback(object sender, ASPxGridViewCustomCallbackEventArgs e)
{
// update database here...
cmbMRType.SelectedIndex = 1;
dtgRepair.JSProperties["cpCallbackAction"] = "DeleteEntry";
}
Client:
function dtgRepair_EndCallback(s,e) {
if(cmbMRType.GetSelectedIndex() == 2 && dtgRepair.cpCallbackAction == "DeleteEntry" )
window.location.reload(true);
}
I have a GridView with dynamically created image buttons that should fire command events when clicked. The event handling basically works, except for the very first time a button is clicked. Then, the postback is processed, but the event is not fired.
I have tried to debug this, and it seems to me, that the code executed before and after the first click is exactly the same as for any other clicks. (With the exception that in the first click, the event handler is not called.)
There is some peculiarity in that: The buttons which fire the event are created dynamically through databinding, i.e. databinding must be carried out twice in the page lifecycle: Once on load, in order to make the buttons exist (otherwise, events could not be handled at all), and once before rendering in order to display the new data after the events have been processed.
I have read these posts but they wouldn't match my situation:
ASP.NET LinkButton OnClick Event Is Not Working On Home Page,
LinkButton not firing on production server,
ASP.NET Click() event doesn't fire on second postback
To the details:
The GridView contains image buttons in each row. The images of the buttons are databound. The rows are generated by GridView.DataBind(). To achieve this, I have used the TemplateField with a custom ItemTemplate implementation. The ItemTemplate's InstantiateIn method creates the ImageButton and assigns it the according event handler. Further, the image's DataBinding event is assigned a handler that retrieves the appropriate image based on the respective row's data.
The GridView is placed on a UserControl. The UserControl defines the event handlers for the GridView's events. The code roughly looks as follows:
private DataTable dataTable = new DataTable();
protected SPGridView grid;
protected override void OnLoad(EventArgs e)
{
DoDataBind(); // Creates the grid. This is essential in order for postback events to work.
}
protected override void Render(HtmlTextWriter writer)
{
DoDataBind();
base.Render(writer); // Renews the grid according to the latest changes
}
void ReadButton_Command(object sender, CommandEventArgs e)
{
ImageButton button = (ImageButton)sender;
GridViewRow viewRow = (GridViewRow)button.NamingContainer;
int rowIndex = viewRow.RowIndex;
// rowIndex is used to identify the row in which the button was clicked,
// since the control.ID is equal for all rows.
// [... some code to process the event ...]
}
private void DoDataBind()
{
// [... Some code to fill the dataTable ...]
grid.AutoGenerateColumns = false;
grid.Columns.Clear();
TemplateField templateField = new TemplateField();
templateField.HeaderText = "";
templateField.ItemTemplate = new MyItemTemplate(new CommandEventHandler(ReadButton_Command));
grid.Columns.Add(templateField);
grid.DataSource = this.dataTable.DefaultView;
grid.DataBind();
}
private class MyItemTemplate : ITemplate
{
private CommandEventHandler commandEventHandler;
public MyItemTemplate(CommandEventHandler commandEventHandler)
{
this.commandEventHandler = commandEventHandler;
}
public void InstantiateIn(Control container)
{
ImageButton imageButton = new ImageButton();
imageButton.ID = "btnRead";
imageButton.Command += commandEventHandler;
imageButton.DataBinding += new EventHandler(imageButton_DataBinding);
container.Controls.Add(imageButton);
}
void imageButton_DataBinding(object sender, EventArgs e)
{
// Code to get image URL
}
}
Just to repeat: At each lifecycle, first the OnLoad is executed, which generates the Grid with the ImageButtons. Then, the events are processed. Since the buttons are there, the events usually work. Afterwards, Render is called, which generates the Grid from scratch based upon the new data. This always works, except for the very first time the user clicks on an image button, although I have asserted that the grid and image buttons are also generated when the page is sent to the user for the first time.
Hope that someone can help me understand this or tell me a better solution for my situation.
A couple problems here. Number one, there is no IsPostBack check, which means you're databinding on every load... this is bound to cause some problems, including events not firing. Second, you are calling DoDataBind() twice on every load because you're calling it in OnLoad and Render. Why?
Bind the data ONCE... and then again in reaction to events (if needed).
Other issue... don't bind events to ImageButton in the template fields. This is generally not going to work. Use the ItemCommand event and CommandName/CommandArgument values.
Finally... one last question for you... have you done a comparison (windiff or other tool) on the HTML rendered by the entire page on the first load, and then subsequent loads? Are they EXACTLY the same? Or is there a slight difference... in a control name or PostBack reference?
Well I think the event dispatching happens after page load. In this case, its going to try to run against the controls created by your first data-binding attempt. This controls will have different IDs than when they are recreated later. I'd guess ASP.NET is trying to map the incoming events to a control, not finding a control, and then thats it.
I recommend taking captures of what is in the actual post.
ASP.NET is pretty crummy when it comes to event binding and dynamically created controls. Have fun.
Since in my opinion this is a partial answer, I re-post it this way:
If I use normal Buttons instead of ImageButtons (in the exact same place, i.e. still using MyItemTemplate but instantiating Button instead of ImageButton in "InstantiateIn", it works fine.
If I assert that DoDataBind() is always executed twice before sending the content to the client, it works fine with ImageButtons.
Still puzzled, but whatever...
I renew parameters of my DataSource for GridView on Button and loads event Page_Load()
and After it (or with it) GridView renews itself.
I need to rename Header rows but there is no event after Page Load.
more information about details here :
[On Button Click] I change DataSource and Bind it (SqlDataSource1.DataBind(); ) Then sure Page gone to Refresh elements.
[On Page_Load] GridView is changing data, but if I can't change Headers there because it's looking like loads after this function :(
[one more Button] I can add new button with a function - rename headers and it works correct everytime
protected void Button2_Click(object sender, EventArgs e)
{
// Stack overflow
DataRow T;
if (go)
if (GridView2.HeaderRow.Cells.Count != 0)
for (int i = 0; i < SQF.SQF.Permission.Rows.Count; i++)
{
T = SQF.SQF.Permission.Rows[i];
GridView2.HeaderRow.Cells[i].Text = (string)T["Caption1"];
WebMsgBox.Show((string)T["Caption1"]);
}
}
Trouble : I no need one more button for it, I need to rename header rows after I click button to change Data but I have no idea where I can do it.
thank you.
Well you could use Gridview DataBound event, like that:
<asp:GridView runat="server" ID="SomeID" OnDataBound="GridVIew_OnDataBound" ... />
The DataBound event occurs right after the databinding process for that particular control has completed.
After Page_Load there is an event Page.PreRender.
Maybe it will suit you.
EDIT.
All events of your components, such as GridView, are fired between Page.Load and Page.PreRender. Consider using RowDataBound and RowUpdated events.
I have a ASP.NET GridView that uses template columns and user controls to allow me to dynamically construct the datagrid. Now I'm implementing the event handler for inserting a row. To do that, I create an array of default values and add it to the data table which is acting as a data source. However, when my OnLoad event is fired on postback, all my template columns no longer have the user controls. My gridview ends up just being all blank with nothing in it and my button column disappears as well (which contains the add row, delete row and save buttons).
My row add event just does this:
public void AddDataGridRow()
{
List<object> defRow = new List<object>();
for (int i = 0; i < fieldNames.Count; i++)
{
defRow.Add(GetDefaultValueFromDBType(types[i]));
}
dt.Rows.Add(defRow);
}
It is fired from a button in a user control that's implement like this:
protected void Button1_Click(object sender, EventArgs e)
{
((Scoresheet)(this.Page)).AddDataGridRow();
}
My on load event does a bunch of stuff on first run to set the GridView up but I don't run that again by using the IsPostBack property to tell.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
Initialize();
}
Anyone have any hints as to why my user controls are vanishing?
You have to add the controls to the grid on every page_load, not just if it's (!Postback)
Do you have the EnableViewState=true on the usercontrols and the GridView?
Is the AddDataGridRow() method called by Initialize()? You basically have two options:
Bind the grid on every postback and do not use viewstate (performace loss)
Bind the Grid only the first time (if (!IsPostBack)), and make sure that your user controls keep their viewstate.
From your code, it is not clear whether the user controls keep viewstate and what they have in them. It is not even clear what is the execution order of the methods you've shown. There is no binding logic, so even if you keep adding rows, the grid may still not be bound. Please elaborate a bit and show the whole page codebehind.
This is probably a simple question but I am not an ASP.NET developer and I am quite stuck.
I have a simple search routine that returns between zero and several hundred results. Each of these must be added to the page as a button and I want to set the text of the button and the CommandArgument property so that when the button is clicked I can read the CommandArgument back and react accordingly.
However, when I click the button the event does not run at all. How can I get it to run?
The code for building the button list (simplified for readability) is as follows:
foreach (SearchResult sr in searchResults)
{
Button result = new Button();
result.Text = sr.name;
result.CommandArgument = sr.ID.ToString();
AccountSearchResults.Controls.Add(result);
result.Click += new EventHandler(SearchResultClicked);
AccountSearchResults.Controls.Add(new LiteralControl("<br/>"));
}
At the minute to test, I have popped a label on the form to put the CommandArgument in. This code is never executed though.
void SearchResultClicked(object sender, EventArgs e)
{
Label1.Text = ((Button)sender).CommandArgument;
}
You mentioned in another answer that you are adding these when a button is clicked. Looking at your code, I would suggest that you try setting a unique ID for each button added, then ensure that on loading the page that buttons with the same IDs and CommandArgument values are reloaded. When a dynamically loaded button is clicked, it must still exist on the page after postback for the event to fire.
I think the ID is all you need, plus your requirement for the CommandArgument). You could put the ID information in the ViewState if you can't get it repeat without a long search process.
Where are you adding this buttons?
if you are adding them inside another control then the event might be raising in the parent control. This happens on DataRepeaters and DataGrids for example.
I think you need to use the OnCommand event handler, rather than the OnClick i.e. try changing this:
result.Click += new EventHandler(SearchResultClicked);
to this:
result.Command += new EventHandler(SearchResultClicked);
UPDATE
Try changing the type of second argument to your event hander from EventArgs to CommandEventArgs. You might also have to set the CommandName property on your button i.e.
result.CommandName = "foo";