I have a GridView that contains DropDownLists. They function as expected except during page postback. When the user clicks the update button on the page, I have a sub that loops through the grid rows, performs business ops and saves the data.
The problem is that during postback, the DropDownLists' selected properties do not represent that changes to selections made by the user. The selected item shows 'Dirty = True' in the break point.
Here is a subset of the code I use for reference:
<asp:GridView ID="materialGridView" runat="server"
AutoGenerateColumns="false" >
<Columns>
<asp:BoundField DataField="MaterialTypeName" HeaderText="Material Type" />
<asp:TemplateField>
<HeaderTemplate>
Quantity
</HeaderTemplate>
<ItemTemplate>
<asp:TextBox ID="quantityTextBox" runat="server" Width ="50" ></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<HeaderTemplate>
Material
</HeaderTemplate>
<ItemTemplate>
<asp:DropDownList ID="materialDropDownList" runat="server" Width="200">
</asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<HeaderTemplate>
Color
</HeaderTemplate>
<ItemTemplate>
<asp:TextBox ID="colorTextBox" runat="server" Width="100" BackColor="BlanchedAlmond" ReadOnly="true" ></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<HeaderTemplate>
RBK
</HeaderTemplate>
<ItemTemplate>
<asp:RadioButton id="rbkRadioButton" runat="server" Checked="true" />
<asp:TextBox ID="rbkPriceTextBox" runat="server" Width="50" ></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<HeaderTemplate>
Wimsatt
</HeaderTemplate>
<ItemTemplate>
<asp:TextBox ID="wimsattPriceTextBox" runat="server" Width="50"></asp:TextBox>
<asp:RadioButton id="wimsattRadioButton" runat="server" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
For Each row As GridViewRow In materialGridView.Rows
With row
materialDropDownList = DirectCast(.FindControl("materialDropDownList"), DropDownList)
quantityTextBox = DirectCast(.FindControl("quantityTextBox"), TextBox)
rbkPriceTextBox = DirectCast(.FindControl("rbkPriceTextBox"), TextBox)
wimsattPriceTextBox = DirectCast(.FindControl("wimsattPriceTextBox"), TextBox)
colorTextBox = DirectCast(.FindControl("colorTextBox"), TextBox)
rbkRadioButton = (DirectCast(.FindControl("rbkRadioButton"), RadioButton))
'compare current selecton in drop down and update if nessisary
For Each materialTableRow As DataRow In materialTable.Rows
'the item we are on is the item selected ANDALSO it is not yet assigned to the quote, so it's a new selection, update pricing.
Dim materialTableRowMaterialID As String = bizClass.dbCStr(materialTableRow.Item("MaterialID"))
If materialTableRowMaterialID = materialDropDownList.SelectedValue Then
If IsDBNull(materialTableRow.Item("QuoteID")) Then
rbkPriceTextBox.Text = bizClass.dbCStr(materialTableRow.Item("RBK"))
wimsattPriceTextBox.Text = bizClass.dbCStr(materialTableRow.Item("Wimsatt"))
End If
End If
Next materialTableRow
If rbkRadioButton.Checked = True Then
materialCostSumDecimal += bizClass.strToDec(quantityTextBox.Text) * bizClass.strToDec(rbkPriceTextBox.Text)
chosenSupplierString = "RBK"
Else
materialCostSumDecimal += bizClass.strToDec(quantityTextBox.Text) * bizClass.strToDec(wimsattPriceTextBox.Text)
chosenSupplierString = "Wimsatt"
End If
End With 'row
First of all make sure you are not binding the gridview on postback before reading dropdown values, because databind causes all controls to lose their postback value.
Second gridview is only able to postback the value of the only row that is being edited, so what you need to do is to move the dropdown (and all other controls) to the EditTemplate and set the row mode to Edit so the value will get posted back to server.
But if you want to be able to change all the dropdowns in all rows you might need to use Repeater control instead of GridView.
Related
I have following gridview in aspx page:
<asp:GridView Runat="server" id="gv1" PageSize="20" Visible="False" AllowPaging="True" Width="100%"
CssClass="clsDataGrid" AutoGenerateColumns="false" DataKeyNames="intProofSLNo,txtAdminRemarks" CommandArgument='Eval(intProofSLNo,txtAdminRemarks)'
OnRowCommand="gv1_RowCommand" OnRowDataBound ="gv1_OnRowDataBound" >
<asp:BoundField DataField="intProofSLNo" ReadOnly="True" Visible="false" ItemStyle-Wrap="false" HeaderText="Sl No" ItemStyle-CssClass="clsNormalText"></asp:BoundField>
<asp:TemplateField HeaderText="Action">
<ItemTemplate>
<asp:LinkButton ID="lnkbtnApprove" runat="server" CommandName="Approve" Text= "Approve / " />
<asp:LinkButton ID="lnkbtnReject" runat="server" CommandName="Reject" Text= "Reject" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Admin Remarks">
<ItemTemplate>
<asp:Label ID="lblAdminRemarks" runat="server" ItemStyle-Wrap="True" Text='<%# Bind("txtAdminRemarks")%>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txtAdminRemarksEdit" runat="server" cssclass=clsCommonInput MaxLength="252" Text='<%# DataBinder.Eval(Container.DataItem, "txtAdminRemarks")%>'></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Edit">
<ItemTemplate>
<asp:LinkButton ID="lblEdit" runat="server" Text="Edit" ToolTip="Edit" CommandName="Edit" CommandArgument='<%# Container.DataItemIndex %>'>
</asp:LinkButton>
</ItemTemplate>
<EditItemTemplate>
<asp:LinkButton ID="lnkUpdate" Width="38" runat="server" Text="Update|" CommandName="Update"CommandArgument='<%# Container.DataItemIndex %>' CausesValidation="true" ToolTip="Save"> </asp:LinkButton>
<asp:LinkButton ID="lnkCancel" runat="server" Width="40" Text="Cancel" CommandName="Cancel"
CausesValidation="false" ToolTip="Reset"></asp:LinkButton>
</EditItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
The user clicks on the 'Edit' link which makes 'Update' and 'Cancel' links visible.It then enters the remarks in the textbox and clicks 'Update'.A row command event is fired which updates the remarks in DB for the entry in that particular row. The same event calls the bind function:
Protected Sub gv1_RowCommand(sender As Object, e As GridViewCommandEventArgs)
If e.CommandName = "Update" Then
//some code to update remarks//
gv1.EditIndex = -1
subBindDataGrid()
End If
The subBindDataGrid() fires the following rowbound event which hides the buttons depending on admin remarks:
Protected Sub gv1_OnRowDataBound(sender As Object, e As GridViewRowEventArgs)
If e.Row.RowType = DataControlRowType.DataRow Then
Dim lblAdminRemarks As Label = DirectCast(e.Row.FindControl("lblAdminRemarks"), Label)
Dim lnkReject As LinkButton = DirectCast(e.Row.FindControl("lnkbtnReject"), LinkButton)
Dim lnkApprove As LinkButton = DirectCast(e.Row.FindControl("lnkbtnApprove"), LinkButton)
Dim lnkEdit As LinkButton = DirectCast(e.Row.FindControl("lblEdit"), LinkButton)
If DataBinder.Eval(e.Row.DataItem, "txtAdminRemarks").ToString().Trim = "Auto-Approved" Then
lnkApprove.Visible = False
lnkReject.Visible = False
lnkEdit.Visible = False
Else
lnkbtnApprove.Visible = True
lnkbtnReject.Visible = True
End If
End If
The remarks get updated in the DB. However, there is some issue in binding and instead of displaying the grid, the page is redirected to an error page. There is no exception thrown anywhere while debugging. The same events are also called in 'Edit'command. However, the functionality works fine there.Please suggest if there is anything wrong with the syntax.
I see you don't define a DataSourceID on the GridView static definition, please make sure you define a DataSource for the GridView in the subBindDataGrid procedure, otherwise it will have a null datasource in input.
Apologies for the slightly convoluted title.
Basically, I have a project where I have a database connected to it. I'm displaying some of the contents of the database using a GridView, which is all up and running, but the way I'm designing the page I need to be able to click a button in each row that in essence exports the value of one of the cells in the row to a subroutine.
I've tried googling it quite a bit and trying related things I found here, but nothing I could find would function like I would like it to.
The relevant code is below.
Markup:
<asp:GridView ID="Staffgv" runat="server" AutoGenerateColumns="false" OnRowCommand="Staffgv_RowCommand" AllowPaging="true" PageSize="20" OnPageIndexChanging="Staffgv_PageIndexChanging" BackColor="#f9f9f9" CssClass="gvStyle" >
<Columns>
<asp:TemplateField HeaderText="Start" InsertVisible="False" SortExpression="DateTimeStart">
<HeaderStyle Width="70px" CssClass="hdrGvStart"/>
<ItemTemplate>
<asp:Label ID="lblDateTimeStart" runat="server" Text='<%# Bind("DateTimeStart", "{0:t}") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Finish" SortExpression="DateTimeEnd">
<HeaderStyle Width="70px" CssClass="hdrGvFinish"/>
<ItemTemplate>
<asp:Label ID="lblDateTimeEnd" runat="server" Text='<%# Bind("DateTimeEnd", "{0:t}") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Forename" SortExpression="Forename">
<HeaderStyle Width="140px" CssClass="hdrGvForename"/>
<ItemTemplate>
<asp:Label ID="lblForename" runat="server" Text='<%# Bind("Forename") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Surname" SortExpression="Surname">
<HeaderStyle Width="140px" CssClass="hdrGvSurname"/>
<ItemTemplate>
<asp:Label ID="lblSurname" runat="server" Text='<%# Bind("Surname") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<HeaderStyle CssClass="gvHeaderEdit" />
<ItemTemplate>
<asp:Button ID="Btnapptid" runat="server" Text="" CssClass="btnGVEdit" CommandName="FillStaffTables" CommandArgument="<%# CType(Container,GridViewRow).RowIndex %>"/>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
And the relevant VB code:
Private Sub Staffgv_RowDataBound(sender As Object, e As GridViewRowEventArgs) Handles Staffgv.RowDataBound
Select Case e.Row.RowType
Case DataControlRowType.DataRow
Dim row = DirectCast(e.Row.DataItem, DataRowView)
Dim apptid As Integer = Integer.Parse(row("AppointmentID").ToString)
Dim Btnapptid = DirectCast(e.Row.FindControl("Btnapptid"), Button)
'Btnapptid.Text = apptid
Btnapptid.ToolTip = apptid
End Select
End Sub
Protected Sub Staffgv_RowCommand(ByVal sender As Object, e As GridViewCommandEventArgs)
If (e.CommandName = "FillStaffTables") Then
Dim index As Integer = Convert.ToInt32(e.CommandArgument)
lblTxtTester.Text = "AppointmentID"
TextboxTester.Text = index
End If
End Sub
If anyone would like more code like the code used to fill the GridView I'll post it, just didn't want to post too much irrelevant code.
Thanks
Solution A
When you only want 1 value from the gridview row when the button is clicked.
You could simply utilize the CommandArgument of your button (Btnapptid). This assumes that you don't need the gridview row index for when the button is clicked. If you do need this, then please see Solution B, otherwise continue here.
First, you'd need to modify your button's CommandArgument in the aspx page
ASPX
<asp:Button ID="Btnapptid" runat="server" Text="" CssClass="btnGVEdit"
CommandName="FillStaffTables" CommandArgument='<%# Bind("AppointmentID") %>'/>
Then you should be able to grab the AppointmentID like this
VB (inside Staffgv_RowCommand())
If (e.CommandName = "FillStaffTables") Then
txtAppointmentID.Text = e.CommandArgument
End If
Solution B
When you need more than 1 value from the gridview row when the button is clicked
Please note that this solution requires a couple changes on your end
Create an additional control (in the gridview) which should hold the value that you want to get when the button is clicked.
Fill said control with the value you want (via Bind() in the UI or in RowDataBound in the codebehind).
Next, in your RowCommand you'd be able to grab the newly created control with the help of the index variable (from your example) like so
Staffgv.Rows(index).FindControl("YOUR_CONTROLS_ID")
Example
Say that you decide to create a HiddenField control in which to store the value from your database
ASPX (hidden field should be somewhere inside the gridview - right under Btnapptid should be fine)
<asp:HiddenField ID="hfMyControl" runat="server" Visible="False"
Value='<%# Bind("SOME_DB_COLUMN") %>'/>
VB (inside Staffgv_RowCommand())
Dim hfMyControl As HiddenField = _
DirectCast(Staffgv.Rows(index).FindControl("hfMyControl"), HiddenField)
Then simply use the value of hfMyControl
hfMyControl.Value
You could also repeat all this using multiple controls in order to potentially access multiple DB values stored in controls in the gridview.
I have gridview with textbox and one Update button outside gridview.
When i click on button whatever data changed in textbox those values will update in database.
Here is My Gridview templatefield which is having Textbox
<asp:TemplateField HeaderText="SeqNo" HeaderStyle-CssClass="gridViolation-status"
ItemStyle-CssClass="gridViolation-status" ItemStyle-HorizontalAlign="Center"
HeaderStyle-ForeColor="White" SortExpression="STATUS">
<ItemTemplate>
<asp:TextBox ID="txtSeqNo" runat="server" Width="40%" Text='<%# Bind("VIOLATIONCODESEQNO") %>'
onchange="SetValue()"></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
and button outside gridview
<asp:Button ID="btnAdd" runat="server" Text="Update"
CssClass="submitbtn" OnClick="btnAdd_Click" />
I just need to update the value that is in textbox to database without using Foreach
I have a GridView that is made up of two database fields populated via a stored procedure and then three fields for user input (two checkbox controls and one textbox) when I click on the save button I can get the information from the three controls but nothing from the two that were populated via the database. How can I get the first two fields?
<asp:GridView ID="gvA1" runat="server" AutoGenerateColumns="false" DataKeyNames="CodeNo" AutoGenerateSelectButton="false" EnablePersistedSelection="True" Visible="false">
<Columns>
<asp:TemplateField Visible="false" >
<ItemTemplate>
<%#DataBinder.Eval(Container.DataItem, "CodeNo")%>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField ItemStyle-Wrap="true" ItemStyle-Width="400px" HeaderText="Violation">
<ItemTemplate>
<%#DataBinder.Eval(Container.DataItem, "CodeViolationCited") %>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox ID="A1Accordion_cbPool" runat="server" Text="Pool:" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox ID="A1Accordion_cbSpa" runat="server" Text="Spa:" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Additional Comments" Visible="true">
<ItemTemplate>
<asp:TextBox ID="A1Accordion_tb" runat="server" TextMode="MultiLine"></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Code Behind:
protected void SaveAndCollapseA1(object sender, EventArgs e)
{
//good stuff
CheckBox myCheckBox_1 = gvA1.Rows[0].FindControl("A1Accordion_cbPool") as CheckBox;
CheckBox myCheckBox_2 = gvA1.Rows[0].FindControl("A1Accordion_cbSpa") as CheckBox;
TextBox myTextBox = gvA1.Rows[0].FindControl("A1Accordion_tb") as TextBox;
//not so good stuff
String myString1 = gvA1.Rows[0].Cells[0].ToString();
String myString2 = gvA1.Rows[0].Cells[1].ToString();
}
I figured it out but I haven't been hear long enough to post the solution via the links but if you change the columns as so:
<asp:label ID="lblA1CodeNo" runat="server" text='<%# Eval("CodeNo") %>'></asp:label>
then the values are available...
Try:
<%# Bind("CodeViolationCited") %>
Instead of
<%#DataBinder.Eval(Container.DataItem, "CodeViolationCited") %>
Eval is one way, bind is two-way.
See Microsoft's documentation for data-binding expressions
I have the following markup in an ASP.NET page:
<asp:GridView ID="gv" runat="server" DataSourceID="ods" OnRowDataBound="gv_RowDataBound">
<columns>
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox ID="cb" runat="server" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:TextBox ID="tbx" runat="server"/>
</ItemTemplate>
</asp:TemplateField>
</columns>
</asp:GridView>
How can I validate the TextBox only if the CheckBox is checked?
I searched for similar situations, but couldn't find anything.
Thanks.
U can use RowCommand under which u can get the control status using int index = AuthorsGridView.EditIndex;
GridViewRow row = AuthorsGridView.Rows[index]; and then validate the text box
refer this http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridviewrow.aspx