i will try to explain what i have, what i'm trying to do and what is my problem
what i have:
i have a modal with and update panel (i need it because the postback closes my modal) that has two text box, a button and a gridview.
in the textbox i write the name and the surname of a person and with the button i retrieve the data and put it in a gridview.
the gridview has a control to select the row that i want, with that row, i use the data from first three cells to change some hidenField values to use in another function.
in the bottom of the modal i have the add button that only changes a textbox to show that i have the correct data. that button is not enabled by default and the event must enable it
what i want:
i want to select the row that i need, enable the add button and fetch the data in my textbox.
where is my problem:
when i select my row, selectedindexchanging fires but nevers enables the add button so cant fetch my textbox for using it
code:
front code:
<div class="modal fade" id="modalSocio" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="staticBackdropLabelSocio">
<asp:Label ID="Label4" runat="server" CssClass="text-primary"></asp:Label>
</h5>
</div>
<asp:UpdatePanel ID="UpdatePanel1" runat="server" >
<ContentTemplate>
<div class="modal-body">
<div class="row g-3">
<div class="row">
<div class="col-3">
<asp:TextBox ID="txtBusquedaNombre" runat="server" CssClass="form-control" placeholder="Nombre"></asp:TextBox>
</div>
<div class="col-3">
<asp:TextBox ID="txtBusquedaApellido" runat="server" CssClass="form-control" placeholder="Apellido"></asp:TextBox>
</div>
<div class="col-3">
<asp:LinkButton ID="btnBuscarSocio" runat="server" CssClass="btn btn-outline-success" Text="Buscar" CausesValidation="false" ToolTip="Buscar" OnClick="btnBuscarSocio_Click" ><span class="fas fa-search"></span></asp:LinkButton>
</div>
</div>
<div class="table-responsive mt-3">
<asp:GridView ID="gvSocios" runat="server" CssClass="table table-bordered" AutoGenerateColumns="False" CellPadding="4" ForeColor="#333333" GridLines="None" OnSelectedIndexChanging="gvSocios_SelectedIndexChanging" >
<AlternatingRowStyle BackColor="White" />
<Columns>
<asp:BoundField DataField="Legajo" HeaderText="Nro. Socio" ></asp:BoundField>
<asp:BoundField DataField="nombreSocio" HeaderText="Nombre" />
<asp:BoundField DataField="Apellido" HeaderText="Apellido" />
<asp:CommandField ButtonType="Link" HeaderText="Seleccionar" ShowSelectButton="True" SelectText="<i class='fa fa-check-circle'></i>">
<ControlStyle CssClass="btn btn-outline-secondary" />
</asp:CommandField>
</Columns>
<EditRowStyle BackColor="#2461BF" />
<FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
<HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
<PagerStyle BackColor="#2461BF" ForeColor="White" HorizontalAlign="Center" />
<RowStyle BackColor="#EFF3FB" />
<SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True" ForeColor="#333333" />
<SortedAscendingCellStyle BackColor="#F5F7FB" />
<SortedAscendingHeaderStyle BackColor="#6D95E1" />
<SortedDescendingCellStyle BackColor="#E9EBEF" />
<SortedDescendingHeaderStyle BackColor="#4870BE" />
<EmptyDataTemplate>
<div class="alert alert-primary" role="alert">
No se encontraron registros!
</div>
</EmptyDataTemplate>
</asp:GridView>
</div>
</div>
</div>
</ContentTemplate>
</asp:UpdatePanel>
<div class="modal-footer">
<asp:Button ID="BtnCancelarSocio" runat="server" Text="Cancelar" CssClass="btn btn-secondary" OnClick="btnCancelar_Click" CausesValidation="False" />
<asp:Button ID="BtnAgregarSocio" ClientIDMode="Static" runat="server" CausesValidation="false" Text="Seleccionar" CssClass="btn btn-success" OnClick="BtnAgregarSocio_Click" />
</div>
</div>
</div>
</div>
codeBehind:
protected void BtnAgregarSocio_Click(object sender, EventArgs e)
{
TxtSocio.Text = hfidNombreSocio.Value;
}
protected void gvSocios_SelectedIndexChanging(object sender, GridViewSelectEventArgs e)
{
var row = gvFormasPago.Rows[e.NewSelectedIndex];
BtnAgregarSocio.Enabled = true;
hfSocio.Value = row.Cells[0].Text;
hfidNombreSocio.Value = row.Cells[0].Text + " - " + row.Cells[1].Text + " " + row.Cells[2].Text;
}
i tried to not use the enabled attribute for test but when the click event fires the hfidNombreSocio value in that moment is empty and the modal never closes.
maybe i'm not using the update panel right.
the text box code:
<div class="row">
<div class="col-md-4">
<asp:Label ID="lblSocio" runat="server" Visible="false" Text="Socio Cuenta Corriente" CssClass="form-label"></asp:Label>
<asp:TextBox ID="TxtSocio" runat="server" text="0" CssClass="form-control" ></asp:TextBox>
<asp:LinkButton ID="btnBuscar" runat="server" Visible="false" CssClass="btn btn-outline-success" Text="Buscar" CausesValidation="false" ToolTip="Buscar" OnClick="btnBuscar_Click" ><span class="fas fa-search"></span></asp:LinkButton> <%-- this button open the modal --%>
</div>
Ok, folks, this is one of those I wish someone corrected me!!
I am MOST HAPPY to have big buckets of egg on my face.
I have for some time preached that when you pop a dialog, you can't have post backs in that dialog. I stand MUCH corrected!!!!
So, lets build a grid, it allows a search, and then we can click on (select the row).
We have this:
<div id="hoteldialog1" style="display:normal">
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
Enter City Name: <asp:TextBox ID="txtSearchCity" runat="server"></asp:TextBox>
<asp:Button ID="cmdSearchCity" runat="server" Text="Search"
style="margin-left:25px" CssClass="btn" OnClick="cmdSearchCity_Click"/>
<br />
<asp:GridView ID="GridHotels" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" OnSelectedIndexChanged="GridHotels_SelectedIndexChanged"
CssClass="table">
<Columns>
<asp:BoundField DataField="HotelName" HeaderText="HotelName" />
<asp:BoundField DataField="City" HeaderText="City" />
<asp:BoundField DataField="Province" HeaderText="Province" />
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:TemplateField HeaderText="Select">
<ItemTemplate>
<asp:Button ID="cmdHSel" runat="server" Text="Select"
CommandName="Select"/>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</ContentTemplate>
</asp:UpdatePanel>
</div>
So, when we run, we get/see this:
Now, in above I DID use CommmandName = "select" because I wanted the select row to work. (and I beyond hate all those extra templates). So I used this code to highlight the row.
protected void GridHotels_SelectedIndexChanged(object sender, EventArgs e)
{
// user selected this row - highlight it
int RowIX = GridHotels.SelectedIndex;
GridViewRow gRow = (GridViewRow)GridHotels.Rows[RowIX];
if ((ViewState["MySel"] != null) && ((int)ViewState["MySel"] != RowIX))
{
GridViewRow gLast = GridHotels.Rows[(int)ViewState["MySel"]];
gLast.CssClass = "";
}
gRow.CssClass = "alert-info";
ViewState["MySel"] = RowIX;
}
Ok, so far so simple. And the search button in above is this:
protected void cmdSearchCity_Click(object sender, EventArgs e)
{
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
using (SqlCommand cmdSQL = new SqlCommand("SELECT * FROM tblHotels ", conn))
{
if (txtSearchCity.Text != "")
{
// filter grid by city
cmdSQL.CommandText += " WHERE City = #City";
cmdSQL.Parameters.Add("#City", SqlDbType.NVarChar).Value = txtSearchCity.Text;
}
conn.Open();
cmdSQL.CommandText += " ORDER BY HotelName";
GridHotels.DataSource = cmdSQL.ExecuteReader();
GridHotels.DataBind();
}
}
}
Again, really simple.
Ok, now the money shot. Now the Rosetta stone. Now the beef, now the magic, now the amazing!!!
The above as noted was placed in a "div", and has a update panel.
So, now lets drop in another grid!!!
We going to display some people, and pop the above hotel selector grid!!
So, we now have this:
<asp:GridView ID="GPeople" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" >
<Columns>
<asp:BoundField DataField="Firstname" HeaderText="Firstname" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="City" HeaderText="City" />
<asp:BoundField DataField="Province" HeaderText="Province" />
<asp:TemplateField>
<ItemTemplate>
<asp:Button ID="cmdGetHotel" runat="server" Text="Hotels"
OnClick="cmdGetHotel_Click"
OnClientClick="return mypop(this);"
/>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
And code:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadPeople();
}
void LoadPeople()
{
GPeople.DataSource = MyRst("SELECT * from People Order by FirstName");
GPeople.DataBind();
}
So we now have a grid of people. We now want to on a row click, pop up the hotel list.
So, I suggest jQuery.UI, as is much better (and cleaner then bootstrap dialog).
So we have this row click in above:
<asp:Button ID="cmdGetHotel" runat="server" Text="Hotels"
OnClick="cmdGetHotel_Click"
OnClientClick="return mypop(this);"
/>
So in above, we have both a server side button, and then a client side js function that pops up the dialog (and ONLY returns true if we hit ok.
So, now all we need is the js code to pop up the dialog. That code is this:
<script>
selok = false;
function mypop(btn) {
if (selok)
return true;
var mydiv = $("#hoteldialog1")
mydiv.dialog({
modal: true, appendTo: "form",
title: "Test dialog", closeText: "",
width: "40%",
position: { my: 'left top', at: 'right bottom', of: btn },
buttons: {
Ok: (function () {
selok = true;
btn.click()
}),
Cancel: (function () {
mydiv.dialog("close")
})
}
});
return false;
}
</script>
(set hotel grid display:none - jquery.ui will manage this).
So, now we get this:
So we are free to search, have post-backs, and of course select the row.
If the user hits ok, then the first grid button code runs. I did NOT use the selected index change event for that first grid (I could have), but I used this code:
protected void cmdGetHotel_Click(object sender, EventArgs e)
{
Debug.Print("hotel grid click");
Button btn = (Button)sender;
GridViewRow gRow = (GridViewRow)btn.Parent.Parent;
Debug.Print("Grid row = " + gRow.RowIndex);
Debug.Print("PK = " + GPeople.DataKeys[gRow.RowIndex]["ID"].ToString());
Also note, that while the pop grid is hidden? We can STILL get any data from that row, since the selected index of that grid does persist!!
eg:
GridViewRow gRow = (GridViewRow)GHotels.Rows[GHotels.SelectedIndex];
Debug.Print("Grid row = " + gRow.RowIndex);
Debug.Print("PK = " + GPeople.DataKeys[gRow.RowIndex]["ID"].ToString());
// cells collection, or find control to grab any other value
So, I think you should dump the bootstrap dialog.
Put your 2nd nice grid + searching, post backs - what ever you want into a div with a name, and use jQuery.UI to pop the grid. This will allow searching, post backs and then when the user selects the row and hits ok, then you are now free to close this dialog, and you have "index" of that pop set for you.
Related
I'm new to C# and asp.net and I have a GridView that has enabled selection on it and I put a button that is called View Products. When a user clicks on View Products, I want to show a panel that has more information for the button.
I have tried everything and looked up multiple ways but nothing is helping me find an answer to my problem.
Picture of the GridView
Ok, this is common, but answers are varied, and I tend to not like how most answers work.
I suggest this approach:
On that page, drop in a "div" with the controls and even additional buttons (such as perhaps a delete command, save command, and "cancel" to simple go back to the grid view.
So, first up, our grid view say like this:
<asp:GridView ID="GridView1" runat="server"
AutoGenerateColumns="False" DataKeyNames="ID"
CssClass="table" Width="45%" ShowHeaderWhenEmpty="true">
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" />
<asp:BoundField DataField="City" HeaderText="City" />
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:TemplateField>
<ItemTemplate>
<asp:Button ID="cmdEdit" runat="server" Text="Edit"
CssClass="btn myshadow"
OnClick="cmdEdit_Click"/>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
And say right below the above, we can simple drop in some standard text boxes and controls inside of a "div" that we hide/show for the details when clicked on.
So, say like this:
<div id="EditRecord" runat="server"
style="float:left;display:none;border:solid 2px;padding:15px">
<div style="float:left" class="iForm">
<label>HotelName</label>
<asp:TextBox ID="txtHotel" runat="server" width="280" f="HotelName"/> <br />
<label>First Name</label>
<asp:TextBox ID="tFN" runat="server" Width="140" f="FirstName" /> <br />
<label>Last Name</label>
<asp:TextBox ID="tLN" runat="server" Width="140" f="LastName" /> <br />
<label>City</label>
<asp:TextBox ID="tCity" runat="server" Width="140" f="City" />
<br />
<label>Province</label>
<asp:TextBox ID="tProvince" runat="server" Width="75" f="Province" ></asp:TextBox> <br />
</div>
<div style="float:left;margin-left:20px" class="iForm">
<label>Description</label> <br />
<asp:TextBox ID="txtNotes" runat="server" Width="400" TextMode="MultiLine"
Height="150px" f="Description" ></asp:TextBox> <br />
<asp:CheckBox ID="chkActive" Text=" Active" runat="server" TextAlign="Right" />
<asp:CheckBox ID="chkBalcony" Text=" Has Balcony" runat="server" TextAlign="Right" />
</div>
<div style="clear:both"></div>
<button id="cmdSave" runat="server" class="btn myshadow" onserverclick="cmdSave_ServerClick" >
<span aria-hidden="true" class="glyphicon glyphicon-floppy-saved"> Save</span>
</button>
<button id="cmdCancel" runat="server" class="btn myshadow"
style="margin-left:15px" onserverclick="cmdCancel_ServerClick" >
<span aria-hidden="true" class="glyphicon glyphicon-arrow-left"> Back/Cancel</span>
</button>
<button id="cmdDelete" runat="server" class="btn myshadow" style="margin-left:15px">
<span aria-hidden="true" class="glyphicon glyphicon-trash"> Delete</span>
</button>
</div>
Again, nothing speical - just controls and text boxes.
So, now our code to load can be this:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadGrid();
}
void LoadGrid()
{
GridView1.DataSource = MyRst("SELECT * FROM tblHotelsA ORDER BY HotelName");
GridView1.DataBind();
}
Code for when we click on a button:
Now we can't (like normal) double click on the button to create the event since that button is "nested" in the gv. So, in the markup, just type in for the button
onclick=
When you hit "=" sign, a popup gives you the option to create a plane jane click event for the button. So, choose create event.
Thus the button in the gv becomes this:
<asp:TemplateField>
<ItemTemplate>
<asp:Button ID="cmdEdit" runat="server" Text="Edit"
CssClass="btn myshadow"
OnClick="cmdEdit_Click"/>
</ItemTemplate>
</asp:TemplateField>
And now our button click event:
it will get the row, load up the controls in that div, and then display the div.
I have this code:
protected void cmdEdit_Click(object sender, EventArgs e)
{
Button cmdEdit = (Button)sender;
GridViewRow gRow = (GridViewRow)cmdEdit.NamingContainer;
int PKID = (int)GridView1.DataKeys[gRow.RowIndex]["ID"];
DataTable rstData = MyRst($"SELECT * FROM tblHotelsA WHERE ID = {PKID}");
General.FLoader(EditRecord, rstData.Rows[0]); // load up the controls
GridView1.Style.Add("display","none");
EditRecord.Style.Add("display", "normal");
}
And the results are thus this:
Note that the cancel button is rather simple.
You hide the "div" and re-show (un-hide) the grid.
this:
protected void cmdCancel_ServerClick(object sender, EventArgs e)
{
GridView1.Style.Add("display", "normal");
EditRecord.Style.Add("display", "none");
}
And I did use a helper routine (just returns a table).
That was this:
DataTable MyRst(string strSQL)
{
DataTable rstData = new DataTable();
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
{
cmdSQL.Connection.Open();
rstData.Load(cmdSQL.ExecuteReader());
}
}
return rstData;
}
So above is the basic idea, and workings.
And we could now that we have a div?
We could call a jQuery.UI "dialog", and that would in place of the div hide/show, simple call jQuery.UI, and then you get this effect:
I can post the code for how that pop up works, but really, the simple idea is a simple button, get PK row id, load that data into some controls, then hide the grid, show the div, and you off and running.
i'm have a problem with button clicked in asp.net update panel. Here My Code :
My Aspx Code :
<asp:UpdatePanel runat="server" ID="UpdatePanel1" UpdateMode="Conditional">
<ContentTemplate>
<div class="modal fade modal-lg" id="mdlVendor" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="mdlVendorLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="mdlVendorLabel">Vendor</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-3">
<asp:Label runat="server" ></asp:Label>
<asp:TextBox runat="server" ID="txtVendorSearch" CssClass="form-control me-2" OnClientClick="javascript:return false;" data-target="#mdlVendor" OnTextChanged="txtVendorSearch_TextChanged" AutoPostBack="true"></asp:TextBox>
<br />
</div>
<div class="col-md-3">
</div>
</div>
<asp:GridView ID="gvVendor" runat="server" CellPadding="4" ForeColor="#333333" GridLines="None" AutoGenerateColumns="false" Width="100%" OnRowCommand="gvVendor_RowCommand">
<AlternatingRowStyle BackColor="White" />
<EditRowStyle BackColor="#2461BF" />
<FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
<HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
<PagerStyle BackColor="#2461BF" ForeColor="White" HorizontalAlign="Center" />
<RowStyle BackColor="#EFF3FB" />
<SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True" ForeColor="#333333" />
<SortedAscendingCellStyle BackColor="#F5F7FB" />
<SortedAscendingHeaderStyle BackColor="#6D95E1" />
<SortedDescendingCellStyle BackColor="#E9EBEF" />
<SortedDescendingHeaderStyle BackColor="#4870BE" />
<EmptyDataTemplate>
<asp:Label runat="server" ID="lblEmptyData" Text="No Data Found"></asp:Label>
</EmptyDataTemplate>
<Columns>
<asp:TemplateField HeaderText="Vendor Id">
<ItemTemplate>
<asp:Label runat="server" ID="VendorID" Text='<%# Eval("VendorID") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Vendor Name">
<ItemTemplate>
<asp:Label runat="server" ID="VendorName" Text='<%# Eval("VendorName") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:ImageButton ImageUrl="~/img/add.png" runat="server" Width="20px" Height="20px" CommandName="SelectDataVendor" ToolTip="Select Data Vendor"/>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</ContentTemplate>
</asp:UpdatePanel>
My Aspx.cs Code :
protected void gvVendor_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName.Equals("SelectDataVendor"))
{
GridViewRow row = (GridViewRow)(((ImageButton)e.CommandSource).NamingContainer);
int index = row.RowIndex;
GridViewRow clickedRow = gvVendor.Rows[index];
Label VendorName = (Label)clickedRow.Cells[2].FindControl("VendorName");
txtVendor.Text = VendorName.Text;
}
}
protected void txtVendorSearch_TextChanged(object sender, EventArgs e)
{
ScriptManager.RegisterStartupScript(this, this.GetType(), "Pop", "openModal();", true);
DataTable dt = new DataTable();
string StrSeacrh = txtVendorSearch.Text;
dt = trxExpenditureCls.GetVendor(StrSeacrh);
if (dt.Rows.Count > 0)
{
gvVendor.DataSource = dt;
gvVendor.DataBind();
}
else
{
dt.Rows.Add(dt.NewRow());
gvVendor.DataSource = dt;
gvVendor.DataBind();
gvVendor.Rows[0].Cells.Clear();
gvVendor.Rows[0].Cells.Add(new TableCell());
gvVendor.Rows[0].Cells[0].ColumnSpan = dt.Columns.Count;
gvVendor.Rows[0].Cells[0].Text = "No Data Found";
gvVendor.Rows[0].Cells[0].HorizontalAlign = HorizontalAlign.Center;
}
}
When i'm click imageButton :
<asp:ImageButton ImageUrl="~/img/add.png" runat="server" Width="20px" Height="20px" CommandName="SelectDataVendor" ToolTip="Select Data Vendor"/>
system doesn't debug into gvVendor_RowCommand. When i make breakpoint in Page_Load, debugger goes into method gvVendor_RowCommand too. But i get a problem, txtVendor doesn't filled after debugger finish.
I'm already try :
<asp:UpdatePanel runat="server" ID="updPnl2" UpdateMode="Conditional">
<ContentTemplate>
<asp:ImageButton ImageUrl="~/img/add.png" runat="server" Width="20px" Height="20px" CommandName="SelectDataVendor" ToolTip="Select Data Vendor" ID="btnAdd"/>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger controlid="btnAdd" eventname="Click" />
</Triggers>
</asp:UpdatePanel>
And both
<asp:AsyncPostBackTrigger controlid="btnAdd" eventname="Click" />
Or
<asp:PostBackTrigger controlid="btnAdd" />
None of All fix my problem, even i have tried :
<asp:UpdatePanel runat="server" ID="updPnl2" UpdateMode="Conditional">
<ContentTemplate>
<asp:Button runat="server" ID="btnAddNewData" OnClick="bntAddNewData_Click" />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger controlid="btnAddNewData" eventname="Click" />
</Triggers>
</asp:UpdatePanel>
Still doesn't fix my problem, is anyone can help me? i'm stuck here. Thanks you before
Hum, I don't think the introduction of a update panel should matter.
On the other hand? I long ago dumped the use of the row command.
Most don't realize that you can drop in a standard asp.net button, or image button.
Just wire up a plane jane click event for the code behind. The beauty of this approach is you don't have to clutter up bunch of events into the row command.
(VERY little reason to bother or use that).
So, say we drop in a button into the GV.
Now, we can't double click on the button in the designer to auto wire up a event, but you can do this in the markup. Just type in onclick= -- and intel-sense will pop this up:
So, choose create new event.
And now you have this code for the image button click event:
protected void ImageButton1_Click(object sender, ImageClickEventArgs e)
{
ImageButton btn = (ImageButton)sender;
GridViewRow gRow = (GridViewRow)btn.NamingContainer;
// get pkID
int PKID = (int)GridView1.DataKeys[gRow.RowIndex]["ID"];
Debug.Print("PK ID = " + PKID);
Debug.Print("Row index click = " + gRow.RowIndex);
Label VendorName = (Label)gRow.FindControl("VendorName");
txtVendor.Text = VendorName.Text;
}
So you don't have to use row command. But, you can drop in a plain jane button, or image button - just wire up a plain old regular event. You can pick up the current row as per above, and you off to the races.
I have a data bound grid-view with action buttons for updating and deleting items in a users shopping cart. The grid-view uses a 'SelectMethod' in the code behind to generate the data. The problem I'm having is that every time I edit some data in the grid-view, the data is successfully persisted, but then an error is thrown before the page even completes loading.
Here's the exception details:
System.InvalidOperationException:
A public method with the name '' was eithernot found or there were multiple methods with the same name on the type 'ASP.posworx_cart_aspx'.
What makes it even more confusing is that (' ') is an empty string, I checked in my code and I don't even have any attributes with an empty string value, except
for the header of an item template, which I don't think even matters really.
Here's the stack trace:
[InvalidOperationException: A public method with the name '' was either not found or there were multiple methods with the same name on the type 'ASP.posworx_cart_aspx'.]
System.Web.UI.WebControls.ModelDataSourceView.FindMethod(String methodName) +2464454
System.Web.UI.WebControls.ModelDataSourceView.RequireAsyncModelBinding(String methodName, ModelDataSourceMethod& method) +67
System.Web.UI.WebControls.ModelDataSourceView.Update(IDictionary keys, IDictionary values, IDictionary oldValues, DataSourceViewOperationCallback callback) +97
System.Web.UI.WebControls.GridView.HandleUpdate(GridViewRow row, Int32 rowIndex, Boolean causesValidation) +1210
System.Web.UI.WebControls.GridView.HandleEvent(EventArgs e, Boolean causesValidation, String validationGroup) +877
System.Web.UI.WebControls.GridView.OnBubbleEvent(Object source, EventArgs e) +89
System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args) +37
System.Web.UI.WebControls.GridViewRow.OnBubbleEvent(Object source, EventArgs e) +90
System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args) +37
System.Web.UI.WebControls.LinkButton.OnCommand(CommandEventArgs e) +121
System.Web.UI.WebControls.LinkButton.RaisePostBackEvent(String eventArgument) +161
System.Web.UI.WebControls.LinkButton.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +12
System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +15
System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +9754214
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3562
The markup code for my grid-view:
<div class="table-responsive unbordered">
<asp:GridView ID="shoppingCartGridView" runat="server" DataKeyNames="ItemDetailId" SelectMethod="GetShoppingCartItems" AutoGenerateColumns="false" BorderColor="Transparent" BackColor="White" ForeColor="Black" CssClass="table table-hover table-condensed"
OnRowUpdating="shoppingCartGridView_RowUpdating" OnRowDeleting="shoppingCartGridView_RowDeleting" ItemType="OnlineShoppingApplication.BusinessEntities.ShoppingCart.ShoppingCartItem">
<SelectedRowStyle BackColor="#CC3333" ForeColor="White"></SelectedRowStyle>
<SortedAscendingCellStyle BackColor="#FFF"></SortedAscendingCellStyle>
<SortedAscendingHeaderStyle BackColor="#333333"></SortedAscendingHeaderStyle>
<SortedDescendingCellStyle BackColor="#FFF"></SortedDescendingCellStyle>
<SortedDescendingHeaderStyle BackColor="#333333"></SortedDescendingHeaderStyle>
<Columns>
<asp:TemplateField HeaderText="Product" HeaderStyle-Width="50%">
<ItemTemplate>
<div class="row">
<div class="col-sm-2 hidden-xs"><img class="img-responsive" src="../Images/product-image holder.gif" alt="<%#:Item.ItemDescription%>"></div>
<div class="col-sm-10">
<h4 class="bold-text nomargin">
<%#:Item.ItemDescription %>
</h4>
<p data-th="Product">
<%#:Item.ItemDescription %>
</p>
</div>
</div>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="ItemDetailId" HeaderText="Id" SortExpression="ItemDetailId" Visible="false" />
<%--<asp:TemplateField HeaderText="Name">
<ItemTemplate>
<a class="btn-link bold-text" href="<%#: GetRouteUrl("ProductByIdRoute", new {productId = Item.ItemId,productDetailId = Item.ItemDetailId})%>">
<%#:Item.ItemDescription%>
</a>
</ItemTemplate>
</asp:TemplateField>--%>
<asp:BoundField DataField="ItemPrice" ItemStyle-CssClass="btn-link item-vertical-align" HeaderText="Price" HeaderStyle-Width="10%" DataFormatString="{0:c}" />
<asp:TemplateField HeaderText="Quantity" HeaderStyle-Width="8%">
<ItemTemplate>
<asp:TextBox ID="quantityTextBox" runat="server" CssClass="form-control text-center" Text="<%#:Item.Quantity %>" TextMode="Number"></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Subtotal" HeaderStyle-Width="22%" HeaderStyle-CssClass="text-center" ItemStyle-CssClass="btn-link text-center">
<ItemTemplate>
<%#:$"{(Convert.ToDouble(Item.Quantity)) * (Convert.ToDouble(Item.ItemPrice)):c}"%>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="" HeaderStyle-Width="10%">
<ItemTemplate>
<asp:LinkButton ID="updateCartItemButton" runat="server" CssClass="btn btn-info btn-sm" Text='<i class="fa fa-refresh"></i>' alt="Update item" CommandName="Update">
</asp:LinkButton>
<asp:LinkButton ID="deleteCartItemButton" runat="server" CssClass="btn btn-danger btn-sm" Text='<i class="fa fa-trash-o"></i>' alt="Delete item" CommandName="Delete">
</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<EmptyDataTemplate>
<div class="row alert alert-warning alert-dismissable fade in" style="margin-bottom:0px">
There are no items in your shopping cart
</div>
</EmptyDataTemplate>
<EmptyDataTemplate>
<div class="row alert alert-warning alert-dismissable fade in" style="margin-bottom:0px">
There are no items in your shopping cart
</div>
</EmptyDataTemplate>
</asp:GridView>
</div>
</div>
Select method for grid-view:
public IQueryable<BusinessEntities.ShoppingCart.ShoppingCartItem> GetShoppingCartItems()
{
IQueryable<BusinessEntities.ShoppingCart.ShoppingCartItem> shoppingCartItems = _cartService.GetCartItems(SiteMaster.Customer.CustomerGuid).AsQueryable();
if (shoppingCartItems != null)
{
CreateCartSummary();
}
return shoppingCartItems;
}
Finally the
shoppingCartGridView_RowUpdating Event method:
protected void shoppingCartGridView_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
try
{
int prouductDetailId = (int)shoppingCartGridView.DataKeys[e.RowIndex].Value;
TextBox quantityTextBox = (TextBox)shoppingCartGridView.Rows[e.RowIndex].FindControl("quantityTextBox");
int newQuantity = int.Parse(quantityTextBox.Text);
UpdateCartItem(prouductDetailId, newQuantity);
DisplayMessage("Your cart has been updated successfully", Bootstrap.MessageType.Success);
shoppingCartGridView.DataBind();
}
catch (Exception ex)
{
ExceptionUtility.LogException(ex, $"{this}");
}
}
And the
shoppingCartGridView_RowDeleting Event method:
protected void shoppingCartGridView_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
try
{
int productDetailId = (int)shoppingCartGridView.DataKeys[e.RowIndex].Value;
RemoveCartItem(productDetailId);
DisplayMessage("The item has been deleted from your cart", Bootstrap.MessageType.Success);
shoppingCartGridView.DataBind();
}
catch(Exception ex)
{
ExceptionUtility.LogException(ex, $"{this}");
DisplayMessage(#"An error occured while deleting the item from the cart please try again later", Bootstrap.MessageType.Danger);
}
}
Thanks in advance guys, I would highly appreciate some assistance
on this, because I really don't know what to do.
After doing some research on the ModelDataSourceView class, I found that there are properties of the class called UpdateMethod,DeleteMethod,InsertMethod (basically properties to specify the names of all the CRUD operations) .
Which then made me think that instead of having the OnRowUpdating and OnRowDeleting events fired when I update a row, why not just add an UpdateMethod attribute to the GridView(with the value of that attribute being the name of the method responsible for performing the update operation)? After all there was already a SelectMethod attribute, so it kinda made more sense to have the UpdateMethod and DeleteMethod attribute to go along with it instead of the OnRowUpdating and OnRowDeleting events being fired.
Aaaaand Walaaa!!!!! IT WORKS perfectly.
So my grid-view now looks like this(all I done was removed the OnRowUpdating attribute and added the UpdateMethod Attribute and of course, I replaced OnRowDeleting with DeleteMethod):
<asp:GridView
ID="ShoppingCartGridView"
runat="server"
DataKeyNames="ItemDetailId"
SelectMethod="GetShoppingCartItems"
UpdateMethod="ShoppingCartGridView_UpdateItem"
DeleteMethod="ShoppingCartGridView_DeleteItem"
AutoGenerateColumns="false"
BorderColor="Transparent"
BackColor="White"
ForeColor="Black"
CssClass="table table-hover table-condensed"
OnDataBound="ShoppingCartGridView_DataBound"
ItemType="OnlineShoppingApplication.BusinessEntities.ShoppingCart.ShoppingCartItem">
<SelectedRowStyle BackColor="#CC3333" ForeColor="White"></SelectedRowStyle>
<SortedAscendingCellStyle BackColor="#FFF"></SortedAscendingCellStyle>
<SortedAscendingHeaderStyle BackColor="#333333"></SortedAscendingHeaderStyle>
<SortedDescendingCellStyle BackColor="#FFF"></SortedDescendingCellStyle>
<SortedDescendingHeaderStyle BackColor="#333333"></SortedDescendingHeaderStyle>
<Columns>
<asp:TemplateField HeaderText="Product" HeaderStyle-Width="50%">
<ItemTemplate>
<div class="row">
<div class="col-sm-2 hidden-sm hidden-xs">
<img class="img-responsive" src="../Images/product-image holder.gif" alt="<%#:Item.ItemDescription%>"></div>
<div class="col-sm-10">
<h4 class="bold-text nomargin"><%#:Item.ItemDescription %></h4>
<p data-th="Product">
<a
href="<%#:GetRouteUrl("ProductByIdRoute", new {productId = Item.ItemId,productDetailId = Item.ItemDetailId})%>"
class="btn-link"><%#:$"{Item.SizeCurve} {Item.Colour} {Item.ItemDescription}"%>
</a>
</p>
</div>
</div>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="ItemDetailId" HeaderText="Id" SortExpression="ItemDetailId" Visible="false" />
<asp:BoundField DataField="ItemPrice" ItemStyle-CssClass="currency item-vertical-align" HeaderText="Price" HeaderStyle-Width="10%" DataFormatString="{0:F2}"/>
<asp:TemplateField HeaderText="Quantity" HeaderStyle-Width="8%">
<ItemTemplate>
<asp:TextBox ID="quantityTextBox" runat="server" CssClass="form-control text-center" Text="<%#:Convert.ToInt32(Item.Quantity) %>" TextMode="Number"></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Subtotal" HeaderStyle-Width="22%" HeaderStyle-CssClass="text-center" ItemStyle-CssClass="text-center">
<ItemTemplate>
<%#:$"{Convert.ToInt32((Convert.ToDouble(Item.Quantity)) * (Convert.ToDouble(Item.ItemPrice)))}"%>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText=" " HeaderStyle-Width="10%" ItemStyle-CssClass="action">
<ItemTemplate>
<asp:LinkButton
ID="updateCartItemButton"
runat="server"
CssClass="btn btn-info btn-sm"
Text='<i class="fa fa-refresh"></i>'
alt="Update item"
CommandName="Update">
</asp:LinkButton>
<asp:LinkButton
ID="deleteCartItemButton"
runat="server"
CssClass="btn btn-danger btn-sm"
Text='<i class="fa fa-trash-o"></i>'
alt="Delete item"
CommandName="Delete">
</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<EmptyDataTemplate>
<div class="row alert alert-warning alert-dismissable fade in" style="margin-bottom: 0px">
There are no items in your shopping cart
</div>
</EmptyDataTemplate>
<EmptyDataTemplate>
<div class="row alert alert-warning alert-dismissable fade in" style="margin-bottom: 0px">
There are no items in your shopping cart
</div>
</EmptyDataTemplate>
</asp:GridView>
Here's my new, but not so different UpdateMethod referenced in the grid-view:
public void shoppingCartGridView_UpdateItem(int ItemDetailId)
{
try
{
int rowIndex = GetRowIndexByItemDetailId(ItemDetailId);
TextBox quantityTextBox = (TextBox)ShoppingCartGridView.Rows[rowIndex].FindControl("quantityTextBox");
int newQuantity = int.Parse(quantityTextBox.Text);
UpdateCartItem(ItemDetailId, newQuantity);
DisplayMessage("Your cart has been updated successfully", Bootstrap.MessageType.Success);
ShoppingCartGridView.DataBind();
}
catch (Exception ex)
{
ExceptionUtility.LogException(ex, $"{this}");
DisplayMessage(#"An error occured while updating your cart item,
please try again in a moment", Bootstrap.MessageType.Danger);
}
}
I am opening a modal window from the below button (btnOpen). This bhutton is located inside a GridView. It needs to open another Gridview in the modal window but my code is not working:
<asp:TemplateField>
<ItemTemplate>
<asp:Button ID="btnOpen" runat="server" Text="Show Gridview" CommandName="cmdDetail" CommandArgument="<%# ((GridViewRow) Container).DataItemIndex %>"/>
</ItemTemplate>
</asp:TemplateField>
My Modal Window:
<div class="modal" id="idModal">
<div class="container">
<div class="modal-header">
<h1>Transaction Details<a class="close-modal" href="#">×</a></h1>
</div>
<div class="modal-body">
<asp:GridView ID="gvDetail" runat="server" AutoGenerateColumns="false" DataSourceID="SqlgvDetail"
OnRowDataBound="gvDetail_RowDataBound" CssClass="table table-hover table-bordered" EmptyDataText="No data to display." >
<Columns>
<asp:BoundField DataField="metalid" HeaderText="Metal ID"/>
<asp:BoundField DataField="enddate" HeaderText="End Date" DataFormatString="{0:dd-MM-yyyy}" />
<asp:BoundField DataField="startdate" HeaderText="Start Date" DataFormatString="{0:dd-MM-yyyy}" />
<asp:BoundField DataField="clientref" HeaderText="Client Ref" />
<asp:BoundField DataField="quantity" HeaderText="Quantity" DataFormatString="{0:N2}" />
</Columns>
</asp:GridView>
</div>
<div class="modal-footer">
<asp:Button ID="btn_close" runat="server" Text="OK" CssClass="close-modal btn-sm btn-primary"/>
</div>
</div>
</div>
<div class="modal-backdrop"></div>
Sql DataSource:
<asp:SqlDataSource ID="SqlgvDetail" runat="server" ConnectionString="<%$ ConnectionStrings:InventoryConnectionString %>">
</asp:SqlDataSource>
Code Behind:
protected void gvSummary_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "cmdDetail")
{
// Retrieve the row index stored in the CommandArgument property.
int index = Convert.ToInt32(e.CommandArgument);
// Retrieve the row that contains the button from the Rows collection.
GridViewRow row = gvSummary.Rows[index];
Button btnOpen = row.FindControl("btnOpen") as Button;
btnOpen.CssClass = "openModal";
string clientRef = row.Cells[0].Text;
SqlgvDetail.SelectCommand = " SELECT td.metalid , td.enddate , td.startdate , td.clientref , td.quantity FROM trxdetail td " +
" WHERE td.clientref = '" + clientRef + "'";
gvDetail.DataBind();
}
}
When I click a button it gets the SQL command correct but doesn't load the modal. If I then click the button again, It brings up the Modal with the SQL command loaded at the first click.
I've been stuck on this for days so any help is appreciated.
I have searched about this topic all over the internet and have come up with nothing. Either I am having a hardtime wording my problem or I am do something so wrong that no one else has ever even tried it...
I have a gridview. I am using a button in the gridview to execute a command to open a ModalPopupExtender. That part works great. Once I have the popup open, I want to be able to press a button to execute a function which will perform a Sql query and bind a gridview that is INSIDE the popup panel. After that the user can perform an action with the gridview which would close the modal popup.
Here is my HTML -
<cc1:ModalPopupExtender runat="server" ID="MPE_Issue" PopupControlID="pnlIssue" BackgroundCssClass="ModalPopupBG"
TargetControlID="Hid_Sno" CancelControlID="btnIssueCancel">
</cc1:ModalPopupExtender>
<asp:Panel ID="pnlIssue" runat="server" Style="display: none" >
<div class="HelloPopup">
<div>
<br />
<h2> Issue Equipment</h2>
<br />
<asp:Panel runat="server" ID="pnlIssueSearch" DefaultButton="btnIssueSearch">
<div class="block" style="text-align: right; margin-left: 50px">
<asp:Label CssClass="lblBlock" runat="server" ID="lblIssueSearch" Text="Search:"></asp:Label>
</div>
<div class="block">
<asp:TextBox runat="server" ID="txtIssueSearch" Width="160px"></asp:TextBox>
<asp:ImageButton runat="server" ID="btnIssueSearch" ImageUrl="../Images/search.png" OnClick="btnIssueSearch_Click" />
</div>
</asp:Panel>
<asp:Panel runat="server" ID="pnlIssueSubmit" DefaultButton="btnIssueSubmit">
<div style="width: 275px; margin: auto; height: 295px; overflow: scroll;">
<asp:GridView runat="server" ID="gvIssue" AutoGenerateColumns="false" CssClass="mGrid" OnRowCommand="gvIssue_RowCommand">
<Columns>
<asp:TemplateField HeaderText="Qty">
<ItemTemplate>
<asp:TextBox ID="txtIssueQty" runat="server" Text='<%# Bind("QTY") %>'></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField HeaderText="Assignment" DataField="FIRST_NAME" />
</Columns>
</asp:GridView>
</div>
<div class="center">
<asp:Button runat="server" ID="btnIssueSubmit" Text="Issue" OnClick="btnIssueSubmit_Click" />
<input type="button" id="btnIssueCancel" value="Cancel" />
</div>
</asp:Panel>
And the codebehind -
protected void gv1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "issue")
{
GridViewRow gvr3 = (GridViewRow)(((ImageButton)e.CommandSource).NamingContainer);
string itemNo = ((Label)gvr3.Cells[0].FindControl("lblItemNo")).Text;
btnIssueSubmit.Visible = false;
txtIssueSearch.Text = "";
MPE_Issue.Show();
}
protected void btnIssueSearch_Click(object sender, ImageClickEventArgs e)
{
string query = "SELECT QTY, NEW_EMP_ID as NAME FROM TRANSACTION_TRACKING WHERE NEW_EMP_ID = #inputINT";
string inputString = "%" + txtIssueSearch.Text + "%";
int inputINT = Convert.ToInt32(txtIssueSearch.Text);
SqlConnection con = new SqlConnection(CS);
SqlDataAdapter da = new SqlDataAdapter(query, con);
SqlParameter parameter = new SqlParameter("inputString", inputString);
SqlParameter parameter2 = new SqlParameter("inputINT", inputINT);
da.SelectCommand.Parameters.Add(parameter);
da.SelectCommand.Parameters.Add(parameter2);
DataSet ds = new DataSet();
da.Fill(ds);
gvIssue.DataSource = ds;
gvIssue.DataBind();
btnIssueSubmit.Visible = true;
MPE_Issue.Show();
}
EDIT/SOLUTION
I was going about solving this problem wrong. I wanted to override the nature of asp.net instead of going with the flow and solving the problem systematically. To overcome this issue I changed my data bind into its own method and had the button within the panel activate the that method, set the popup control to Open(), and also set a boolean from false to true. Then on the page_load I have an event that checks the boolean and automatically does the data Method if it is true (and therefore a search parameter is in the textbox).
Thanks all for the suggestions and help.
If you make your pnlIssueSubmit an UpdatePanel then do an asyncpostback trigger on btnIssueSearch wouldn't that fix your issue? Because your imageButton needs to do a post back in order to refresh you grid but then you'll lose your modal. Something like this:
<asp:UpdatePanel id="pnlIssueUpdate" runat="server">
<ContentTemplate>
<asp:Panel runat="server" ID="pnlIssueSubmit" DefaultButton="btnIssueSubmit">
<div style="width: 275px; margin: auto; height: 295px; overflow: scroll;">
<asp:GridView runat="server" ID="gvIssue" AutoGenerateColumns="false" CssClass="mGrid" OnRowCommand="gvIssue_RowCommand">
<Columns>
<asp:TemplateField HeaderText="Qty">
<ItemTemplate>
<asp:TextBox ID="txtIssueQty" runat="server" Text='<%# Bind("QTY") %>'></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField HeaderText="Assignment" DataField="FIRST_NAME" />
</Columns>
</asp:GridView>
</div>
<div class="center">
<asp:Button runat="server" ID="btnIssueSubmit" Text="Issue" OnClick="btnIssueSubmit_Click" />
<input type="button" id="btnIssueCancel" value="Cancel" />
</div>
</asp:Panel>
</ContentTemplate>
<Triggers>
<asp:asyncPostBackTrigger ControlID="btnIssueSearch" />
</Triggers>
I was going about solving this problem wrong. I wanted to override the nature of asp.net instead of going with the flow and solving the problem systematically. To overcome this issue I changed my data bind into its own method and had the button within the panel activate the that method, set the popup control to Open(), and also set a boolean from false to true. Then on the page_load I have an event that checks the boolean and automatically does the data Method if it is true (and therefore a search parameter is in the textbox).