Using Validation controls with a GridView - asp.net

A typical situation:
In my GridView control, I have a Footer row which contains a Textbox and an "Add" Button. When the button is pushed, the Text entered in the TextBox is added to the grid. I also have a validation control to require that, when the button is pushed, that text has been entered in the TextBox. After a new row is added, the textbox is clear to allow for easy entry of the next item.
The user may also edit the text in previously entered rows by clicking the Edit LinkButton, which puts the row into edit mode. Clicking an Update LinkButton commits the change.
The problem:
When, I click the Update link to commit the changes, if text has not been entered in the Footer row's TextBox (the row used to add a new entry), the validation control returns a "Entry Required" error. It should only require an entry if the Add button is pushed, not if the Update LinkButton is pushed.
It seems that the server side Validation control's validating event fires before the GridView's RowCommand event or the btnAdd_Click event, so I am wondering how, from the server, I can determine what event fired the postback so I can determine whether what edits should be performed for the given situation.
I am using a mix of client side "required" validation edits as well as more complex server sides. Since I probably have to have some server sided validations, I would be happy with just knowing how to handle server sided validations, but really, know how to handle this situation for client validations would also be helpful.
Thanks.

Convert your CommandField into a TemplateField, and in the EditItemTemplate, change the Update LinkButton's CausesValidation property to false.
Update:
Converting to a TemplateField is simple and doesn't require any code changes (just markup):
Changing the CausesValidation property to false in the markup is also straightforward:
<asp:TemplateField ShowHeader="False">
<EditItemTemplate>
<asp:LinkButton ID="lnkUpdate" runat="server" CausesValidation="False"
CommandName="Update" Text="Update"></asp:LinkButton>
<%--
More controls
--%>
</EditItemTemplate>
<ItemTemplate>
<%--
Controls
--%>
</ItemTemplate>
</asp:TemplateField>
Now, if you want your footer and data rows to be validated separately, you need to use validation groups, which is explained in Microsoft's documentation. All the controls in the same validation group will have their ValidationGroup property set to the same value, like this:
<asp:LinkButton ID="lnkUpdate" runat="server" CausesValidation="True"
CommandName="Update" Text="Update" ValidationGroup="GridViewDataRowGroup">
</asp:LinkButton>

Related

Wait cursor on click of auto select button on GridView

I have an asp:GridView control where the first column is where the user selects the row (so it displays an underlined "Select" on each row). The AutoGenerateSelectButton is set to "True". When the row is selected, the query behind it may take some time to return the data on the page, so I'd like to set the cursor to 'wait'. The problem is, on the client side, I'm not sure how I can trap which row was selected before the postback. With an autogenerate Select on a grid, the actual HTML on the page is an anchor tag with a javascript:postback assigned.
I can easily set a wait cursor for a control like an asp:Button by simply doing a
btnButton.Attributes.Add("onclick", "document.body.style.cursor = 'wait';")
in the C# code behind, but I'm not sure how to do something similar with a asp"GridView control when someone not just clicks on the grid but clicks the Select hyperlink.
Thanks!
Set AutoGenerateSelectButton=false and use a button instead. This shall replace the select link column on your gridview, which should allow for your desired cursor functionality.
<asp:GridView ID="GridView1" runat="server" OnSelectedIndexChanged="GridView1_SelectedIndexChanged">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton Text="Select" runat="server" CommandName="Select" OnClientClick="$('body').addClass('waiting');"/>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
I placed the jquery directly into client side click, but it could also be used in a function. I found the javascript/css resources from another question on SO.
Changing cursor to waiting in javascript/jquery
CSS:
<style>
body.waiting * {
cursor: progress;
}
</style>

Can't access checkbox values in gridview on postback

This sounds a lot like a bunch of other questions on here, but nothing I've read follows what I'm seeing.
I have a gridview that contains a number of bound fields and a couple of template fields containing checkboxes. The gridview is bound to a custom datasource on pageload (inside a "not page.ispostback()" condition). The user can check the checkboxes to specify certain actions that are then committed when a link button is clicked.
The link button's click event has the following code in it:
For Each row As GridViewRow In UnpaidEntriesGridView.Rows
Dim paidCheckbox As CheckBox = CType(row.FindControl("PaidCheckbox"), CheckBox)
If paidCheckbox.Checked Then
// perform database action
End If
Next
Initialise() // (this rebinds the gridview)
No matter what I do, I cannot get hold of the checked value of any checkbox in the gridview that the user has changed. All checkboxes remain in their original state (set on data bind).
This is more than likely a page life-cycle issue, but for the life of me, I can't figure out why the user's changes aren't persisted after postback, despite the fact that the gridview isn't rebound until after I've checked.
ViewState is enabled, everything's pretty standard here otherwise.
Gridview code snippet from ascx follows:
<asp:GridView ID="UnpaidEntriesGridView" runat="server" AutoGenerateColumns="false" EnableViewState="true">
<Columns>
<asp:BoundField HeaderText="Entry Name" DataField="EntryName" />
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox ID="PaidCheckbox" runat="server" EnableViewState="true" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:LinkButton ID="UnpaidEntriesSaveLinkButton" runat="server" Text="Commit Changes" />
Any help (even a slap for being so stupid) would be massively appreciated.

OnTextChanged loses focus when AutoPostBack is true

