Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people, just like you, are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
Solved

Can we fix an AJAX Enabled ASP.NET 2.0 Web Form with UpdatePanels controlling Validation controls?

Posted on 2008-06-10
21
1,336 Views
Last Modified: 2013-11-07
What I need to happen is to have 3 controls (2 dropdownlists and one date User Control) only be required if any of the 3 have values.

The code I've attached is complete and will run with the exception of the Date User Control.  It is simply a textbox (with the OnTextChanged event exposed), a MaskedEditExtender, a CalendarExtender, and a RequiredFieldValidator.  The IsRequired property simply sets the RequiredFieldValidator.Enabled (this of course is on the Date's textbox).

My problem is that the code when clearing the Date's Textbox, it doesn't fire the OnTextChanged event.  Also, the two DropDownLists do fire, but the validation controls aren't always set (I can't make this happen consistently).

Thank you!
<table width="948" id="tblMain" runat="server">
    
    <tr align="left">
        <td></td>
        <td></td>
        <td></td>
        <td>Test Text (never required):</td>
        <td>
            <asp:TextBox runat="server" ID="txtTest" />
        </td>
    </tr> 
    
        <tr align="left">
            <td></td>
            <td></td>
            <td></td>
            <td>DropDownList1 (if selected DropDownList2 and Date1 are required):</td>
            <td>
                <asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="true" OnSelectedIndexChanged="CheckValidation_TextChanged">
                    <asp:ListItem Text="[Select]" value="0"></asp:ListItem>
                    <asp:ListItem Text="something1" value="1"></asp:ListItem>
                    <asp:ListItem Text="something2" value="2"></asp:ListItem>
                </asp:DropDownList>
                <asp:UpdatePanel ID="UpdatePanel1" runat="server" RenderMode="Inline" UpdateMode="conditional">
                    <ContentTemplate>
                        <asp:CompareValidator ID="cvDropDownList1" runat="server" ControlToValidate="DropDownList1" 
                        ErrorMessage="DDL 1 must be selected." Operator="NotEqual" ValueToCompare="0" 
                        SetFocusOnError="True" Enabled="false" >*</asp:CompareValidator>
                    </ContentTemplate>
                    <Triggers>
                        <asp:AsyncPostBackTrigger ControlID="DropDownList1" EventName="SelectedIndexChanged" />
                    </Triggers>
                </asp:UpdatePanel>
            </td>
        </tr>
        <tr align="left">
            <td></td>
            <td></td>
            <td></td>
            <td>DropDownList2 (if selected DropDownList1 and Date1 are required):</td>
            <td>
                <asp:DropDownList ID="DropDownList2" runat="server" AutoPostBack="true" OnSelectedIndexChanged="CheckValidation_TextChanged" >
                    <asp:ListItem Text="[Select]" value="0"></asp:ListItem>
                    <asp:ListItem Text="something else 1" value="1"></asp:ListItem>
                    <asp:ListItem Text="something else 2" value="2"></asp:ListItem>
                </asp:DropDownList>
                <asp:UpdatePanel ID="UpdatePanel2" runat="server" RenderMode="Inline" UpdateMode="conditional">
                    <ContentTemplate>
                        <asp:CompareValidator ID="cvDropDownList2" runat="server" ControlToValidate="DropDownList2" 
                        ErrorMessage="DropDownList2 must be selected." Operator="NotEqual" ValueToCompare="0" 
                        SetFocusOnError="True" Enabled="false" >*</asp:CompareValidator>
                </ContentTemplate>
                <Triggers>
                    <asp:AsyncPostBackTrigger ControlID="DropDownList2" EventName="SelectedIndexChanged" />
                </Triggers>
            </asp:UpdatePanel>
            </td>
        </tr>
        <tr align="left">
            <td></td>
            <td></td>
            <td></td>
            <td>Date 1 (if entered DropDownList1 and DropDownList2 are required):</td>
            <td><user:DateEntry id="usrDate" runat="server" IsRequired="false" RequiredErrorMessage="Date is required." OnTextChanged="CheckValidation_TextChanged" ></user:DateEntry></td>
        </tr>
        <tr>
            <td align="right" colspan="5">
                <asp:Button ID="btnSave" runat="server" Text="Save" OnClick="btnSave_Click" />
            </td>
        </tr> 
    </table>
 
 
