I have a nested GridView(GvMP_Summary_Items). Each row contains a DropDownList. The DropDownList is bounded on the RowDataBound event of the nested GridView.
Each row also contains 1 Button. Upon pressing this button on the RowCommand event, I would like to find the current selected value of the DropDownList so I can use it further on in the code.
The code I have will only get the default value of the DropDownList on each row, which is currently set at 0 for each row.
Below is the RowCommand Event:
Protected Sub GvMP_Summary_Items_RowCommand(sender As Object, e As GridViewCommandEventArgs)
Dim lb As ImageButton = CType(e.CommandSource, ImageButton)
Dim gvRow As GridViewRow = lb.BindingContainer //Getting current row to get index
Dim GvMP_Summary_Items As GridView = CType(gvRow.FindControl("GvMP_Summary_Items"), GridView)
Dim intMPItem_Qty As Integer = CType(gvRow.FindControl("cboMPItem_Qty"), DropDownList).SelectedValue
Dim strMPItem_Qty As String = CType(gvRow.FindControl("txtMPItem_Qty"), TextBox).Text
End Sub
I have even included a TextBox in the GridView row which default value is empty "". Although on the row if something is entered the on RowCommand event brings back the value with a comma(,) in front of it.
This proves that I am picking up the correct row and can retrieve a value from a TextBox but not a DropDownList.
Is there something I am missing? Why can I return a value entered in a TextBox but not the selected value of a DropDownList? Also why the comma(,) in front of the TextBox value?
Note: In above case code has been written using VB so answers in VB over C# but I can accept both.
This can be done very easily by casting the CommandSource of the RowCommand back to a button and then get the correct row from that. Once you have the row you can use FindControl to locate the DropDownList. This works on every level of nested items and also on the top Control.
VB
Protected Sub GMP_Summary_Items_RowCommand(ByVal sender As Object, ByVal e As GridViewCommandEventArgs)
'cast the commandsource back to a button
Dim btn As Button = CType(e.CommandSource,Button)
'get the current gridviewrow from the button namingcontainer
Dim row As GridViewRow = CType(btn.NamingContainer,GridViewRow)
'use findcontrol to locate the dropdownlist in that row
Dim ddl As DropDownList = CType(row.FindControl("cboMPItem_Qty"),DropDownList)
'show the selected value of the dropdownlist
Label1.Text = ddl.SelectedValue
End Sub
Code was translated from C# with a code translator, so it may not be 100% accurate.
C#
protected void GMP_Summary_Items_RowCommand(object sender, GridViewCommandEventArgs e)
{
//cast the commandsource back to a button
Button btn = e.CommandSource as Button;
//get the current gridviewrow from the button namingcontainer
GridViewRow row = btn.NamingContainer as GridViewRow;
//use findcontrol to locate the dropdownlist in that row
DropDownList ddl = row.FindControl("cboMPItem_Qty") as DropDownList;
//show the selected value of the dropdownlist
Label1.Text = ddl.SelectedValue;
}
You do need to bind data to the GridView and the DropDownLists in an
IsPostBack check, otherwise the data will be rebound to the DDL on every PostBack and the selected value is lost
Important things:
Bind parent GridView in Page_Load method
Bind child GridView in parent GridView 's RowDataBound event
Bind DropDownList in child GridView 's RowDataBound event
Add CommandName to the Button which is inside child GridView
Finally, in RowCommand event of child GridView
Get child GridView 's row
Then find all controls inside child GridView from child GridView 's row
I'm not so aware of VB.NET so I have added an example (C#) of Nested GridView with RowCommand event (hope OP can use it in VB.NET):
HTML code (.Aspx):
<form id="form1" runat="server">
<asp:GridView ID="GridView_Outer" OnRowDataBound="GridView_Outer_RowDataBound" AutoGenerateColumns="false" runat="server">
<Columns>
<asp:TemplateField HeaderText="Outer Column1">
<ItemTemplate>
<asp:Label ID="Label_Outer" runat="server" Text='<%# Eval("Label_Outer") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Outer Column2">
<ItemTemplate>
<asp:GridView ID="GridView_Inner" OnRowDataBound="GridView_Inner_RowDataBound" OnRowCommand="GridView_Inner_RowCommand" AutoGenerateColumns="false" runat="server">
<Columns>
<asp:TemplateField HeaderText="Inner Column1">
<ItemTemplate>
<asp:Label ID="Label_Inner" runat="server" Text='<%# Eval("Label_Inner") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Inner Column2">
<ItemTemplate>
<asp:TextBox ID="TextBox_Inner" Text='<%# Eval("TextBox_Inner") %>' runat="server"></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Inner Column3">
<ItemTemplate>
<asp:DropDownList ID="DropDownList_Inner" runat="server"></asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Inner Column4">
<ItemTemplate>
<asp:Button ID="Button_Inner" runat="server" CommandName="BtnInnerCmd" Text="Inner Button" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<br />
<asp:Label ID="Label_Result" runat="server"></asp:Label>
</form>
Code-Behind (.Aspx.cs):
DataTable TempDT = new DataTable();
protected void Page_Load(object sender, EventArgs e)
{
CreateDataTable();
if (!IsPostBack)
{
GridView_Outer.DataSource = TempDT;
GridView_Outer.DataBind();
}
}
// create DataTable
public void CreateDataTable()
{
TempDT = new DataTable();
TempDT.Columns.Add("Label_Outer");
TempDT.Columns.Add("Label_Inner");
TempDT.Columns.Add("TextBox_Inner");
TempDT.Rows.Add("OuterLabel", "InnerLabel", "");
TempDT.Rows.Add("OuterLabel", "InnerLabel", "");
// store DataTable into ViewState to prevent data loss on PostBack
ViewState["DT"] = TempDT;
}
// Calls Outer GridView on Data Binding
protected void GridView_Outer_RowDataBound(object sender, GridViewRowEventArgs e)
{
// check if gridview row is not in edit mode
if (e.Row.RowType == DataControlRowType.DataRow)
{
// Get Outer GrridView 's controls
Label Label_Outer = (Label)e.Row.FindControl("Label_Outer");
GridView GridView_Inner = (GridView)e.Row.FindControl("GridView_Inner");
// get DataTable from ViewState and set to Inner GridView
GridView_Inner.DataSource = (DataTable)ViewState["DT"];
GridView_Inner.DataBind();
}
}
// Calls Inner GridView on Data Binding
protected void GridView_Inner_RowDataBound(object sender, GridViewRowEventArgs e)
{
// check if gridview row is not in edit mode
if (e.Row.RowType == DataControlRowType.DataRow)
{
// Get Outer GrridView 's controls
DropDownList DropDownList_Inner = (DropDownList)e.Row.FindControl("DropDownList_Inner");
// Create a DataTable to Bind data for DropDownlist
DataTable TempDDLDT = new DataTable();
TempDDLDT.Columns.Add("ItemText");
TempDDLDT.Columns.Add("ItemValue");
TempDDLDT.Rows.Add("ItemText1", "ItemValue1");
TempDDLDT.Rows.Add("ItemText2", "ItemValue2");
// bind DataTable to the DropDownList
DropDownList_Inner.DataSource = TempDDLDT;
DropDownList_Inner.DataTextField = "ItemText";
DropDownList_Inner.DataValueField = "ItemValue";
DropDownList_Inner.DataBind();
}
}
// Calls when Inner GridView 's button clicked
protected void GridView_Inner_RowCommand(object sender, GridViewCommandEventArgs e)
{
// get Inner GridView 's clicked row
GridViewRow InnerGridViewRow = (GridViewRow)(((Control)e.CommandSource).NamingContainer);
// get Inner GridView 's controls from clicked row
TextBox TextBox_Inner = (TextBox)InnerGridViewRow.FindControl("TextBox_Inner");
DropDownList DropDownList_Inner = (DropDownList)InnerGridViewRow.FindControl("DropDownList_Inner");
// check if correct button is clicked
if (e.CommandName == "BtnInnerCmd")
{
string DropDownListValue = DropDownList_Inner.SelectedValue;
string TextBoxValue = TextBox_Inner.Text;
Label_Result.Text = "DropDownList 's Selected Value is " + DropDownListValue +
"<br />TextBox 's Entered Value is " + TextBoxValue;
}
}
Demo Image:
Note: Above DropDownList selects Selected Value not Text.
Related
I have a Gridview that has 4 columns. All in ItemTemplate One column is a CheckBox. This Gridview is binded to a datasource. What I want to do is when the Checkbox is checked update the database with the bit value '1' and if I uncheck the Checkbox to do the same but '0'.
I already know my SQL code to update the database, but I am not sure how to run the event so that it looks at the current row the checkbox is on in the gridview.
Here is the CheckBox Column.
<asp:TemplateField HeaderText="Pick" ItemStyle-CssClass="hrGrid" HeaderStyle-CssClass="hdrHrBase">
<ItemTemplate>
<asp:CheckBox id="cbViewCustomer" runat="server" OnCheckedChanged="ViewCustomer" onAutoPostBack="true" Checked='<%#(Eval("chosen"))%>'/>
</ItemTemplate>
</asp:TemplateField>
Do I use EventArgs like this:
The problem with this is it updates the database but all the rows.
What I am trying to do is update only the current row that is in the Gridview. I am just not sure where to go from here.
protected void ViewCustomer(object sender, EventArgs e)
{
string SelectCustomer = "UPDATE tblcustomer Set chosen ='0'";
NpgsqlCommand changedata = new NpgsqlCommand(SelectCustomer, con);
con.Open();
changedata.ExecuteNonQuery();
con.Close();
}
Or should I be doing something different?
You can do this with OnRowCommand event of gridview like this:-
Associate a RowCommand event with your gridview:-
<asp:GridView ID="mygridview" runat="server" OnRowCommand="mygridview_OnRowCommand">
Next, associate a CommandName & CommandArgument to your checkbox:-
<asp:TemplateField HeaderText="Pick" ItemStyle-CssClass="hrGrid" >
<ItemTemplate>
<asp:CheckBox id="cbViewCustomer" runat="server" Checked='<%#(Eval("chosen"))%>'
CommandName="myCheckbox" CommandArgument="<%# Container.DataItemIndex %>"/>
</ItemTemplate>
</asp:TemplateField>
In the code behind handle the event:-
protected mygridview_OnRowCommand (object sender, GridViewCommandEventArgs e)
{
if(e.CommandName == "myCheckbox")
{
int rowIndex = Convert.ToInt32(e.CommandArgument);
GridViewRow row = mygridview.Rows[rowIndex];
bool ischecked = (row.FindControl("cbViewCustomer") as CheckBox).Checked;
}
}
You can also do it with checbox checked event, but if you have multiple controls then fire the gridview command event instead of individual events.
I have GridView filled automatically as
<asp:GridView ID="gvValues" runat="server"
OnRowDataBound="gvValues_RowDataBound"
OnPageIndexChanging="gvValues_PageIndexChanging"
<Columns>
<asp:TemplateField HeaderText="#">
<ItemTemplate>
<%# gvValues.PageSize*gvValues.PageIndex+ Container.DisplayIndex+1 %>
<asp:CheckBox ID="chkProduct" runat="server" CssClass="chkProduct"/>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="online" meta:resourcekey="Online">
<ItemTemplate >
<asp:CheckBox ID="chkProductonline" runat="server" OnCheckedChanged ="chkProductonline_CheckedChanged" AutoPostBack="true"/>
</ItemTemplate>
</asp:TemplateField>
What I need is when I click on the chkProductonline checkbox, to fire an event and get the chkProductonline and chkProducton values. I have tried this but it always gives me null.
protected void chkProductonline_CheckedChanged(object sender, EventArgs e)
{
var chkProductonline = FindControl("chkProductonline") as CheckBox;
// bool ischeck = chkProductonline.Checked;
var chkProduct = gvValues.FindControl("chkProduct") as CheckBox;
}
I can't loop the GridView. I need to do this one-by-one. Is there another way to do that?
You can try this:
protected void chkProductonline_CheckedChanged(object sender, EventArgs e)
{
CheckBox chkProductonline = sender as CheckBox;
...
CheckBox chkProduct = chkProductionLine.NamingContainer.FindControl("chkProduct") as CheckBox;
...
}
You need to call FindControl on a specific row. You will not be able to call it on the entire GridView because there exists repeating content (i.e. multiple chkProductionlines and chkProducts). A row knows of its checkboxes, and not of the others.
So what you can do is first get the CheckBox that called the event (your sender parameter, chkProductionline) and use its NamingContainer. Since it is contained in a GridView row, cast the row as such as use it to find the other controls you may need.
protected void chkProductonline_CheckedChanged(object sender, EventArgs e)
{
CheckBox chkProductionline = (CheckBox)sender;
GridViewRow row = (GridViewRow)chkProductionline.NamingContainer;
CheckBox chkProduct = (CheckBox)row.FindControl("chkProduct");
}
I am confused with this problem.
I have put a button in side the template field of a gridview and want to return the data from that specific GridView Row when that corresponding button is clicked.
<asp:TemplateField>
<ItemTemplate>
<asp:Button ID="Button2" CssClass ="btnSkin" runat="server" Text="Answer" Width="117px" onclick="Button2_Click" />
</ItemTemplate>
</asp:TemplateField>
In the button click event fireup, I want to read that data by creating a GridViewRow Element.
protected void Button2_Click(object sender, EventArgs e)
{
GridViewRow gvr = (GridViewRow)(sender as Control).Parent.Parent;
Label8.Text = gvr.Cells[1].Text;
Label10.Text = gvr.Cells[2].Text;
Label12.Text = gvr.Cells[3].Text;
}
Now the problem is, the GridViewRow Cells are returning empty strings.
What should I do?????
When using <asp:TemplateFields>, you actually need to find the text which is inside your controls such as <asp:Label> you used inside your <ItemTemplate>.
Cells won't have text, its the Controls inside the cells that have text.
So, If suppose , you have a Label inside one of your <ItemTemplate> as:
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Bind("CustomerID") %>'>
</asp:Label>
</ItemTemplate>
Then access the Text of this Label control using below code in your button Click event:[ assuming, 2nd Column contains the above <ItemTemplate> defined ]
protected void Button2_Click(object sender, EventArgs e)
{
GridViewRow gvr = (GridViewRow)(sender as Control).Parent.Parent;
String str = ((Label)gvr.Cells[1].FindControl("Label1")).Text;
}
I found the reason behind the empty strings error.
Gridview.Cells[i].Text will return the string value only when it is a <asp:BoundField>
If it is a <asp:TemplateField> and you have some ASP control inside the <ItemTemplate>, you must follow the FindControl("<control_id>") approach.
Here, basically we look for the control object in that particular GridviewRow Cell by its ID and cast it into the corresponding Control Type. Now, we can use that as we call any other asp control from code-behind.
String str = ((Label)gvr.Cells[1].FindControl("Label1")).Text;
Try using GridView.RowCommand Event and refer the following link for the same
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridview.rowcommand.aspx
hope this helps you.
Please check whether you are binding the grid properly on Page Load.
if(!IsPostBack)
{
BindgridView();
}
Hope this helps..Give a try..
I have a gridview in my form. I am working with RowDataBound event to the grid. Now I have a template field inside columns of the gridview. A label has been taken inside template field. I want to add a link to this label on RowDataBound event at runtime, but .System.Web.UI.WebControls.LinkButton is showing instead of link button.
How do I add a link button with label text in the grid view?
Just add a linkbutton inside your templatefield
<asp:GridView runat="server" ID="gridView">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton runat="server" ID="lnkTest"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Then in your rowdatabound event you can find it and do whatever you want
void gridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
Entity entity = e.Row.DataItem as Entity;
LinkButton lnkTest = e.Row.FindControl("lnkTest") as LinkButton;
lnkTest.CommandArgument = entity.ID.ToString();
lnkTest.Text = entity.Name;
}
}
You can then subscribe to gridview Command event and correct CommandArgument will be passed when clicking by linkbutton.
Hope this helps.
When i click on a row in gridview1, i want to go to gridview2 with the id i get from first grid.
How to get id from gridview1 to gridview2 and gridview2 autobinding?
You should define in gridview markup your primary key for table that would be showed in master grid like here:
<asp:GridView ID="gvUsers" runat="server" AutoGenerateColumns="False"
DataKeyNames="UserID" onrowcommand="gvUsers_RowCommand">
where "ID" - is the name of your actual primary key. And add some button for selecting purpose like here:
<asp:TemplateField>
<ItemTemplate>
<asp:Button runat="server" Text="SELECT" CommandName="Select" />
</ItemTemplate>
</asp:TemplateField>
Then in code behind create RowCommand event handler in the way like here:
protected void gvUsers_RowCommand(object sender, GridViewCommandEventArgs e)
{
Control ctl = e.CommandSource as Control;
GridViewRow CurrentRow = ctl.NamingContainer as GridViewRow;
object objTemp = gvUsers.DataKeys[CurrentRow.RowIndex].Value as object;
if (objTemp != null)
{
string id = objTemp.ToString();
//Do your operations
}
}
When you find your Master id you can load Detail gridview.