开发者

In vb.net, how do I force validating controls within a (winform) datarepeater after the data is populated?

I have a form with a datarepeater that contains various controls (i.e. datetimepickers, text boxes, combo box) that are populated via a binding source. I also have other controls on the form that are not part of the data repeater.

I would like to force validating all controls after the data is populated. I have successfully forced validating the non-datarepeater controls using Me.ValidateChildren() at the end of my load event. However, it does not fire the validating events for the controls within the data repeater.

I have unsuccessfully tried many different attempts to set and move focus within the datarepeater controls trying to get the validating events kicked off. I am not sure where would be the best place (e.g. in drawItem? in ItemCloned?) to place the code and what it should be exactly. Here was my latest attempt:

Private Sub DataRepeater1_DrawItem(ByVal sender As Object, ByVal e As Microsoft.VisualBasic.PowerPacks.DataRepeaterItemEventArgs) _
        Handles DataRepeater1.DrawItem

        For i = 0 To e.DataRepeaterItem.Controls.Count - 1
            e.DataRepeaterItem.Controls.Item(i).Focus()
            e.DataRepeaterItem.Controls.Item(0).Focus()
        Next

Note: I successfully hand开发者_高级运维led the validating events in the data repeater caused by user input errors. However, I have the unusual situation that the data coming into my form is already bad for some of the controls. The purpose of the form is to validate the data coming in to it and from user-input.

Thanks in advance for any help. I am newbie with vb.net.


Have you tried calling

DataRepeater1.ValidateChildren()

after calling form's Me.ValidateChildren()

MSDN link

EDIT:

Can you try this

Private Shared Function ValidateAllChildern(cc As ContainerControl) As Boolean
    Return cc.ValidateChildren() And cc.Controls.OfType(Of ContainerControl)().[Select](Function(c) ValidateAllChildern(c)).Aggregate(True, Function(x, y) x And y)
End Function

and call

ValidateAllChildren(Me)


Here is what I ended up using and it worked great. Basically, you can call the same validation functions in cellformatting and cellvalidating. Cell formatting handles the validation on initial load. Cell validating handles validation on user changes. Also, if you want a global change on user entry (e.g. change to upper case), use EditControlShowing.

A nice feature too is that it shows the little error icon in the cell the error occurred on. Here are the details, fyi.

'handles dgv validation on initial load
Private Sub dgvExample_CellFormatting(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) _
    Handles dgvExample.CellFormatting

    Dim results As String = ""

    If e.RowIndex <> -1 Then
    Select Case e.ColumnIndex
        Case 1, 2 'starting and ending service dates
        results = ValidateDate(e.Value)
        If results = "" Then
            results = ValidateDateRange(e.RowIndex)
        End If
        Case 11 'billed amount
        results = ValidateBilledAmount(e.RowIndex)
    End Select

    dgvExample.Rows(e.RowIndex).Cells(e.ColumnIndex).ErrorText = results
    End If
End Sub


'handles dgv validation from user changes
Private Sub dgvExample_CellValidating(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellValidatingEventArgs) _
    Handles dgvExample.CellValidating

    Dim results As String = String.Empty
    dgvExample.CurrentCell.ErrorText = String.Empty

    Select Case dgvExample.Columns(e.ColumnIndex).HeaderText
    Case "Start Date", "End Date"
        results = ValidateDate(e.FormattedValue)
        If results = "" Then
        results = ValidateDateRange(e.RowIndex)
        End If
    Case "Billed Amt"
        dgvExample(e.ColumnIndex, e.RowIndex).Value = FormatNumber(CType(e.FormattedValue, Double), 2, TriState.False, TriState.False, TriState.False).ToString
        results = ValidateBilledAmount(e.RowIndex)
    End Select

    dgvExample.CurrentCell.ErrorText = results

End Sub


'handles dgv dataentry events
    Private Sub dgvExample_EditingControlShowing(ByVal sender As Object, _
                        ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) _
    Handles dgvExample.EditingControlShowing

    'Change Case to upper case for all textboxes
    Dim editingControl As TextBox = TryCast(e.Control, TextBox)
    If editingControl IsNot Nothing Then
    editingControl.CharacterCasing = CharacterCasing.Upper

    End If
    End Sub

'FUNCTIONS called in above

'check dates not old or in future
Private Function ValidateDate(ByVal dte As String) As String

Dim errorMessage As String = ""

If CType(dte, Date) > Now Then
    errorMessage = "DATE cannot be in the future"
    Return errorMessage
End If

If CType(dte, Date) <= Now.Date.AddYears(-1) Then
    errorMessage = "WARNING: DATE cannot be older than 1 year"
    Return errorMessage
End If

Return errorMessage

End Function


'Checks that start date is less than end date
Private Function ValidateDateRange(ByVal rowIndex As Integer) As String

Dim errorMessage As String = ""

If CType(dgvExample.Rows(rowIndex).Cells(1).Value, Date) > _
   CType(dgvExample.Rows(rowIndex).Cells(2).Value, Date) Then
    errorMessage = "START DATE cannot be after END DATE"
End If

Return errorMessage

End Function


'validates billed amount is currency and in range
Private Function ValidateBilledAmount(ByVal rowIndex As Integer) As String

    Dim errorMessage As String = ""
    Dim billedAmt = dgvExample.Rows(rowIndex).Cells(11).Value 

    If Not String.IsNullOrEmpty(billedAmt) Then
    If IsNumeric(billedAmt) Then
        If CType(billedAmt, Decimal) > 0 Then
        If billedAmt > 100000.0 Then
            errorMessage = "BILLED AMOUNT must not exceed $100,000"
        End If
        Else
        errorMessage = "BILLED AMOUNT must be greater than $0"
        End If
    Else
        errorMessage = "BILLED AMOUNT must be numeric"
    End If
    End If

    If errorMessage = "" Then
    CalculateNewTotal()
    End If

    Return errorMessage
End Function


I just tested this and in order to get the ValidateChildren to work, you need to programmatically set the event handler using AddHandler.

Private Sub DataRepeater1_DrawItem(ByVal sender As Object, ByVal e As Microsoft.VisualBasic.PowerPacks.DataRepeaterItemEventArgs) _         Handles DataRepeater1.DrawItem          
    AddHandler e.DataRepeaterItem.Controls.Item("ctlDateTimePicker").Validated, AddressOf dtpStartingServiceDate_Validating ' Validating DatePicker
    AddHandler e.DataRepeaterItem.Controls.Item("ctlComboBox").Validated, AddressOf cboUnitType_Validating
End Sub

Once the Validated event handler is initialized, you can then call 'Me.ValidateChildren()' to cause the validation to run. I don't know if it's good or bad for your situation but the validation event will execute whenever the control's value is changed.

Let me know if that works.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