--CODE BEHIND--
protected void btnSave_Click(object sender, EventArgs e)
    {
        if (Page.IsValid)
        {
            Response.Write("WHAT??");
        }
    }
 
    protected void CheckValidation_TextChanged(object sender, EventArgs e)
    {
        AssessValidate(DropDownList1.SelectedIndex != 0 || DropDownList2.SelectedIndex != 0 ||
           !string.IsNullOrEmpty(usrDate.Value));
    }
 
    private void AssessValidate(bool isRequired)
    {
        cvDropDownList1.Enabled = isRequired;
        cvDropDownList1.EnableClientScript = isRequired;
        cvDropDownList2.Enabled = isRequired;
        cvDropDownList2.EnableClientScript = isRequired;
        usrDate.IsRequired = isRequired;
    }

Open in new window

0
Comment
Question by:sjd01032
  • 11
  • 9
21 Comments
 
LVL 33

Expert Comment

by:raterus
ID: 21755024
What's this <user:DateEntry> control and how can I know the events you have attached to it actually function as expected and are compatible with asp.net ajax?
0
 

Author Comment

by:sjd01032
ID: 21766507
As I stated (and I'll attach the code tomorrow):

<user:DateEntry> is simply a textbox (with the OnTextChanged event exposed), a MaskedEditExtender, a CalendarExtender, and a RequiredFieldValidator.  The IsRequired property simply sets the RequiredFieldValidator.Enabled (this of course is on the Date's textbox).

None of the controls are other than ASP and AJAX.
0
 
LVL 33

Expert Comment

by:raterus
ID: 21768148
Yes, please send the code.  I'd also look at the browser's source to make sure you actually see an "onchange" event listed for the textbox.
0
Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

 

Author Comment

by:sjd01032
ID: 21768752
The OnTextChanged event does fire when populating the textbox, but not always when clearing it.  I've attached the code for the user control.

I've attached the source code and what was rendered in the table for the DropDownList2 and Date 1

I don't see an onchange JS for the textbox like I do for DropDownList2 - evidently this is where I need the help?
<%@ Control Language="C#" AutoEventWireUp="false" CodeFile="DateEntry.ascx.cs" Inherits="DateEntry" %>
<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="ajaxToolkit" %>
<table border="0" cellpadding="0" cellspacing="0">
    <tr>
        <td nowrap>
            <asp:TextBox ID="txtDate" runat="server" OnTextChanged="txtDate_TextChanged" Columns="10"></asp:TextBox><asp:Image ID="imgDate" SkinId="ImageCalendar" runat="server" />
            <ajaxToolkit:MaskedEditExtender ID="meeDate" runat="server" Century="2000" ClearMaskOnLostFocus="True" Mask="99/99/9999" MaskType="Date" TargetControlID="txtDate" />
            <ajaxToolkit:CalendarExtender ID="ceDate" runat="server" TargetControlID="txtDate" PopupButtonID="imgDate" />
        </td>
        <td class="RequiredIndicator">
            <asp:RequiredFieldValidator ID="rfvDate" runat="server" ControlToValidate="txtDate"
                ErrorMessage="Field is required." Display="Dynamic" Enabled="False">*</asp:RequiredFieldValidator>
            <asp:CompareValidator id="cvDate" runat="server" ControlToValidate="txtDate"
                    Display="dynamic" Enabled="false">*</asp:CompareValidator>
        </td>
    </tr> 
</table>
 
----------------code behind begin:
public partial class DateEntry : System.Web.UI.UserControl
{
    public event EventHandler TextChanged;
 
    protected virtual void OnTextChanged()
    {
        if (TextChanged != null)
            TextChanged(this, new EventArgs());
    }
 
    protected void txtDate_TextChanged(object sender, System.EventArgs e)
    {
        OnTextChanged(); // raise the trlTextChanged event
    }
 
/// <summary>
    /// Determines whether or not entry is required for the control.
    /// </summary>
    /// <value>trus/false</value>
    public bool IsRequired
    {
        get { return rfvDate.Enabled; }
        set { rfvDate.Enabled = value; }
    }
 
    /// <summary>
    /// Sets/gets the message that is displayed when the required field validation fails.
    /// </summary>
    /// <value>String</value>
    public string RequiredErrorMessage
    {
        get { return rfvDate.ErrorMessage; }
        set { rfvDate.ErrorMessage = value; }
    }
}
 
 
----------------code behind end-----segment of source begin:
 
 
<tr align="left">
		<td></td>
		<td></td>
		<td></td>
		<td>DropDownList2 (if selected DropDownList1 and Date1 are required):</td>
		<td>
                <select name="ctl00$MainContentPlaceHolder$DropDownList2" onchange="javascript:setTimeout('__doPostBack(\'ctl00$MainContentPlaceHolder$DropDownList2\',\'\')', 0)" id="ctl00_MainContentPlaceHolder_DropDownList2">
			<option selected="selected" value="0">[Select]</option>
			<option value="1">something else 1</option>
			<option value="2">something else 2</option>
 
		</select>
                <span id="ctl00_MainContentPlaceHolder_UpdatePanel2">
                        <span id="ctl00_MainContentPlaceHolder_cvDropDownList2" style="color:Red;visibility:hidden;">*</span>
                </span>
            </td>
	</tr>
	<tr align="left">
		<td></td>
		<td></td>
		<td></td>
		<td>Date 1 (if entered DropDownList1 and DropDownList2 are required):</td>
		<td>
<table border="0" cellpadding="0" cellspacing="0">
    <tr>
        <td nowrap>
            <input name="ctl00$MainContentPlaceHolder$usrDate$txtDate" type="text" size="10" id="ctl00_MainContentPlaceHolder_usrDate_txtDate" /><img id="ctl00_MainContentPlaceHolder_usrDate_imgDate" src="../images/calendar.png" style="border-width:0px;" />
            <input type="hidden" name="ctl00$MainContentPlaceHolder$usrDate$meeDate_ClientState" id="ctl00_MainContentPlaceHolder_usrDate_meeDate_ClientState" />
            
        </td>
        <td class="RequiredIndicator">
            <span id="ctl00_MainContentPlaceHolder_usrDate_rfvDate" style="color:Red;display:none;">*</span>
            <span id="ctl00_MainContentPlaceHolder_usrDate_cvDate" style="color:Red;display:none;">*</span>
        </td>
 
----------------end of source segment

Open in new window

0
 

Author Comment

by:sjd01032
ID: 21777699
Bumped the points - why no interest?  Should I include something else?
0
 
LVL 33

Expert Comment

by:raterus
ID: 21778283
Sorry, I was away from my computer for a day.  Have you tried adding autopostback="true" to the textbox in the UserControl?  This is the only way you can raise server events when they happen.
0
 

Author Comment

by:sjd01032
ID: 21778561
raterus - this caused a nice little infinite loop.  Below is the code I added.  I've rolled back so no one else gets stuck in the same loop.  What am I doing wrong?

Thanks for not giving up on me!
Infinite loop with AutoPostBack="true":
 
ASPX:
<user:DateEntry id="usrDate" runat="server" AutoPostBack="true" IsRequired="false" RequiredErrorMessage="Date is required." OnTextChanged="CheckValidation_TextChanged" ></user:DateEntry>
 
ASCX Code Behind:
/// <summary>
    /// Gets or sets the AutoPostBack property of the date textbox
    /// </summary>
    public bool AutoPostBack
    {
        get { return txtDate.AutoPostBack; }
        set { txtDate.AutoPostBack = value; }
    }

Open in new window

0
 

Author Comment

by:sjd01032
ID: 21778674
I think this post "explains" the infinite loop issue:  http://www.codeplex.com/AjaxControlToolkit/WorkItem/View.aspx?WorkItemId=13013

What I don't understand is the comment, "Problem was resolved with manually setting loaded control ID. "
0
 

Author Comment

by:sjd01032
ID: 21778734
Info:  I'm using AjaxControlToolKit.dll version 1.0.20229.20675
0
 
LVL 33

Expert Comment

by:raterus
ID: 21778782
As I think you've already suspected, I don't think the AutoPostBack=True is to blame here, I think it just enabled what you were hoping would work, to actually work, and now you need to work out the bugs with the OnTextChanged event.

I couldn't make much sense of that article you just posted either.  That would make sense if you are dynamically loading controls, but I don't see you doing that.

I think right now, you just need to isolate the issue.  Forget right now raising the event in the UserControl so the base page can use it.  Just get the textchanged event of the textbox working, and then we'll work in the other part.  I don't know about you, but I'm getting lost in all these eventhandlers!
0
 

Author Comment

by:sjd01032
ID: 21778899
Actually, I just read, "The problem is an infinate loop of postbacks occures when using the MaskedEditExtender on a textbox that has autopostback enabled" from this page:  

http://www.codeplex.com/AjaxControlToolkit/WorkItem/View.aspx?WorkItemId=15445

So, I disabled the MaskedEditExtender and it's working.  Now I have to get the MaskedEditExtender to work and I'll be in good shape!  Any thoughts on that one?
0
 
LVL 33

Expert Comment

by:raterus
ID: 21778944
Sorry, that's over my head!  Sounds like it's a bug that needs to be fixed, and until then you'll have to just disable the MaskedEditExtender and find another way.
0
 

Author Comment

by:sjd01032
ID: 21779372
Well, I still have half the original problem.  

"My problem is that the code when clearing the Date's Textbox, it doesn't fire the OnTextChanged event..." - OK - THIS WORKS NOW

"...Also, the two DropDownLists do fire, but the validation controls aren't always set (I can't make this happen consistently)." - THIS STILL DOESN'T work consistently.
0
 
LVL 33

Expert Comment

by:raterus
ID: 21779485
Ok, lets go back to the beginning.  Looks like you only want the DropDownLists to be validated when certain conditions are met in the page.  Can you tell me more about these conditions?  It's hard to determine it from your example.

e.g.

"if they enter text, then dropdownlist1 & 2 are required",
or
"if no text is entered, only date is required", stuff like that, etc.
0
 

Author Comment

by:sjd01032
ID: 21815200
There are 3 controls: 2 dropdownlists and the Date user control we worked with earler.

If any of the controls have a value (selectedindex != 0 for either dropdown - and the date has a value), then all 3 of those controls need to have their validation enabled.  By default the validation controls are disabled since on page load none of the 3 controls have values.

I think I've supplied all the code you'd need to make it run - you can see that it works kind of randomly and I can't figure out why.

Any help?
0
 
LVL 33

Expert Comment

by:raterus
ID: 21815727
When an UpdatePanel "refreshes", it is only going to change the state of the controls within it.  I think you have two options.  Create one large UpdatePanel that holds all the controls and their validators.  Or enabled/disable the validators from javascript (I think this can be done, but I can't provide you an example)
0
 

Author Comment

by:sjd01032
ID: 21830101
Hey - sorry about the delay on testing this.  I'll get on it this weekend and have results for Monday.
0
 
LVL 33

Expert Comment

by:raterus
ID: 21883826
I don't think that's your solution here.  You said yourself in the next comment "I still have my original problem..", which we dialoged about for a few more days and then you disappeared?
0
 

Author Comment

by:sjd01032
ID: 21884135
You know how Monday  turns into Friday so quickly.  Actually I went back and tested and it's working.  So, I do believe that was the culprit.  Thank you for your attention on this matter.  I don't know the etiquette here - should I give you the points for being a sounding board (which is normally what helps the most)?  I don't have a problem with that...Let me know.
0
 
LVL 33

Accepted Solution

by:
raterus earned 425 total points
ID: 21884164
It's really up to you, if I've helped you anyway, any how, then you should give the points where it helped most.
0

Featured Post

Networking for the Cloud Era

Join Microsoft and Riverbed for a discussion and demonstration of enhancements to SteelConnect:
-One-click orchestration and cloud connectivity in Azure environments
-Tight integration of SD-WAN and WAN optimization capabilities
-Scalability and resiliency equal to a data center

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
FInd Image Control Gridview 3 20
Open a link in vb.net 2 15
ASP.NET Content Page 3 25
Where does legacy ASP.NET initialize language? 2 20
Today I had a very interesting conundrum that had to get solved quickly. Needless to say, it wasn't resolved quickly because when we needed it we were very rushed, but as soon as the conference call was over and I took a step back I saw the correct …
This article shows how to deploy dynamic backgrounds to computers depending on the aspect ratio of display
In an interesting question (https://www.experts-exchange.com/questions/29008360/) here at Experts Exchange, a member asked how to split a single image into multiple images. The primary usage for this is to place many photographs on a flatbed scanner…

809 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question