We have a simple datagrid. Each row has a checkbox. The checkbox is set to autopostback, and the code-behind has an event handler for the checkbox check-changed event. This all works as expected, nothing complicated.
However, we want to disable the checkboxes as soon as one is checked to prevent a double submit i.e. check box checked, all checkboxes are disabled via client side javascript, form submitted.
To achieve this I we are injecting some code into the onclick event as follows (note that the alert is just for testing!):
Protected Sub DgAccounts_ItemCreated(ByVal sender As System.Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles DgAccounts.ItemCreated
If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem Then
Dim chk As CheckBox = CType(e.Item.FindControl("chkItemChecked"), CheckBox)
chk.Attributes.Add("onclick", "alert('fired ...');DisableAllDataGridCheckBoxes();")
End If
End Sub
When inspecting the source of the rendered page we get the following:
<input id="DgAccounts__ctl2_chkItemChecked" type="checkbox" name="DgAccounts:_ctl2:chkItemChecked" onclick="alert('fired ...');DisableAllDataGridCheckBoxes();setTimeout('__doPostBack(\'DgAccounts$_ctl2$chkItemChecked\',\'\')', 0)" language="javascript" />
It all appears in order, however the server side event does not fire – I believe this is due to the checkbox being disabled, as if we just leave the alert in and remove the call to disable the checkbox it all works fine.
Can I force the check-changed event to fire even though the check box is disabled?
I haven't tested this myself but when you call your 'DisableAllDataGridCheckBoxes' method, do you need to disable the checkbox that has been checked?
If not, you could pass the calling checkbox's id and then only disable all the other checkboxes.
chk.Attributes.Add("onclick", "alert('fired ...');DisableAllDataGridCheckBoxes(" + chk.ClientId + ");")
I would think this would then allow the server side code to fire.
The reason the server side event is not firing is that disabled checkboxes do not get submited with the rest of the form.
The workaround I have used is to set the onclick event of the checkboxes to null rather than disable them - while this gives no visual clue to the user that subsequent clicks are ignored, it does prevent the double submit, and the check boxes are set top the correct state when the response is rendered.
Instead of disabling the checkboxes (which then do not get submitted), just "prevent" them from being selected. Do this by changing their onclick handler to reset the checked state. You coul dset all of the other checkboxes to disabled, and do this just for the one that is processing. Something like:
function stopChanges(cbCurrent) {
$('INPUT[type=checkbox]').disable(); // disable all checkboxes
$(cbCurrent)
.disable(false) // enable this checkbox, so it's part of form submit
.click(function() {
// reset to previous checked - effectively preventing change
$(this).checked = !$(this).checked;
}
);
}
A possible workaround, would be to do all this in the server side code of the RowCommand of the data grid.
(posting the sample in C# but won't be much different in VB I hope)
protected void myGrid_RowCommand(object sender, GridViewCommandEventArgs e)
{
if(((CheckBox)e.Item.FindControl("chkItemChecked")).Checked)
{
foreach(GridViewRow dvRow in myGrid.Rows)
((CheckBox)dvRow.FindControl("chkItemChecked")).Enabled = false;
}
}
or you could use
((CheckBox)e.Item.FindControl("chkItemChecked")).Enabled = false;
if you only want to disable the specific item.
However if you only want to implement this in client side code, it won't help you.
Related
I have an update panel which refreshes a user control. The update panel is set to conditional, and the condition is on a textbox control. Using AsyncPostBackTrigger, to fire when the text changes in the textbox, it works fine. However, what I am not getting is when the page is first loaded, and the textbox is populated with data is that it is not firing the postback trigger.
Is there a way of forcing it fire when the page is loaded for the first time?
I have tried simple things such as UpdatePanel.Update(), or txtbox.text = string.empty to force it to recognise a change- but no luck.
Any ideas anyone?
Thanks
Please replace with your ids
private void tb_Loaded(object sender, RoutedEventArgs e)
{
TextStateChanged((TextBox)sender);
}
UpdateSite.txtPhone.Loaded += new RoutedEventHandler(tb_Loaded);
I have some checkboxes and a dropdownlist when the value changes I want to refresh the page while passing the new value. I tried using autopostback; however, the value is already in the url previously so when the postback occurs the value never changes.
Example:
CurrentPage: page.aspx?tab=Home&checkbox=True
Then I uncheck the checkbox so I want it to go to the following page...
IntendedPage: page.aspx?tab=Home&checkbox=False
But instead I the autopostback gives me this page...
DestinationPage: page.aspx?tab=Home&checkbox=True
Because, I handle the building of the url through a function on my page. Perhaps I'm doing something wrong by this point. If so I'd be happy to be corrected on my current setup. What I think I need to know though is how to load a custom URL on the checkbox.checkchanged event. I hope this made sense, if not let me know I'll try and clarify it. Thanks!
You could try something like this ( I have not tested, it was just an idea).
protected void CheckBox1_CheckedChanged ( object sender, EventArgs e )
{
string url = "page.aspx?tab=Home&checkbox="+ CheckBox1.Checked.ToString();
Response.Redirect ( url );
}
And then on the page:
<asp:CheckBox ID="CheckBox1" runat="server"
oncheckedchanged="CheckBox1_CheckedChanged" />
VB.NET Conversion
Protected Sub CheckBox1_CheckedChanged(sender As Object, e As System.EventArgs) Handles CheckBox1.CheckedChanged
Dim url = "page.aspx?tab=Home&checkbox=" & CheckBox1.Checked.ToString()
Response.Redirect(url)
End Sub
This is very easy to do through javascript. First add onclick="checkCheckBox(this);" to your checkbox.
<script language = "javascript" type="text/javascript">
function checkCheckBox(checkbox) {
if (checkbox.checked) {
window.location.href = '../page.aspx?tab=Home&checkbox=True';
}
else {
window.location.href = '../page.aspx?tab=Home&checkbox=False';
}
}
</script>
This should do it pretty easily.
This behavior is caused by the viewstate. The checkbox use it to persists its property, especially the checked property.
Actually, there is no out of the box link between a control and query string.
In your case, you will have two options, depending on your needs :
in the Checked event, build the expected url, and redirect the user to this page. The drawback is that you "loose" the viewstate and thus, the controls' state.
instead of using postbacks, use client side script (jQuery is your friend) to hide/show parts of the page. If the url matters, use # in the urls because it does allow staying on the same page.
I have a page in ASP.net written in VB.net.
It is a series of checklists that the user will click on. When they click "SUBMIT" VBScripts will run in the background and post to a database.
I need to then get results from the database in a table.
I think I will use either GridView or ListView to do this. A requirement is when the user hits submit, the table will appear on the same page and the preexisting "SUBMIT" button will disappear.
Does this make sense? What may be the best way for me to go about this?
Currently I do not have the DB implemented but that is something I am planning to have in a week. I do have a "test" DB I can utilize.
Could you simply set the visibility of the button to false and the gridview to true during postback?
e.g.
If(Not IsPostBack) Then
{
submitButton.Visible = true; // show button
gridView.Visible = false; // hide grid
}
Else
{
submitButton.Visible = false; // user submitted, so hide button
gridView.Visible = true; // show grid
}
EndIf
You could also use the Wizard control, ask the Questions in Step 1 and return the response in Step 2. That is just an alternative, but the above is really the way to go.
In your Submit button code, after your VBScript runs you can just set the visibility of the Asp.net controls to false.
Something like this.
Private Sub btnSubmit_Click(sender As Object, e As EventArgs)
...
btnSubmit.visible = false
gridview1.visible = true
End Sub
Also on the .aspx page set these control to there default state so the submit button when the user first gets to the page should by visible, and the gridview to be not visible.
Hope this helps.
I have a CheckBox on an ASP.NET Content Form like so:
<asp:CheckBox runat="server" ID="chkTest" AutoPostBack="true" OnCheckedChanged="chkTest_CheckedChanged" />
In my code behind I have the following method:
protected void chkTest_CheckedChanged(object sender, EventArgs e)
{
}
When I load the page in the browser and click the CheckBox it becomes checked, the page posts back, and I can see chkTest_CheckedChanged being called.
When I then click the CheckBox again it becomes unchecked, the page posts back, however chkTest_CheckedChanged is not called.
The process is repeatable, so once the CheckBox is unchecked, checking it will fire the event.
I have View State disabled in the Web.Config, enabling View State causes this issue to disappear. What can I do to have reliable event firing while the View State remains disabled?
Update:
If I set Checked="true" on the server tag the situation becomes reversed with the event firing when un-checking the CheckBox, but not the other way around.
Update 2:
I've overridden OnLoadComplete in my page and from within there I can confirm that Request.Form["__EVENTTARGET"] is set correctly to the ID of my CheckBox.
To fire CheckedChanged event set the following properties for CheckBox, AutoPostBack property should be true and should have a default value either checked false or true.
AutoPostBack="true" Checked="false"
Implementing a custom CheckBox that stores the Checked property in ControlState rather than ViewState will probably solve that problem, even if the check box has AutoPostBack=false
Unlike ViewState, ControlState cannot be disabled and can be used to store data that is essential to the control's behavior.
I don't have a visual studio environnement right now to test, but that should looks like this:
public class MyCheckBox : CheckBox
{
private bool _checked;
public override bool Checked { get { return _checked; } set { _checked = value; } }
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
//You must tell the page that you use ControlState.
Page.RegisterRequiresControlState(this);
}
protected override object SaveControlState()
{
//You save the base's control state, and add your property.
object obj = base.SaveControlState();
return new Pair (obj, _checked);
}
protected override void LoadControlState(object state)
{
if (state != null)
{
//Take the property back.
Pair p = state as Pair;
if (p != null)
{
base.LoadControlState(p.First);
_checked = (bool)p.Second;
}
else
{
base.LoadControlState(state);
}
}
}
}
more info here.
It doesn't fire because with viewstate disabled the server code does not know that the checkbox was previously checked, therefore it doesn't know the state changed. As far as asp.net knows the checkbox control was unchecked before the postback and is still unchecked. This also explains the reverse behavior you see when setting Checked="true".
I'm not sure but I guess that my solution is working only for .NET Framework 4.0:
Use ViewStateMode = "Disabled" to disable view state insted of EnableViewState="false". This will caution the same behavior except that you can save a local view state.
So, on your checkbox, set the attribute ViewStateMode = "Enabled" and the problem is solved, without implementing a custom checkbox.
It's an old post but I had to share my simple solution in order to help others who searched for this problem.
The solution is simple: Turn on AutoPostBack.
<asp:CheckBox id="checkbox1" runat="server"
AutoPostBack="True" //<<<<------
Text="checkbox"
OnCheckedChanged="knowJobCBOX_CheckedChanged"/>
I wanted to tidy things up a bit so I've just spent a bit of time testing a solution for this.
joshb is correct with his explanation for why the CheckBox behaves the way it does.
As I don't know how I got round this last year or even if I did (I can't remember what I was working on at the time to check), I've put together a simple solution/workaround.
public class CheckBox2 : CheckBox
{
protected override bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection)
{
bool isEventTarget = postCollection["__EVENTTARGET"] == UniqueID;
bool hasChanged = base.LoadPostData(postDataKey, postCollection);
hasChanged = hasChanged || isEventTarget;
return hasChanged;
}
}
If you now register CheckBox2 in your page and use it in place of your standard CheckBoxes, you will get the CheckedChanged event fired as you expect with ViewState disabled and AutoPostBack enabled.
The way this works is allowing the normal CheckBox to do its thing with validation and change checking, but then performs an additional check to see if it was the target of the event that caused the postback. If it was the target, it returns true to tell the framework to raise the CheckedChanged event.
Edit:
Please note that this only solves the problem for AutoPostBack on the CheckBox. If the PostBack is invoked from anything else (a button, for example), the CheckedChanged event still exhibits the observed problem.
I had the same problem. I have spent a lot of time on it and finally have solved it.
In my case the Checkbox was disabled by default:
<asp:CheckBox ID="chkActive" runat="server" Enabled="false"/>
It turns ViewState isn't loaded for disabled or invisible controls.
So remove Enabled="false" or Visible="false" and it will work as expeceted. And of course ViewState shouldn't be disabled.
Additionally: Check for any errors in the JavaScript console.
I experienced the same exact issue described by OP except that it only happened in Safari (checkbox worked fine in Chrome and Firefox). Upon inspecting the JavaScript console, I found an error that was being thrown by a malformed jQuery selector.
In my case, I had $('a[id*=lbView') which was missing a closing ]. This threw an error in Safari but, surprisingly, not in Chrome nor in Firefox.
The super easy answer is to set the ViewState on for that one control.
Just add the EnableViewState="true" to the AutoPostBack="true" property in the checkbox tag.
The default value of "Checked" Property of CheckBox is false (which means Uncheck). So, when you Check/Uncheck the CheckBox it compares with Checked Property.
If it does not match with Checked Property, ASP fires OnCheckedChanged Event.
If it matches with the Checked Property it will not fire the OnCheckedChanged Event.
So, in order to make ASP to fire OnCheckedChanged event when unchecking, it has to know Original value, so that it compares with the value from user and fires the event.
By adding data-originalValue='<%# Eval("ValueFromCodeBehind") %>' property in asp:CheckBox will be able to fire the OnCheckChanged Event as ASP can now able to know its previous value. So that when we change it, ASP fires OnCheckChanged Event even if we do Uncheck.
This is probably a simple question but I am not an ASP.NET developer and I am quite stuck.
I have a simple search routine that returns between zero and several hundred results. Each of these must be added to the page as a button and I want to set the text of the button and the CommandArgument property so that when the button is clicked I can read the CommandArgument back and react accordingly.
However, when I click the button the event does not run at all. How can I get it to run?
The code for building the button list (simplified for readability) is as follows:
foreach (SearchResult sr in searchResults)
{
Button result = new Button();
result.Text = sr.name;
result.CommandArgument = sr.ID.ToString();
AccountSearchResults.Controls.Add(result);
result.Click += new EventHandler(SearchResultClicked);
AccountSearchResults.Controls.Add(new LiteralControl("<br/>"));
}
At the minute to test, I have popped a label on the form to put the CommandArgument in. This code is never executed though.
void SearchResultClicked(object sender, EventArgs e)
{
Label1.Text = ((Button)sender).CommandArgument;
}
You mentioned in another answer that you are adding these when a button is clicked. Looking at your code, I would suggest that you try setting a unique ID for each button added, then ensure that on loading the page that buttons with the same IDs and CommandArgument values are reloaded. When a dynamically loaded button is clicked, it must still exist on the page after postback for the event to fire.
I think the ID is all you need, plus your requirement for the CommandArgument). You could put the ID information in the ViewState if you can't get it repeat without a long search process.
Where are you adding this buttons?
if you are adding them inside another control then the event might be raising in the parent control. This happens on DataRepeaters and DataGrids for example.
I think you need to use the OnCommand event handler, rather than the OnClick i.e. try changing this:
result.Click += new EventHandler(SearchResultClicked);
to this:
result.Command += new EventHandler(SearchResultClicked);
UPDATE
Try changing the type of second argument to your event hander from EventArgs to CommandEventArgs. You might also have to set the CommandName property on your button i.e.
result.CommandName = "foo";