我想创建一个简单的时间表应用程序,其中用户可以拥有不同的角色,并且根据角色他可以更新和查看时间表。为了更新时间表,我实现了一个datagrid,其中包含日期和时间从和时间到,格式为“HH:mm”。
我想要的是验证单元格的时间从和时间因此时间间隔尚未存在于数据网格中,例如,如果任务的工作时间为下午 2 点到下午 5 点,而用户想要插入工作时间为下午 4 点到下午 6 点的新任务,则验证应该失败。
到目前为止,我已经实现了类 ValidationRule,但是如果我使用它进行行验证,那么我无法获取新行的值,如果我将它用于单元格,我无法获取 datagrid 的 ItemSource。
还考虑使用 INotifyDataErrorInfo 但我也不知道如何到达 datagrid 的 ItemSource。
实际执行:
View:
<DataGrid HeadersVisibility="All" ItemsSource="{Binding DataList , Mode=TwoWay}"
AutoGenerateColumns="False"
RowHeaderWidth="15"
CanUserResizeColumns="False"
CanUserResizeRows="False"
Margin="10 20 10 10">
<DataGrid.Columns>
<DataGridTextColumn Header="Id" Binding="{Binding Id}" />
<DataGridTextColumn Header="User Id" Binding="{Binding UserId}" />
<DataGridTextColumn Header="Date" Binding="{Binding Date , StringFormat=\{0:dd.MM.yyyy\}}" />
<DataGridTextColumn Header="Time from">
<DataGridTextColumn.Binding>
<Binding Path="TimeFrom" StringFormat="HH:mm">
<Binding.ValidationRules>
<validation:TimeIntervalValidation/>
</Binding.ValidationRules>
</Binding>
</DataGridTextColumn.Binding>
</DataGridTextColumn>
<DataGridTextColumn Header="Time to" Binding="{Binding TimeTo , StringFormat=\{0:HH:mm\}}" />
<DataGridTextColumn Width="*" Header="Task" Binding="{Binding Task}" />
<DataGridTextColumn Width="3*" Header="Description" Binding="{Binding Description}" />
</DataGrid.Columns>
</DataGrid>
查看模型:
public class TimesheetViewModel:BindableBase
{
private List<TimeSheet> _dataList;
public List<TimeSheet> DataList
{
get => _dataList;
set
{
SetProperty(ref _dataList, value);
}
}
}
public class TimeSheet : BindableBase
{
private DateTime _date,_timeFrom,_timeTo;
private string _task, _description;
private int _id, _userId;
public int Id
{
get => _id;
set
{
SetProperty(ref _id, value);
}
}
public int UserId
{
get => _userId;
set
{
SetProperty(ref _userId, value);
}
}
public DateTime Date
{
get => _date;
set
{
SetProperty(ref _date, value);
}
}
public DateTime TimeFrom
{
get => _timeFrom;
set
{
SetProperty(ref _timeFrom, value);
}
}
public DateTime TimeTo
{
get => _timeTo;
set
{
SetProperty(ref _timeTo, value);
}
}
public String Task
{
get => _task;
set
{
SetProperty(ref _task, value);
}
}
public String Description
{
get => _description;
set
{
SetProperty(ref _description, value);
}
}
}
注意:BindableBase 是一个实现
INotifyPropertyChanged
的类
忘记添加TimeIntervalValidation
课程
public class TimeIntervalValidation:ValidationRule
{
public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
{
// implementation
return new ValidationResult(true, null);
}
}
EF 生成的 TimeSheet 模型:
namespace WpfApp1
{
using System;
using System.Collections.Generic;
public partial class Timesheet
{
public int Id { get; set; }
public int UserId { get; set; }
public System.DateTime Date { get; set; }
public System.DateTime TimeFrom { get; set; }
public System.DateTime TimeTo { get; set; }
public string Task { get; set; }
public string Description { get; set; }
public virtual User User { get; set; }
}
}
您可以将 Validationrule 的 ValidationStep 属性设置为 ValidationStep.UpdatedValue(例如在 XAML 或构造函数中),以便使用更新的值调用 Validate 函数。
<DataGrid.RowValidationRules>
<local:TimeIntervalValidation ValidationStep="UpdatedValue"/>
</DataGrid.RowValidationRules>
或在 Visual Basic 中:
Public Class TimeIntervalValidation
Inherits ValidationRule
Sub New()
Me.ValidationStep = ValidationStep.UpdatedValue
End Sub
Public Overrides Function Validate(value As Object, cultureInfo As CultureInfo) As ValidationResult
Dim drvRow As DataRowView = CType(CType(value, BindingGroup).Items(0), DataRowView)
If CType(drvRow.Row.Item("TimeFrom"), Date) < Now Then
Return ValidationResult.ValidResult
Else
Return New ValidationResult(False, "TimeFrom must be in the future.")
End If
End Function
End Class