我正在使用 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 不纯,我只需要一些有用的东西。