User Control validation group issue - asp.net

I have two instances of a user control on a page. Both have fields and one submit button.
I have set validation groups on the fields and validators but for some reason when validating the two user controls' validators fire.

This method also works:
Dim valGroup = String.format("{0}-validation", Guid.NewGuid())
rfv001.ValidationGroup = valGroup
rfv002.ValidationGroup = valGroup
rfv003.ValidationGroup = valGroup
rfv004.ValidationGroup = valGroup
rfv005.ValidationGroup = valGroup
btnSubmit.ValidationGroup = valGroup
You only need to set the values for the ValidationGroup manually.

You could expose a property ValidationGroup in your UserControl that you would set from the Page. This value should be stored in ViewState, so that every instance of the UserControl will get different ValidationGroups(if your page assigns different).
For example:
Public Property ValidationGroup() As String
Get
Return CStr(ViewState("ValidationGroup"))
End Get
Set(ByVal value As String)
SetValidationGroupOnChildren(Me, value)
ViewState("ValidationGroup") = value
End Set
End Property
Private Sub SetValidationGroupOnChildren(ByVal parent As Control, ByVal validationGroup As String)
For Each ctrl As Control In parent.Controls
If TypeOf ctrl Is BaseValidator Then
CType(ctrl, BaseValidator).ValidationGroup = validationGroup
ElseIf TypeOf ctrl Is IButtonControl Then
CType(ctrl, IButtonControl).ValidationGroup = validationGroup
ElseIf ctrl.HasControls() And ctrl.Visible = True Then
SetValidationGroupOnChildren(ctrl, validationGroup)
End If
Next
End Sub
http://www.craigwardman.com/blog/index.php/2009/05/setting-a-validation-group-on-a-user-control/
http://justgeeks.blogspot.com/2009/09/be-careful-using-hard-coded.html
If you need different ValidationGroups in your UserControl the above recursive function won't work, then you could assign it manually from codebehind. For example by putting the UserControl's ID(might suffice) or ClientID in front of the ValidationGroup properties of the according controls. A good place where you could call this function would be PreRender.

Related

Adding unique ValidationGroup names to forms

I have a problem when adding modules/controls to a webpage in a ASP.NET CMS which have form validation that it would validate all forms on the page, because the ValidationGroup has the same name. How to solve this with a function?
I came up with below solution:
A function that iterates through a certain placeholder to assign unique ValidationGroup names to each form.
Public Shared Sub SetValGroupControls(PageModule As Control, valGroupName As String)
For Each ctrl As Control In PageModule.Controls
If TypeOf ctrl Is RequiredFieldValidator Then
DirectCast(ctrl, RequiredFieldValidator).ValidationGroup = valGroupName
ElseIf TypeOf ctrl Is RegularExpressionValidator Then
DirectCast(ctrl, RegularExpressionValidator).ValidationGroup = valGroupName
ElseIf TypeOf ctrl Is CompareValidator Then
DirectCast(ctrl, CompareValidator).ValidationGroup = valGroupName
ElseIf TypeOf ctrl Is CustomValidator Then
DirectCast(ctrl, CustomValidator).ValidationGroup = valGroupName
ElseIf TypeOf ctrl Is RangeValidator Then
DirectCast(ctrl, RangeValidator).ValidationGroup = valGroupName
ElseIf TypeOf ctrl Is Button Then
DirectCast(ctrl, Button).ValidationGroup = valGroupName
End If
If ctrl.Controls.Count > 0 Then
SetValGroupControls(ctrl, valGroupName)
End If
Next
End Sub
Where PageModule represents the placeholder where the validation controls are contained (to avoid iterating through all controls on the page) and the ValGroupName represents the unique string which will be assigned as name.
Assuming my validation controls are contained in a placeholder that is called 'plhMyForm' you can call the function like this:
Dim nGuid = String.format("{0}-validation", Guid.NewGuid())
SetValGroupControls(plhMyForm, nGuid)
Above will create a unique string like:
24ad5ae3-fead-4a6f-98f3-dffcd2e815ba-validation
Of course you can use your own unique string generation.
Now you can leave your ValidationGroup name empty and the function assigns one for you. This way every form on the same page that requires validation will individually validate itself.

Stumped With Custom Property on User Control

