数据网格 WPF 中的单元格验证基于其他行中的单元格值

问题描述 投票:0回答:1

我想创建一个简单的时间表应用程序,其中用户可以拥有不同的角色,并且根据角色他可以更新和查看时间表。为了更新时间表,我实现了一个datagrid,其中包含日期和时间从时间到,格式为“HH:mm”
我想要的是验证单元格的时间从和时间因此时间间隔尚未存在于数据网格中,例如,如果任务的工作时间为下午 2 点到下午 5 点,而用户想要插入工作时间为下午 4 点到下午 6 点的新任务,则验证应该失败。
到目前为止,我已经实现了类 ValidationRule,但是如果我使用它进行行验证,那么我无法获取新行的值,如果我将它用于单元格,我无法获取 datagridItemSource。 还考虑使用 INotifyDataErrorInfo 但我也不知道如何到达 datagridItemSource


实际执行:

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; }
     }
    }
c# wpf datagrid
1个回答
0
投票

您可以将 Validationrule 的 ValidationStep 属性设置为 ValidationStep.UpdatedValue(例如在 XAML 或构造函数中),以便使用更新的值调用 Validate 函数。

https://learn.microsoft.com/en-us/dotnet/api/system.windows.controls.validationstep?view=windowsdesktop-8.0

<DataGrid.RowValidationRules>
  <local:TimeIntervalValidation ValidationStep="UpdatedValue"/>
</DataGrid.RowValidationRules>

(来自 https://learn.microsoft.com/en-us/dotnet/desktop/wpf/controls/how-to-implement-validation-with-the-datagrid-control?view=netframeworkdesktop-4.8

或在 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
© www.soinside.com 2019 - 2024. All rights reserved.