0

我正在使用 WPF 和实体框架编写 HR 安全跟踪应用程序,我想在其中显示和编辑安全事件网格,并且在每个选定的事件下将是几个月的网格,在该网格中,由于事件而损失了几个小时。这意味着事件的 DataGrid 的 RowDetailsTemplate 内的小时数的 DataGrid。

我目前可以保存对现有小时行所做的更改,但无法将添加或删除保存到这个内部 DataGrid。我的相关型号代码:

[Table("hr.safety_incident")]
public partial class SafetyIncident
{
    [Key]
    [Column(TypeName = "numeric")]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public decimal incident_id { get; set; }

    [Column(TypeName = "datetime2")]
    public DateTime incident_date { get; set; }

    [Required]
    [StringLength(30)]
    public string incident_type { get; set; }
}

// EDIT: forgot this part of the class
public partial class SafetyIncident    // In another file
{
    protected ObservableCollection<SafetyHours> _lostHoursDetails;

    [NotMapped]
    public ObservableCollection<SafetyHours> LostHoursDetails
    {
        get { return _lostHoursDetails; }
        set
        {
            if (_lostHoursDetails != value)
            {
                _lostHoursDetails = value;
            }
        }
    }
}

[Table("hr.safety_hours")]
public partial class SafetyHours
{
    [Key]
    [Column(TypeName = "numeric")]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public decimal safety_hours_id { get; set; }

    [Column(TypeName = "numeric")]
    public decimal incident_id { get; set; }

    [Column(TypeName = "datetime2")]
    public DateTime safety_hours_date { get; set; }

    [Column(TypeName = "numeric")]
    public decimal restricted_hours { get; set; }

    [Column(TypeName = "numeric")]
    public decimal lost_hours { get; set; }
}

相关 XAML:

<DataGrid x:Name="dtgAllIncidents" AutoGenerateColumns="False" 
        ItemsSource="{Binding Source={StaticResource safetyIncidentViewSource}}" 
        RowDetailsVisibilityMode="VisibleWhenSelected">
    <DataGrid.Columns>
        <DataGridTemplateColumn x:Name="incident_dateColumn" Header="Incident Date" Width="110" SortMemberPath="incident_date">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <DatePicker IsHitTestVisible="False" 
                        SelectedDate="{Binding incident_date, Mode=TwoWay, NotifyOnValidationError=true, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=true}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
            <DataGridTemplateColumn.CellEditingTemplate>
                <DataTemplate>
                    <DatePicker SelectedDate="{Binding incident_date, Mode=TwoWay, NotifyOnValidationError=true, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=true}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellEditingTemplate>
        </DataGridTemplateColumn>
        <DataGridTextColumn Header="Incident Type" Binding="{Binding incident_type}"/>
    </DataGrid.Columns>
    <DataGrid.RowDetailsTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="Enter data into the blank row to add lost and restricted hours.”/>
                <DataGrid x:Name="dtgLostHoursDetails" ItemsSource="{Binding LostHoursDetails}" AutoGenerateColumns="False" CanUserAddRows="True" CanUserDeleteRows="True">
                    <DataGrid.Columns>
                        <DataGridTemplateColumn x:Name="incident_dateColumn" Header="Month in Which Hours Lost">
                            <DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                    <DatePicker IsHitTestVisible="False"
                                            SelectedDate="{Binding safety_hours_date, Mode=TwoWay, NotifyOnValidationError=true, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=true}"/>
                                </DataTemplate>
                            </DataGridTemplateColumn.CellTemplate>
                            <DataGridTemplateColumn.CellEditingTemplate>
                                <DataTemplate>
                                    <DatePicker SelectedDate="{Binding safety_hours_date, Mode=TwoWay, NotifyOnValidationError=true, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=true}"/>
                                </DataTemplate>
                            </DataGridTemplateColumn.CellEditingTemplate>
                        </DataGridTemplateColumn>
                        <DataGridTextColumn Width="SizeToHeader" Header="Lost Hours" Binding="{Binding lost_hours}"/>
                        <DataGridTextColumn Width="SizeToHeader" Header="Restricted Hours" Binding="{Binding restricted_hours}"/>
                    </DataGrid.Columns>
                </DataGrid>
            </StackPanel>
        </DataTemplate>
    </DataGrid.RowDetailsTemplate>
</DataGrid>

相关代码隐藏:

private ObservableCollection<SafetyIncident> _incidents;
private SafetyIncidentsViewModel _incidentsVM = new SafetyIncidentsViewModel();

private void mniIncidents_Click(object sender, RoutedEventArgs e)
{
    CollectionViewSource safetyIncidentViewSource = ((CollectionViewSource)this.FindResource("safetyIncidentViewSource")));
    _incidents = _incidentsVM.GetIncidents();
    safetyIncidentViewSource.Source = _incidents;
}
private void btnSaveIncidents_Click(object sender, RoutedEventArgs e)
{
    _incidentsVM.SaveChanges();
    dtgAllIncidents.Items.Refresh();
}

...

public class SafetyIncidentsViewModel
{
    private Corp_DB _context = new Corp_DB();

    public ObservableCollection<SafetyIncident> GetIncidents()
    {
        ObservableCollection<SafetyIncident> results = null;
        LoadSafetyIncidents();
        results = _context.safety_incident.Local;
        return results;
    }

    private void LoadSafetyIncidents()
    {
        _context.safety_incident.OrderBy(si => si.incident_date).Load();
        _context.safety_hours.Load();
        foreach (var i in _context.safety_incident)
        {
            var lostHours = new ObservableCollection<SafetyHours>();
            foreach (var h in _context.safety_hours.Where(sh => sh.incident_id == i.incident_id).OrderBy(sh => sh.safety_hours_date))
            {
                lostHours.Add(h);
            }
            i.LostHoursDetails = lostHours;
        }
    }

    public void SaveChanges()
    {
        // Assign new hours rows their safety incident.  Open to more automatic way...
        foreach (var si in _context.safety_incident)
        {
            foreach (var sh in si.LostHoursDetails.Where(h => h.incident_id == 0))
            {
                sh.incident_id = si.incident_id;
            }
        }
        _context.SaveChanges();
    }

...

另一个复杂点:在调用 _context.SaveChanges 之前,新事件行(外部网格)的事件 ID 将为 0,那么任何新的时间行(内部网格)如何知道为此保存什么?在第一次通话后是否需要做一些额外的事情,包括第二次通话?谢谢……</p>

PS 是的,我知道我的 MVVM 不纯,我只需要一些有用的东西。

4

0 回答 0