I have created an ASP.NET usercontrol. When I explicity provide the value for a custom property, the value is passed to the control. However, when I try to use the value from a datasource, the value is not passed to the control.
The user control sits within a FormView. The FormView successfully displays the underlying record. I am attempting to pass to the control a value in a column from the FormView's datasource. This works
<asp:formview .... />
<editTemplate>
<uctrl:DateSelector ID="DateSelector1" runat="server" DateValue="5/30/2011" /><br />
<%#Eval("MilestoneDate")%>
</editTemplate>
</asp:formview>
This does not...
<asp:formview .... />
<editTemplate>
<uctrl:DateSelector ID="DateSelector1" runat="server" DateValue='<%#Eval("MilestoneDate")%>' /><br />
<%#Eval("MilestoneDate")%>
</editTemplate>
</asp:formview>
I have confirmed that MileStoneDate does have a value in it. For whatever the reason, the value is not being passed to the control, however the control does recognize a literal value.
Imports Microsoft.VisualBasic
Imports System.Data
Imports System.Data.SqlClient
Imports System.Web.UI
Imports System.ComponentModel
Partial Class content_WebUserControl
Inherits System.Web.UI.UserControl
<Bindable(True, BindingDirection.OneWay)>
Public Property DateValue() As String
Get
Return _DateValue
End Get
Set(ByVal value As String)
_DateValue = value
End Set
End Property
Private _DateValue As String
Protected Sub Page_Load() Handles Me.Load
If IsDate(Me.DateValue) Then
Dim NewDate As DateTime = CDate(Me.DateValue)
LabelSelectedDateDisplay.Text = Me.DateValue
LabelSelectedDateDisplay_DayOfWeek.Text = NewDate.ToString("dddd")
TextBoxSelectedDate.Text = Me.DateValue
Else
LabelSelectedDateDisplay.Text = ""
LabelSelectedDateDisplay_DayOfWeek.Text = ""
TextBoxSelectedDate.Text = ""
End If
End Sub
End Class
I was refered to the post at this URL ASP.NET User Control : can't initialize a user control property using Eval("...")
However, based on my understanding of the post, what I have should be working.
You need to use ViewState to persists DateValue between page requests.
Public Property DateValue() As String
Get
IF IsNothing(ViewState("datevalue") Then
return String.Empty
End If
return ViewState("datevalue").ToString()
End Get
Set(ByVal value As String)
ViewState("datevalue")=value
End Set
End Property
Or store value directly to the controls:
Public Property DateValue() As String
Get
Return LabelSelectedDateDisplay.Text
End Get
Set(ByVal value As String)
If IsDate(value) Then
Dim NewDate As DateTime = CDate(value)
LabelSelectedDateDisplay.Text = NewDate
LabelSelectedDateDisplay_DayOfWeek.Text = NewDate.ToString("dddd")
TextBoxSelectedDate.Text = NewDate
Else
LabelSelectedDateDisplay.Text = ""
LabelSelectedDateDisplay_DayOfWeek.Text = ""
TextBoxSelectedDate.Text = ""
End If
End Set
End Property
The problem is that databinding doesn't occur on your formview until after Page.Load, and you are checking the value of the property during that time. If you want the value to be set in Page.Load you need to manually bind using FormView.Databind().
Alternatively, you can change the code you listed in your custom control from handling Page.Load to handle Page.Prerender, if nothing requires that code to execute earlier.
It looks like the issue might be timing/event related.
When you set a property with <%# %>, the value is assigned to the property during the Control's databinding event. If you look for it at Page_Load() time, it won't be there yet.
If you change your code to check the value in the PreRender event, it should be there.

Custom Validator Not Firing (No error message, but no validation)

I have a custom validator:
<asp:CustomValidator ID="QuestionValidator" runat="server" ErrorMessage="Please select an option" ClientValidationFunction="QuestionValidator_ServerValidate" OnServerValidate="QuestionValidator_ServerValidate" ValidateEmptyText="true"></asp:CustomValidator>
I have a list of questions provided by a datalist, which I need to ensure a user selects an answer to each question. I then have my validation functions:
Protected Sub QuestionValidator_ServerValidate(ByVal source As Object, ByVal args As ServerValidateEventArgs)
Dim SelectedItem As Boolean = False
For Each c As Control In Page.Master.FindControl("form1").Controls
If TypeOf c Is RadioButton Then
Dim rb As RadioButton = DirectCast(c, RadioButton)
If rb.GroupName = "AnswerOptions" AndAlso rb.Checked = True Then
SelectedItem = True
End If
End If
Next
args.IsValid = SelectedItem
End Sub
<script type="text/javascript" language="javascript">
function QuestionValidator_ServerValidate() {
return true;
}
</script>
When I run the page, there is no validation and no error message. Please can you point out where I am going wrong, I'm suspicious it is at Page.Master.FindControl("form1").Controls.
I have previously done such validation by looping through controls via form1.controls but this is unavailable as the page uses a form passed down via the master page.
There could be a flaw in your code. Because as per the logic if out of 50 radio buttons on your page even if just one is selected your validation will pass. Also the groupname for all the RBs is same for each item. Not sure if ASP.NET renames those and if not then all RBs with be grouped into one for all the questions.
For the looping part you can loop through DataList.Items collection instead of looping through all controls on the form:
Dim item As DataListItem
For Each item In DataList1.Items
Dim ctrl As Control
For Each ctrl In item.Controls
'do your rb state check here
Next ctrl
Next item
I would try looping through either "Page.NamingContainer" or "Page.Controls" and see how that goes.
Maybe I missed something, but shouldn't You also set property ControlToValidate="ID_of_the_control_to_validate" in the custom validator?
I think you need to give ValidationGroup for the CustomValidator and all the Controls Involved in the Validaiton process

How can I access textbox properties in a custom validator?

I want to build a custom validator control that inherits from BaseValidator. It will only be used on textboxes in my asp.net application. How can I get access to the textbox itself (read properties of the textbox) within the custom validator?
Here is what I have in my EvaluateIsValid function:
Dim t As TextBox = CType(Page.FindControl(Me.ControlToValidate), TextBox)
Return t.Text.Length <= t.MaxLength
It can't seem to find the control, so it breaks with a null reference exception. Can I do this another way?
Thanks!
To get the textbox:
Dim t As TextBox = CType(Me.FindControl(Me.ControlToValidate), TextBox)

How to enable/disable web elements of a parent aspx page from the child ascx page?

I have an aspx page with three web controls: one to control the List Users page, one to control the Edit Users page, and one to control the Add User page. I have discovered a method for accessing these elements, but it seems to be limited. Here is what I have done:
Protected Sub editUser(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewEditEventArgs)
'set selected user from gridview.
Dim index As Integer = e.NewEditIndex
Dim userId As Integer = gvListUsers.DataKeys(index).Value
Session.Item("SelectedUserId") = userId
'show edit page, hide list and add page.
With Page.Form.Controls(1)
.Controls(getControlId("loadAddUser")).Visible = False
.Controls(getControlId("loadEditUser")).Visible = True
.Controls(getControlId("loadListUser")).Visible = False
End With
End Sub
The getControlId function looks like this:
Public Function getControlId(ByVal control As String) As Integer
Dim enumer As System.Collections.IEnumerator = Page.Form.Controls.Item(1).Controls.GetEnumerator
Dim i As Integer
For i = 0 To (Page.Form.Controls.Item(1).Controls.Count - 1)
If Page.Form.Controls(1).Controls.Item(i).ID = control Then
Return i
End If
Next
Return Nothing
End Function
This works in most cases. However, I am unable to access the "enabled" attribute of these web controls. Why is this, and how might I access that attribute?
Thanks :)
You could raise events from your UserControls which you subscribe to in the parent ASPX page. In the parent page event action you could enable/disable your controls,
Here's an example of events in UserControls: http://codebetter.com/blogs/brendan.tompkins/archive/2004/10/06/Easily-Raise-Events-From-ASP.NET-ASCX-User-Controls.aspx
Something else to think about: are you getting any benefit from moving this code into usercontrols? Would any of the individual controls be re-usable on their own? Creating tightly coupled controls that rely on each other being present doesn't give you much re-usability of the individual controls.
Visible is a property provided by the System.Web.UI.Control class, which is why you can access it directly. Enabled is not a property on this class, so you need to map the control object to a variable of the type of your custom control class if you want to access the Enabled property.
Dim myControl As TheAddUserControl
With Page.Form.Controls(1)
myControl = .Controls(getControlId("loadAddUser"))
myControl.Enabled = False
.Controls(getControlId("loadEditUser")).Visible = True
.Controls(getControlId("loadListUser")).Visible = False
End With
To expose an Enabled property in you user control:
Public Property Enabled As Boolean
Get
Return (Child1.Enabled And Child2.Enabled And Child3.Enabled)
End Get
Set(ByVal value As Boolean)
Child1.Enabled = value
Child2.Enabled = value
Child3.Enabled = value
End Set
End Poperty

Resources