I have a gridview and I need to make an event fire when a row is clicked.
Is there an existing GridView event I need to bind to to make this happen?
Here's something I prepared earlier:
public class RowClickableGridView : GridView
{
public Style HoverRowStyle
{
get { return ViewState["HoverRowStyle"] as Style; }
set { ViewState["HoverRowStyle"] = value; }
}
public bool EnableRowClickSelection
{
get { return ViewState["EnableRowClickSelection"] as bool? ?? true; }
set { ViewState["EnableRowClickSelection"] = value; }
}
public string RowClickCommand
{
get { return ViewState["RowClickCommand"] as string ?? "Select"; }
set { ViewState["RowClickCommand"] = value; }
}
public string RowToolTip
{
get
{
if (!RowToolTipSet) return string.Format("Click to {0} row", RowClickCommand.ToLowerInvariant());
return ViewState["RowToolTip"] as string;
}
set
{
ViewState["RowToolTip"] = value;
RowToolTipSet = true;
}
}
private bool RowToolTipSet
{
get { return ViewState["RowToolTipSet"] as bool? ?? false; }
set { ViewState["RowToolTipSet"] = value; }
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
foreach (GridViewRow row in Rows)
{
if (row.RowType != DataControlRowType.DataRow) continue;
if (EnableRowClickSelection && row.RowIndex != SelectedIndex && row.RowIndex != EditIndex)
{
if (string.IsNullOrEmpty(row.ToolTip)) row.ToolTip = RowToolTip;
row.Style[HtmlTextWriterStyle.Cursor] = "pointer";
PostBackOptions postBackOptions = new PostBackOptions(this,
string.Format("{0}${1}",
RowClickCommand,
row.RowIndex));
postBackOptions.PerformValidation = true;
row.Attributes["onclick"] = Page.ClientScript.GetPostBackEventReference(postBackOptions);
foreach (TableCell cell in row.Cells)
{
foreach (Control control in cell.Controls)
{
const string clientClick = "event.cancelBubble = true;{0}";
WebControl webControl = control as WebControl;
if (webControl == null) continue;
webControl.Style[HtmlTextWriterStyle.Cursor] = "Auto";
Button button = webControl as Button;
if (button != null)
{
button.OnClientClick = string.Format(clientClick, button.OnClientClick);
continue;
}
ImageButton imageButton = webControl as ImageButton;
if (imageButton != null)
{
imageButton.OnClientClick = string.Format(clientClick, imageButton.OnClientClick);
continue;
}
LinkButton linkButton = webControl as LinkButton;
if (linkButton != null)
{
linkButton.OnClientClick = string.Format(clientClick, linkButton.OnClientClick);
continue;
}
webControl.Attributes["onclick"] = string.Format(clientClick, string.Empty);
}
}
}
if (HoverRowStyle == null) continue;
if (row.RowIndex != SelectedIndex && row.RowIndex != EditIndex)
{
row.Attributes["onmouseover"] = string.Format("this.className='{0}';", HoverRowStyle.CssClass);
row.Attributes["onmouseout"] = string.Format("this.className='{0}';",
row.RowIndex%2 == 0
? RowStyle.CssClass
: AlternatingRowStyle.CssClass);
}
else
{
row.Attributes.Remove("onmouseover");
row.Attributes.Remove("onmouseout");
}
}
}
protected override void Render(HtmlTextWriter writer)
{
base.Render(writer);
foreach (GridViewRow row in Rows)
{
if (row.RowType == DataControlRowType.DataRow)
{
Page.ClientScript.RegisterForEventValidation(row.ClientID);
}
}
}
}
You then hook into the standard row command events...
Some javascript programming will be required in order to make this happen.
Basically you are going to have to handle the click event for the row(is some browsers the row does not have a click event so you might have to handle the click event of the tds... time to invest in an ajax framework!)
You will then from javascript have to fire a postback with the row index as a parameter. See encosia(a great site for ASP.Net - ajax implementations) on how to do that. Here is a link to an article along those lines
This can be done easily by adding a dummy LinkButton with no Text to the GridView and some code in the RowDataBound.
The LinkButton is needed on the page to avoid the Invalid postback or callback argument error. Setting the visibility to false will also cause this error.
The LinkButton also has a CommandArgument with the current row number and a OnCommand event to handle the actual clicking.
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="LinkButton1" runat="server" CommandArgument='<%# Container.DataItemIndex %>' OnCommand="LinkButton1_Command"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
The OnRowDataBound method
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
//check if the row is a datarow
if (e.Row.RowType == DataControlRowType.DataRow)
{
//find the linkbutton with findcontrol and cast it back to one
LinkButton lb = e.Row.FindControl("LinkButton1") as LinkButton;
//create the correct postback event with the UniqueID property of the linkbutton
string href = "javascript:__doPostBack('" + lb.UniqueID + "','')";
//add the onclick event with the correct href to the row
e.Row.Attributes.Add("onclick", href);
//to make it visible to the user that the row can be clicked
e.Row.Attributes.Add("style", "cursor:pointer;");
}
}
And the Command Method where you can get the CommandArgument from the LinkButton and do all sorts of neat things with it.
protected void LinkButton1_Command(object sender, CommandEventArgs e)
{
//the row index of the clicked row from the grid if needed
int rowIndex = Convert.ToInt32(e.CommandArgument);
//do stuff
}
There is no existing event to handle an entire row click. Your best bet is to have some javascript (maybe via ASP.NET Ajax) detect the click and fire the event yourself. Alternatively you would have to create a button or checkbox that the user selects.
You need to handle the "SelectedIndexChanged" event, you can then query the grid for the .SelectedRow. Alternativley use the "SelectedIndexChanging" event which sets "e.NewSelectedIndex"
Check out this article by Teemu, in where he explains about clicking a row in Gridview and throw the RowClicked event.
Here is a excerpt of the code:
Protected Overrides Sub RaisePostBackEvent(ByVal eventArgument As String)
If eventArgument.StartsWith("rc") Then
Dim index As Integer = Int32.Parse(eventArgument.Substring(2))
Dim args As New GridViewRowClickedEventArgs(Me.Rows(index))
OnRowClicked(args)
Else
MyBase.RaisePostBackEvent(eventArgument)
End If
End Sub
Public Class GridViewRowClickedEventArgs
Inherits EventArgs
Private _row As GridViewRow
Public Sub New(ByVal row As GridViewRow)
_row = row
End Sub
Public ReadOnly Property Row() As GridViewRow
Get
Return _row
End Get
End Property
End Class
Btw, it's in VB not C# though.
Related
I have entered this condition in my dataset
when the value of message is equal to "1" it is not possible to continue working on this webpage...
when the value of message is equal to "0" it's possible to continue but it's not possible to edit the gridview data...
My code below
if (message == 1)
{
Page.ClientScript.RegisterStartupScript(this.GetType(), "Alert", "alert('test msg 1');window.location='Default.aspx';", true);
return null;
}
else if (message == 0)
{
Page.ClientScript.RegisterStartupScript(this.GetType(), "Alert", "alert('test msg 2');", true);
btrila.Visible = false;
btnreset.Visible = true;
return dsProducts;
}
else
{
return dsProducts;
}
when the value of message is equal to "0" I need hidden or disable the button below for edit the gridview data
<ItemTemplate>
<asp:ImageButton ID="btnedit" runat="server"
CommandName="Edit"
ImageUrl="/aspnet/img/edit_icon.gif"
ToolTip="Edit" />
</ItemTemplate>
I have tried this solution in RowDataBound without success because the "btnedit" is always hidden...
Any help would greatly appreciate... Thank you.
protected void gvProducts_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
if (e.Row.DataItem != null)
{
if (btnreset.Visible == true)
{
gvProducts.Columns[2].Visible = false;
}
else
{
gvProducts.Columns[2].Visible = true;
}
}
}
}
when the value of message is equal to "0" I need hidden or disable the
button below for edit the gridview data
on the DataBound function you need to loop the cells and locate your control - here is how
protected void onRowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
// loop all data rows
foreach (DataControlFieldCell cell in e.Row.Cells)
{
// check all cells in one row
foreach (Control control in cell.Controls)
{
// go to find this button
Button button = control as Button;
if (button != null && button.CommandName == "Edit")
button.Enable = false; // or true depend on your contitions.
}
}
}
}
I tried to get the control of edit template which is checkbox in row command event but I am unable to get it, but I am getting label control which is in row index.
I tried the above below code to get the control:
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
GridViewRow gvr = (GridViewRow)(((ImageButton)e.CommandSource).NamingContainer);
Label icllbl = (Label)GridView1.Rows[gvr.RowIndex].FindControl("icllbl");
CheckBox iclcb = (CheckBox)GridView1.Rows[gvr.RowIndex].FindControl("iclcb");
if (e.CommandName.Equals("Edit"))
{
if (icllbl.Text == "Y")
{
iclcb.Checked = true;
}
}
}
And I tried RowDataBound event also luckily I am getting checkbox control here but this time I am unable to get the Label control in below code:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
Label icllbl = (Label)e.Row.FindControl("icllbl");
if ((e.Row.RowState & DataControlRowState.Edit) > 0)
{
CheckBox iclcb = (CheckBox)e.Row.FindControl("iclcb");
if (icllbl.Text == "Y")
{
iclcb.Checked = true;
}
}
}
}
Please correct me if I am wrong anywhere.
Thanks in advance!
In your RowCommand event use control class to cast into GridViewRow:
GridViewRow row = (GridViewRow)(((Control)e.CommandSource).NamingContainer);
int rowIndex = row.RowIndex;
And in RowDataBound event place Label control inside Edit (check for EditTemplate) check:
if ((e.Row.RowState & DataControlRowState.Edit) > 0)
{
Label icllbl = (Label)e.Row.FindControl("icllbl");
CheckBox iclcb = (CheckBox)e.Row.FindControl("iclcb");
//... other code of lines will be here
}
Basically, when I click on the cell, I want to be able to get everything on that row to show up in another form.
I have this code on my Show Form:
public partial class showTask : Form
{
public string TaskID, TaskName, TaskDescription, TaskTimeAndDateCompletion;
public int TaskPriority;
public showTask()
{
InitializeComponent();
}
public void ShowTaskChosen()
{
showTaskIDRtb.Text = TaskID;
showTaskNameRtb.Text = TaskName;
showTaskDescRtb.Text = TaskDescription;
showTaskPriorityRtb.Text = Convert.ToString(TaskPriority);
showTaskTimeAndCompletionDate.Text = TaskTimeAndDateCompletion;
}
}
And on my DataGridView named tasksViewerDGV in my mainPage Form, I have this to try and get the values to show on another form:
private void tasksViewerDGV_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
int column = e.ColumnIndex;
int row = e.RowIndex;
DataGridView ShowTask = sender as DataGridView;
if (ShowTask == null)
return; //If the cell is null, then just return without sending any information
var cell = ShowTask[column, row];
if (cell != null)
{
DataGridViewRow rows = cell.OwningRow; //Which ever cell is clicked, it gets the row of that cell
showTask displayTask = new showTask();
displayTask.TaskID = rows.Cells["taskID"].Value.ToString();
displayTask.TaskName = rows.Cells["taskName"].Value.ToString();
displayTask.TaskDescription = rows.Cells["taskDescription"].Value.ToString();
displayTask.TaskPriority = Convert.ToInt32(rows.Cells["taskPriority"].Value.ToString());
displayTask.TaskTimeAndDateCompletion = rows.Cells["taskTimeAndDateCompletion"].Value.ToString();
displayTask.ShowDialog();
displayTask.ShowTaskChosen();
}
}
The problems are these: var cell = ShowTask[column, row]; as I get the IndexOutOfRange Exception. Furthermore, when debugging it say's -1 on 'row' variable. Finally, it takes me ages to trigger the event, sometimes I ave to press on the cell title multiple times for it to work. I have no clue what is going on, any light that could come my way would be greatly appreciated.
Kind Regards,
Kieran
Try this..
private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex != -1)
{
string value = dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString();
}
}
CellContentClick event docs says:
This event occurs when the cell content is clicked
But cell content means just exactly the content of the cell and not some empty space in the cell. In that case you don't get the event fired.
In your context I would use CellMouseClick.
However this event is raised also in case you click the row or column headers of the grid. And for these cases the row or column index is -1.
You should have some kind of protection around these invalid values for row and column before trying to use them to find your grid cell.
private void dgv_CellClickMouse(object sender,
DataGridViewCellMouseEventArgs e)
{
DataGridView dgv = sender as DataGridView;
int column = e.ColumnIndex;
int row = e.RowIndex;
if(column == -1 || row == -1)
{
// for debug purpose...
Console.WriteLine("Not a valid row/column");
return;
}
DataGridViewCell cell = dgv[column, row];
if (cell != null)
{
......
}
}
I have added a GridView to my webform. I then bounded data to the gridview programatically, followed by adding a RowDataBound function so that I can have each cell, in the gridView selectable as such:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
LinkButton _singleClickButton = (LinkButton)e.Row.Cells[0].Controls[0];
string clickInfo = ClientScript.GetPostBackClientHyperlink(_singleClickButton, "");
// Add events to each editable cell
for (int columnIndex = 3; columnIndex < e.Row.Cells.Count; columnIndex++)
{
// Add the column index as the event argument parameter
string jsClick = clickInfo.Insert(clickInfo.Length - 2, columnIndex.ToString());
// Add this javascript to the onclick Attribute of the cell
e.Row.Cells[columnIndex].Attributes["onclick"] = jsClick;
// Add a cursor style to the cells
e.Row.Cells[columnIndex].Attributes["style"] += "cursor:pointer;cursor:hand;";
}
}
}
...So then what i wanted to do is that whenever a cell is selected, turn that cell red and add a textbox so i can enter a value.. Shown below
<Columns>
<asp:ButtonField CommandName="CellClick" Visible="false" ControlStyle- CssClass="redCell"></asp:ButtonField>
</Columns>
codebehind:
public void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName.ToString() == "CellClick")
{
//INDEX INFO
int selectedRowIndex = Convert.ToInt32(e.CommandArgument.ToString());
int selectedColumnIndex = Convert.ToInt32(Request.Form["__EVENTARGUMENT"].ToString());
//TRIGGERS EVENT FOR SELECTED CELL
GridView1.Rows[selectedRowIndex].Cells[selectedColumnIndex].Attributes["style"] += "background-color:Red;";
TextBox scheduleBox = new TextBox();
scheduleBox.CssClass = "redCell";
scheduleBox.ID = "ActiveCell";
scheduleBox.Width = 35;
this.GridView1.Rows[selectedRowIndex].Cells[selectedColumnIndex].Controls.Add(scheduleBox);
scheduleBox.Focus();
//LABEL INDEX INFO
lblCell.Text = (selectedColumnIndex - 2).ToString();
//LABEL HEADER & ROW TITLES
lblStartTime.Text = GridView1.Rows[selectedRowIndex].Cells[1].Text;
}
} GridView1.DataBind();
}
what I want to do now is once I press enter, get the value that currently resides in the texbox that was created programmatically and for now just display that value on a messagebox or whateevr (what Im really going to do is update a database but first I just need to find out how to get that value)
<asp:Panel runat="server" DefaultButton="Button1">
<asp:Button ID="Button1" CssClass="ActiveCell" runat="server" Style="display: none" OnClick="Button1_Click1" /></asp:Panel>
and the function Im using is this:
protected void Button1_Click1(object sender, EventArgs e)
{
var schedule = FindControl("ActiveCell") as TextBox;
ScriptManager.RegisterStartupScript(this, typeof(Page),
"alert", "alert('VALUE GOES HERE FROM TEXTBOX');", true);
}
So now my question: How can i get the value from ScheduleBox?
If I understand your question correctly, you should be able to use:
<%=schedule.ClientID %>.value
I am admittedly not a javascript expert, so let me know if that helps.
also, is the
var schedule = FindControl("ActiveCell") as TextBox;
returning the textbox correctly?
EDIT: if that doesn't work, try
<%=ActiveCell.ClientID %>.value
Have you tried looking into the controls of the cell of the selected row?
To work around the lack of a selectedColumnIndex in the GridView, I had to change your "GridView1_RowCommand" event to replace one line (to set the ID) and add one more:
scheduleBox.ID = "ActiveCell_" + selectedRowIndex.ToString() + "_" + selectedColumnIndex.ToString();
scheduleBox.TextChanged += scheduleBox_TextChanged;
It would look something like this:
int selectedColumnIndex = 0;
int selectedRowIndex = 0;
string lastUserInputText = string.Empty;
public void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName.ToString() == "CellClick")
{
//INDEX INFO
selectedRowIndex = Convert.ToInt32(e.CommandArgument.ToString());
selectedColumnIndex = Convert.ToInt32(Request.Form["__EVENTARGUMENT"].ToString());
//TRIGGERS EVENT FOR SELECTED CELL
GridView1.Rows[selectedRowIndex].Cells[selectedColumnIndex].Attributes["style"] += "background-color:Red;";
TextBox scheduleBox = new TextBox();
scheduleBox.CssClass = "redCell";
//This formats the ID so its unique, and now the TextBox contains the row and colummn indexes:
scheduleBox.ID = "ActiveCell_" + selectedRowIndex.ToString() + "_" + selectedColumnIndex.ToString();
scheduleBox.TextChanged += scheduleBox_TextChanged;
scheduleBox.Width = 35;
this.GridView1.Rows[selectedRowIndex].Cells[selectedColumnIndex].Controls.Add(scheduleBox);
scheduleBox.Focus();
//LABEL INDEX INFO
lblCell.Text = (selectedColumnIndex - 2).ToString();
////LABEL HEADER & ROW TITLES
lblStartTime.Text = GridView1.Rows[selectedRowIndex].Cells[1].Text;
}
GridView1.DataBind();
}
//The following event gets the current index of the Row and the column where the user is changing the text
void scheduleBox_TextChanged(object sender, EventArgs e)
{
TextBox txtSelected = (TextBox)sender;
string[] selectedValues = txtSelected.ID.Split(new char[] { '_' });
selectedRowIndex = int.Parse(selectedValues[1]);
selectedColumnIndex = int.Parse(selectedValues[2]);
//you could also use it to get the text directly while the user is editing it:
lastUserInputText = txtSelected.Text;
}
//This gets the text for the selected row and column. But if you only have 1 column with a TextBox it would be easier to just use the column index constant instead of doing it dynamically. However, remember you already have this value in the "lastUserInputText" variable. If you use that the following code may not be necessary:
string GetTextFromSelectedRowTextBox()
{
string textBoxValue = string.Empty;
foreach (Control curControl in this.GridView1.Rows[selectedRowIndex].Cells[selectedColumnIndex].Controls)
{
if (curControl is TextBox)
{
TextBox txtScheduleBox = (TextBox)curControl;
textBoxValue = txtScheduleBox.Text;
break;
}
}
return textBoxValue;
}
I am using checkbox in gridview .... I am using it in 1st cell.... When I select the checkbox at run time, I need to get those values... but on selecting or on click to checkbox, it's not finding or value is taking as FALSE... how to write in asp.net backend and in c# code?
<asp:TemplateField>
<ItemTemplate >
<asp:checkbox id="ShowAddress" runat="server" />
</ItemTemplate>
</asp:TemplateField>
Code-behind:
protected void Button1_Click(object sender, EventArgs e)
{
// Looping through all the rows in the GridView
foreach (GridViewRow di in GridView1.Rows)
{
CheckBox chkBx = (CheckBox)di.FindControl("ShowAddress");
if (chkBx != null && chkBx.Checked)
{
/// put your code here
}
}
}
Is there any implementation to be done in script at page load?
Can anyone help?
How do you populate your GridView? If you do this in Page_Load, make sure you are not doing it on postbacks (check IsPostBack).
Is your chkBx variable null?
The following code works:
protected void Button1_Click(object sender, EventArgs e)
{
foreach (GridViewRow row in GridView1.Rows)
{
CheckBox chk = row.Cells[0].Controls[0] as CheckBox;
if (chk != null && chk.Checked)
{
// ...
}
}
}
StringCollection idCollection = new StringCollection();
string strID = string.Empty;
for (int i = 0; i < GridView1.Rows.Count; i++)
{
CheckBox chkDelete = (CheckBox) GridView1.Rows.Cells[0].FindControl("chkSelect");
if (chkDelete != null)
{
if (chkDelete.Checked)
{
strID = GridView1.Rows.Cells[1].Text;
idCollection.Add(strID);
}
}
}
for more details check this link: http://www.itworld2.com/ghowto.aspx?id=69
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Loadgridview();// its a correct
}// not Loadgridview() here if you load above error is occur
}
check it
int i = 0;
foreach (GridViewRow row in GridView1.Rows)
{
CheckBox chk = (CheckBox)GridView_AdminTags.Rows[i].Cells[0].FindControl("chkTag");
if (chk != null)
if (chk.Checked)
{
////.......;
}
i++;
}
i = 0;
Jakob Answer will work if below line is used. Even one control only in the cell, index need to be 1 not 0
CheckBox chk = row.Cells[0].Controls[1] as CheckBox;
Thank you
Sam