I have a ASP.Net webform that has several textboxes. Some of the textboxes have an OnTextChanged event with AutoPostBack set to true.
When the user enters some text and leaves the textbox, I want some code to run. This part works fine.
The problem is that if a user enters some text, then clicks or tabs to another textbox, the OnTextChanged of the current textbox event fires fine but the textbox that the user clicked on does not keep focus. This causes problems because the user thinks they are on the next textbox but they aren't. And no object seems to have the focus.
Is there anything that can be done to make the next object keep focus while the OnTextChanged event of the current textbox fires?
One option is to use <asp:UpdatePanel> Control.
Facts about using it:
The postback request would be made via AJAX.
It would not recreate the whole page HTML.
When the UpdatePanel updates, it replaces the DIV innerHTML, that would make the textbox lose focus (bad point).
To maintain the focus, you would have to avoid the UpdatePanel from updating when the textbox posts back.
You can avoid the update by setting the UpdateMode and ChildrenAsTriggers properties.
Here is an example:
<asp:UpdatePanel ID="uppTextboxes" runat="server" UpdateMode="Conditional" ChildrenAsTriggers="false">
<ContentTemplate>
<asp:TextBox ID="txb1" runat="server" AutoPostBack="true" OnTextChanged="txb1_OnTextChanged" />
<asp:TextBox ID="txb2" runat="server" />
</ContentTemplate>
</asp:UpdatePanel>
Since the whole page is recreated on postback on serverside and the browser will recreate all html on clientside, you have to tell ASP.NET that your TextBox needs focus.
Use Page.SetFocus:
Page.SetFocus(IdOfControl);
However, i would prefer not to postback at all if i can. Can't you use a button that the user has to click after he has entered all necessary data?

Setting Visibility of Button Control in GridView Header

I have a gridview that displays entries from a data table. I am giving users the ability to select a subset of the data in the table by having a textbox and search button in the grid view header. The search button fires the gridview row command, and changes the underlying sqlDataSource's select command, and adds the text value from the text box as a parameter.
This works smoothly.
Also, I have a "Show All" button in the header, that clears out the select parameters, so all entries in the table are shown. Again, this works perfectly.
What is NOT working is controlling the visibility of the "Show All" button control. Below is the html markup for the data grid header template:
<HeaderTemplate>
<asp:Button ID="btnShowAll" runat="server" CausesValidation="False" CommandName="ShowAll" Text="Show All" />
<asp:Button ID="btnSearch" runat="server" CausesValidation="True" CommandName="Search" Text="Search" ValidationGroup="vldSearch" /><br />
<asp:TextBox ID="txtSearchName" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="vldSearchName" runat="server" ErrorMessage="You have to provide an attorney name to search for." Text="*" ControlToValidate="txtSearchName" ValidationGroup="vldSearch" ForeColor="White"></asp:RequiredFieldValidator>
</HeaderTemplate>
In the Row Command event handler, here is how I am setting the visibility of the button:
If Not Me.dgAttorneys.HeaderRow Is Nothing Then
Dim btnShowAll As Button = Me.dgAttorneys.HeaderRow.FindControl("btnShowAll")
btnShowAll.Visible = Me.sqlAttorneys.SelectParameters.Count > 0
Trace.Write("Show all status is " & btnShowAll.Visible.ToString)
End If
The trace statement is showing the correct visible status - if the "show all" button is clicked, I do a SelectParameters.Clear() on the sqlAttorneys sqlDataSource.
Is my problem due to a misunderstanding of how the "FindControl" method works - I had assumed my new btnShowAll that I define is actually a reference to the "physical" control on the aspx page, so any changes I make to my local object is reflected in the control on the page.
If this is not the case, what is the best way to get a reference to the button control in the header row of the grid view?
I managed to get the button behavior to work - it was all to do with where in the overall process I was setting the button visibility. I moved that code block (setting the button visibility based on the presence of a search parameter) to the DataBound event for the data grid, and the button's visibility was set as it should be.
I suspect this is because during the overall data binding process, based on the state of the overall grid view and each grid row, the appropriate template object is used to render each row. Thus, any changes made to the button's visible property were being overridden during the data binding process. By shifting my code to set the visibility until after the data binding was complete, then it took effect.

Delete from grid asp.net

i have this template field inside a gridview.
<asp:TemplateField ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:ImageButton ID="ImageButton2" ImageUrl="~/images/DeleteRecord.gif" runat="server"
OnClientClick="return ConfirmacionBorrarClausula();" CommandName="BorrarClausula" CommandArgument='<%#Eval("ClausulaID")%>' OnCommand="gvClausulas_OnRowDeleting" CausesValidation="false"
</ItemTemplate>
</asp:TemplateField>
I have another one in the same page but in a different gridview, almost exactly like this one but the second one isnĀ“t working.
So i have two gridviews each one with a template field like the one here, one onRowDeleting working perfectly, the other one not working at all, when i click it, it asks for confirmation (javascript function) but when i click ok to delete, the grid loses it data and the page fires all the validators.
Thank you for your time.
Make sure the control IDs are set right. And Ispostback the control level set to true. And also Try deleting the control and add it again some time that might help. Try add it from design view.
i manage to solve it, the problem was the second gridview was losing its data on the pageload, i managed that but only with the first gridview.

Resources