I have been working on this problem for a while now, I would like to add a validation rule to my DatePicker that will make sure the SelectedDate is between two dates (Upper and Lower limits). I would also like these two limits to be data bound to other elements, the example I am working with an employee cannot have a birth date before they joined a company for eg. Here are my classes: LimitDates:
Public Class LimitDates
Inherits DependencyObject
Public Shared ReadOnly UpperLimitDateProperty As DependencyProperty
Public Shared ReadOnly LowerLimitDateProperty As DependencyProperty
Shared Sub New()
Dim metadata As New FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.None)
UpperLimitDateProperty = DependencyProperty.Register("UpperLimitDate", GetType(Date), GetType(LimitDates))
LowerLimitDateProperty = DependencyProperty.Register("LowerLimitDate", GetType(Date), GetType(LimitDates))
End Sub
Public Property UpperLimitDate As Nullable(Of DateTime)
Get
Return CType(GetValue(UpperLimitDateProperty), Nullable(Of DateTime))
End Get
Set(value As Nullable(Of DateTime))
SetValue(UpperLimitDateProperty, value)
End Set
End Property
Public Property LowerLimitDate As Nullable(Of DateTime)
Get
Return CType(GetValue(LowerLimitDateProperty), Nullable(Of DateTime))
End Get
Set(value As Nullable(Of DateTime))
SetValue(LowerLimitDateProperty, value)
End Set
End Property
End Class
DateValidationRule:
Public Class DateValidationRule
Inherits ValidationRule
Public Property FutureDateAllowed As Boolean = True
Public Property LimitDates As LimitDates
Public Overloads Overrides Function Validate(value As Object, cultureInfo As CultureInfo) As Windows.Controls.ValidationResult
Try
Dim d As Date = CDate(value)
If Not FutureDateAllowed And d > Now Then
Return New System.Windows.Controls.ValidationResult(False, "Future dates not allowed")
End If
If Not LimitDates Is Nothing Then
If Not LimitDates.LowerLimitDate Is Nothing Then
If d < LimitDates.LowerLimitDate Then
Return New System.Windows.Controls.ValidationResult(False, "Date must less then " & LimitDates.LowerLimitDate)
End If
End If
If Not LimitDates.UpperLimitDate Is Nothing Then
If d > LimitDates.UpperLimitDate Then
Return New System.Windows.Controls.ValidationResult(False, "Date must not be behond " & LimitDates.UpperLimitDate)
End If
End If
End If
Catch ex As Exception
Return New System.Windows.Controls.ValidationResult(False, "Not in correct format, please input a correct date. Eg. 23-04-2012")
End Try
' If hasn't returned an error already, must be okay
Return New System.Windows.Controls.ValidationResult(True, Nothing)
End Function
End Class
And XAML markup for EmployeeView:
<Label Style="{StaticResource EditViewLabel}" Grid.Row="0">Birth Date</Label>
<DatePicker Grid.Row="0" Grid.Column="1" x:Name="dtPkBirthDate" DisplayDateEnd="{Binding ElementName=dtPkStartDate, Path=SelectedDate}">
<DatePicker.SelectedDate>
<Binding Path="Employee.DateOfBirth">
<Binding.ValidationRules>
<local:DateValidationRule FutureDateAllowed="True">
<local:DateValidationRule.LimitDates>
<local:LimitDates UpperLimitDate="4/5/2010" />
</local:DateValidationRule.LimitDates>
</local:DateValidationRule>
</Binding.ValidationRules>
</Binding>
</DatePicker.SelectedDate>
</DatePicker>
It all looks fine to me, and it does work if the date is hard coded, but when I try binding to another control or to a property of the DataContext, the Limit date value is never set, only the default value of 12:00AM appears in the debugger.
Also how can I set and check if dates are null (VB.net not C# with I am used to)?
Thanks. Luke
Edit:
Okay so I think I might have worked out a little bit of why, after reading Binding ElementName. Does it use Visual Tree or Logical Tree and http://social.msdn.microsoft.com/Forums/vstudio/en-US/e359b99f-e864-4e9e-b81e-2692f240598f/binding-to-object-in-template-in-another-visual-tree?forum=wpf I think that the binding on DateValidationRule might not be finding the ElementName as both element's are siblings and so in a different visual tree..?
I will keep researching