Button in GridView, OnCommand, Event Bubbling, Master Page - asp.net

Prerequisite, I am fairly new to event bubbling.
I have a page with a gridview that has buttons in the rows. When the button is clicked, it fires an OnCommand event and everything works as expected.
<ItemTemplate>
<asp:Button ID="btnG" runat="server" OnCommand="btnG_Command" Text="View"/>
</ItemTemplate>
... (on the codebehind) ..
Protected Sub btnG_Command(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.CommandEventArgs)
'Does some stuff
When I added a textbox (with validators) and a button on the Master Page, now when the buttons in the gridview are clicked, it fires the validators in the Master page for some reason.
<asp:RequiredFieldValidator ID="ReqValidator" runat="server" ControlToValidate="txtTextbox" Display="Dynamic" ErrorMessage="Please enter a valid number."></asp:RequiredFieldValidator>
Through some research I found that it has to do with event bubbling somehow since the button controls in the gridview are using OnCommand rather than OnClick.
My question is why is it firing the validators off in the Master page? Shouldn't the bubbling first go through the GridView instead of the Master page? How can I bypass the validators or event bubbling so that the correct event is fired from the content page?

You should add a validation group to your validator in the master page. Validation groups allow you to organize validation controls on a page as a set. Each validation group can perform validation independently from other validation groups on the page.
You create a validation group by setting the ValidationGroup property to the same name (a string) for all the controls you want to group. You can assign any name to a validation group, but you must use the same name for all members of the group
Source: https://msdn.microsoft.com/en-us/library/ms227424(v=vs.100).aspx
<asp:RequiredFieldValidator ID="ReqValidator" runat="server"
ControlToValidate="txtTextbox" Display="Dynamic"
ErrorMessage="Please enter a valid number."
ValidationGroup="MasterNumber"></asp:requiredfieldvalidator>

Related

Radcombobox OnItemRequested firing page validation

I have some really weird stuff going on here.
I have the following RadComboBox and button in the master page:
<telerik:RadComboBox ID="rcbPesquisa" runat="server" CausesValidation="false" ShowToggleImage="false" LoadingMessage="Carregando..." HighlightTemplatedItems="true" OnClientKeyPressing="onKeyPressing" EmptyMessage="Buscar" EnableLoadOnDemand="True" EnableVirtualScrolling="true" OnItemsRequested="rcbPesquisa_ItemsRequested" AllowCustomText="True" AutoPostBack="true" OnSelectedIndexChanged="rcbPesquisa_SelectedIndexChanged" Width="350">
<asp:Button runat="server" ID="btnExcluir" Text="Excluir" OnClick="btnExcluir_Click" CausesValidation="true" ValidationGroup="Excluir" CssClass="btn" OnClientClick="return confirm('Deseja realmente excluir o registro?');" />
In the page, I have this validator:
<asp:CustomValidator ID="cuvExclusaoRelacionamento" runat="server" ValidationGroup="Excluir" OnServerValidate="cuvExclusaoRelacionamento_ServerValidate"></asp:CustomValidator>
What happens is: When i click the combobox, and it tries to load it's items, cuvExclusaoRelacionamento validator is called on the server, and of course things go south.
By the way... __EventTarget on cuvExclusaoRelacionamento_ServerValidate is empty
Unfortunately, and without seeing the full code I'm only guessing, I believe there is no way of getting around this due to the following settings:
ValidationGroup="Excluir" The ValidationGroup property assigned to an input control is the Validation Group which should be triggered when the control posts back; The ValidationGroup property of a validator control is the name of the group to which it is assigned; Finally the ValidationGroup property of a submitting control (which could be a button but can also be the input control) is the name of the group of Validators to validate the page against before posting back to the server. I should point out at this timethat it will not post back (server-side event handlers will not be triggered) if the validation fails. Given that the validation group of the control is the same as the validation group of your Custom Validator the validator will be triggered when the control attempts to post back to the server (e.g. when being clicked), if this validation fails it will not post back.
AutoPostBack="true" When you set the control to auto post back it will post back to the server when updated. Given you have an OnClick event I'm guessing you need to perform some server side action when the state of the control is changed.
CausesValidation="true" When set to true all validators assigned to the same "Validation Group" as the submitting control will be triggered when the control attempts to post back to the server. As I've said above, this will prevent post back (meaning the server-side Event Handlers will not be triggered) if the validation fails.
Given the information provided, I'm guessing that the best action you could take is to set CausesValidation="false" for the control. The validation can still be performed so long as you have a submit button (or other control which triggers a post back) elsewhere which is assigned to the "Excluir" Validation Group.

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?

Asp.NET dropdownlist autopostback

I have a dropdownlist with autopostback enabled. and have a repeater where i populate checkboxes from database.
If i set the autopostback to true then when selecting a value checkboxes lose its value...
Any workarounds on this?
Here is the code :
<asp:DropDownList ID="dropdown" runat="server" class="pop" AutoPostBack="true" >
</asp:DropDownList>
<asp:Repeater ID="rptD" runat="server" >
<ItemTemplate>
<td valign="top" >
<input type="checkbox" class="al" />
</ItemTemplate>
</asp:Repeater>
I assume this is because you are DataBinding the Repeater not only if(!IsPostBack) but also on postbacks. Therefore the checked state will be overriden.
So do this in Page_Load(assuming C#):
if(!IsPostBack){
DataBindRepeater();
}
Whereas DataBindRepeater is a method that sets the DataSource property and DataBind the Repeater.
You might also want to use an ASP.NET Checkbox control instead of the html input type="checkbox". The checked state is reloaded only if it's a server WebControl that implements IPostBackDataHandler.
This sounds indicative of populating the checkboxes in Page_Load. Is that the case? If you're populating the controls in Page_Load then you'll want to wrap it in a conditional:
if (!IsPostBack)
{
// populate your controls from data
}
Otherwise, they'll get re-populated with each postback. When you have an autopostback or click a button or perform some other action on the page which initiates a postback, Page_Load is called before the event handler. So in effect, this is happening:
User navigates to the page
Page_Load clears and populates the checkboxes
User chooses an item in the DropDownList (triggering a postback)
Page_Load clears and populates the checkboxes
DropDownList autopostback handler is called
(On a side note... Please look into using AJAX for dynamic client-server interaction like this. Autopostback makes for a poor user experience, and as you're discovering also makes for a difficult development experience.)

Using Validation controls with a GridView

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>

2 DetailsView validation conflict problem

I have 2 DetailsView.
The first one is hidden (display:none) with DefaultMode=Insert, has RequiredFieldValidator
<asp:RequiredFieldValidator ID="valRequireAddedBy" runat="server"
ControlToValidate="txtAddedBy" SetFocusOnError="true"
Text="Your name is required." Display="Dynamic">
</asp:RequiredFieldValidator>
The second one, in edit mode.
When I try to submit it I get an error:
htmlfile: Can't move focus to the
control because it is invisible, not
enabled, or of a type that does not
accept the focus.
Only if i remove the validator from first DetailsView it works.
Can you use the ValidationGroup property on the validators to create two groups, one for each DetailsView? I'm not sure how you're firing the event that causes validation in each case, so I don't know if you can associate a ValidationGroup with the firing control or not...
In your second DetailsView, set CausesValidation property to false
That way your "EditMode" details view won't cause the validation to fire
I guess DetailsView does not expose CausesValidation property, you'd have to deal with it on your DetailsView.UpdateItem event

Resources