If I just drop a gridview on my page (AutoGenerateColumns = true) and then wire up a datasource on the code-behind, is there a way to get a click event to occur in each cell for certain columns? I know I can add buttons,checkboxes, etc from designer. I was just wondering if I can do it quick and easy with AutoGenerateColumns on.
void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DataControlFieldCell c = e.Row.Cells[2] as DataControlFieldCell;
//Maybe somehow put a click event here.
}
}
You can add client-side onclick event and pass cell's (TD) ID there:
c.Attributes["onclick"] = "myJSfunction('" + c.ClientID + "')";
And perform some logic on client side, calling server if needed either via some Button/LinkButton click() method, calling __doPostBack() on some other control or even making AJAX call.
Related
I have a DevExpress.XtraGrid.GridControl which has a column using DevExpress.XtraEditors.Repository.RepositoryItemLookUpEdit as cell editors.
When I select an item from the LookUpEdit, this does not cause any validation but does nothing until I click anywhere to make the Grid lose focus.
My desired behaviour would be that changing the LookUpEdit's selection immediately triggers a row validation event of the Grid.
How could this be achieved?
The official DevExpress Documentation tells to call the GridView's UpdateCurrentRow method:
There may be cases when you need to implement row validation. [...] To do so, handle the ColumnView.ValidateRow event. Note that you can also initiate row validation manually by calling the ColumnView.UpdateCurrentRow method.
I did this in the GridView's ValidatingEditor event handler:
private void gridView1_ValidatingEditor(object sender,BaseContainerValidateEditorEventArgs e)
{
(sender as GridView).UpdateCurrentRow();
}
However, now I can't add new rows to the Grid any more as end-user.
What would be the correct approach?
Update:
I am now listening to the GridView's CellValueChanging event and handling it like this:
private void gridView_CellValueChanging(object sender, CellValueChangedEventArgs e)
{
GridView gv = (sender as GridView);
gv.CellValueChanging -= gridView_CellValueChanging; // detach this event handler
gv.ActiveEditor.EditValue = e.Value;
gv.CellValueChanging += gridView_CellValueChanging; // re-attach handler
gv.CloseEditor();
}
I am sure this is not the way how one should do it, but it works for existing rows. However, it does not work on the "new row" - I still have to click anywhere else to apply changes that create a new entry. I want a new row to be created as soon as any cell of the "new row" got edited.
The editor in the cell is still open, you have to close it.
private void lookup_Closed(object sender, EventArgs e)
{
gvMyGrid.CloseEditor();
gvMyGrid.UpdateCurrentRow();
}
Previously when my RadGrid was not a batch edit grid I was able to use the grid's AddNewRecord button to redirect the user to another page with the following code:
protected void RadGrid1_ItemCommand(object sender, GridCommandEventArgs e)
{
if (e.CommandName == "InitInsert")
{
Response.Redirect(redirectUrl + "?ProductID=" + this.ProductId);
}
}
After I made my grid a batch edit grid the Add New Button doesn't go into the ItemCommand event anymore and instead tries adding an inline insert record row to the grid. Is there anyway I can still use this button and override its functionality to still redirect the user?
So I've tested this and confirmed what I suspected in the comments. When EditMode="Batch", the "Add New Record" button, along with others, no longer cause a postback. You can override this by removing the JavaScript of the OnClientClick in the RadGrid1_ItemCreated like so:
Add this to your RadGrid1 attributes:
OnItemCreated="RadGrid1_ItemCreated"
Code behind (note: there is actually a Button AND a LinkButton):
protected void RadGrid1_ItemCreated(object sender, Telerik.Web.UI.GridItemEventArgs e)
{
if (e.Item.ItemType == Telerik.Web.UI.GridItemType.CommandItem) {
//This is the icon with the plus (+) sign unless you've changed the icon
Button iconButton = e.Item.FindControl("AddNewRecordButton");
if (iconButton != null) {
iconButton.OnClientClick = "";
}
//This is the words "Add New Record" or whatever you've called it
LinkButton wordButton = e.Item.FindControl("InitInsertButton");
if (wordButton != null) {
wordButton.OnClientClick = "";
}
}
}
This should allow the postback to happen and the code you posted should be able to run.
I have dynamically created GridView in my .aspx from codebehind. I inserted a sql table in that GridView. Then I added one more button filed column. Here is the code:
ButtonField bf = new ButtonField();
bf.Text = "Details";
bf.ButtonType = ButtonType.Button;
DataTable table = new DataTable();
table.Load(reader);
GridView gv = new GridView();
gv.Columns.Add(bf);
gv.DataSource = table;
gv.DataBind();
Now I want to add a MouseClickEvent on this ButtonField, but there is no property Click or MouseClick. Is there any way to do this?
For a ButtonField inside GridView you specify CommandName:
bf.CommandName = "MyCommand";
And access it like:
void gv_RowCommand(Object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "MyCommand")
{
}
}
You may find it useful: ButtonField.CommandName Property.
When it comes to gridviews that each row have an action (like edit button, or details), I personally like to do the following:
Have a hidden button right after the GridView, this button has an onclick event (let's say OnDetailsButtonClick). So this button is the one that will be making the submission.
Create a Hidden Field that will be filled when an action from a row is clicked, so that the server side code will pick up which rowId that the action was performed on
Make every button in the gridview to have OnClientClick (lets say the javascript function called goToDetails(entityId))
so the javascript function will look like:
function goToDetails(entityId){
$("#HiddenEntityId").val(entityId);
$("#Button").click()
}
from the code behind you can get the row/Entity ID from the hidden field:
private void OnDetailsButton_Click(object sender, EventArgs e){
string entityId = HiddenEntityId.Value;
//now you can do whatever you like
}
You have to use 'Gridview.RowCommand' handle to enable custom script for a button in a ButtonField..
I.e.
1) add a 'CommandName' property to your buttonfield, this example assumes the CommandName = "Delete"
2)
Protected Sub GridView1_buttonsclicked(sender As Object, e As GridViewCommandEventArgs) Handles GridView1.RowCommand
If e.CommandName = "Delete" Then
'Delete clicked with index of " + e.CommandArgument.ToString
'Your code here, using the e.commandargument as the gridview index, then select column values using that index.
End If
End Sub
I have a datatable that I bind to a gridview. The columns are variable so I'd like to take advantage of AutoGeneratedColumns. I'd like to bind an image in certain condtions. What do I need to do?
void GridView1_RowCreated(object sender, System.Web.UI.WebControls.GridViewRowEventArgs e)
{
DataRowView drv = e.Row.DataItem as DataRowView;
if (drv != null)
drv[1] = new HtmlImage() { Src = "add.png" };
}
It sounds like the AutoGeneratedColumns property won't help you here because column types apply to the whole GridView; they are not calculated per-row.
You might be able to use a TemplateField with databinding to conditionally format the field for each row without writing any code.
If that doesn't get it done for you, I suppose you will have to write code. Bear in mind that the RowCreated event always fires (event on postback) when a row is created, but will only give you a non-null DataItem (e.Row.DataItem) when the GridView actually goes to its DataSource for databinding; if the GridView has cached its rendered state (in ViewState), the data item will be null. At that point, you would only be able to access the row's primary key fields by doing something like this: var keys = myGridView.DataKeys[rowIndex]; (The primary key fields are determined by the value you give the GridView's DataKeyNames property, and are stored in ViewState so that you can access them on postback.)
You would also be careful when modifying a column that is some type of DataBoundField (as most Fields are); since the RowDataBound event happens after the RowCreated event, any manual changes to the content of a row/cell you make in the RowCreated event handler are going to be clobbered by databinding when RowDataBound is fired.
That said, RowDataBound is probably the event you want.
The RowDataBound event will always give you a non-null DataItem, but only fires when real databinding happens (as opposed to "binding" from ViewState); so typically this event does not fire at all on postbacks. That's OK, though, since the GridView will remember its state for you.
If you must use code, it should probably look something like this:
//don't forget to attach this event handler, either in markup
//on the GridView control, in code (say, in the Page_Init event handler.)
protected void GridView1_RowDataBound(object sender, System.Web.UI.WebControls.GridViewRowEventArgs e)
{
//HtmlImage gives you a plain-vanilla <img> tag in the HTML.
//If you need to handle some server side events (such as Click)
//for the image, use a System.Web.UI.WebControls.Image control
//instead.
HtmlImage img = new HtmlImage() { Src = "path/to/image.jpg" };
e.Row.Cells[1].Controls.Add(img);
}
But, seriously, check out TemplateField first.
You can use RowDataBound event to process each row:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DataRowView drv = e.Row.DataItem as DataRowView;
if (drv != null)
{
// your code here...
}
}
}
For more information about this event see here
This should work, it uses the controls of the actual cell:
void GridView1_RowCreated(object sender, System.Web.UI.WebControls.GridViewRowEventArgs e)
{
HtmlImage img = new HtmlImage() { Src = "add.png" };
e.Row.Cells[1].Controls.Add(img);
}
I'm having trouble figuring out how could I use my imagebutton (see below) in my ITemplate to append the button's corresponding row data (ItemID) as a query string.
My ImageButton in my ITemplate:
ImageButton select_button = new ImageButton();
select_button.ID = "select_button";
select_button.ImageUrl = "~/Files/System/Icons/highlighter.png";
select_button.CommandName = "Select";
select_button.ToolTip = "Select";
container.Controls.Add(select_button);
Should I handle it in in the imagebutton's OnClick event (if so, is there a way to get the row where the button is located) or can I handle in in the GridView events (rowbinding, rowseleted, rowcommand, etc.)?
I'd be glad to elaborate more on my code upon request. ^ ^
You can set the ID in the CommandArgument property of your button control in the RowDataBound Event. Once you have an ID, you can track rows with it.
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DataRow dr = ((DataRowView)e.Row.DataItem).Row;
((Button)e.Row.FindControl("select_button")).CommandArgument = dr["IdColumn"].ToString();
}
}