我正在编写一个使用WPF和实体框架的人力资源安全跟踪应用程序,我想要显示和编辑安全事件网格,并且在每个选定的事件下,将是由于事件而丢失数小时的网格。这意味着DataGrid用于事件的DataGrid的RowDetailsTemplate内的小时数。
我目前可以保存对现有小时行所做的更改,但我无法保存对此内部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调用之前,新的事件行(外部网格)的incident_id为0,那么任何新的小时行(内部网格)如何知道为此保存的内容?在初次通话后还需要做些额外的事情吗,包括第二次通话?感谢...
PS是的,我知道我的MVVM并不纯粹,我只需要一些有用的东西。