我有以下类设置(部分取自Store open days and times):
public class Location {
[Key]
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual ICollection<LocationTime> LocationTimes { get; set; }
}
public class LocationTime {
[Key]
public virtual int Id { get; set; }
public virtual int LocationId { get; set; }
[ForeignKey("LocationId")]
public virtual Location Location { get; set; }
public virtual int TimeId { get; set; }
[ForeignKey("TimeId")]
public virtual Time Time { get; set; }
}
public class Time {
public Time(DayOfWeek day, string openTime, string closeTime) {
Day = day;
OpenTime = openTime ?? "0000";
CloseTime = closeTime ?? "0000";
}
[Key]
public virtual int Id { get; set; }
public virtual DayOfWeek Day { get; private set; }
public virtual string OpenTime { get; private set; }
public virtual string CloseTime { get; private set; }
public virtual IEnumerable<LocationTime> LocationTImes { get; set; }
public override string ToString() {
return $"{Day} : {OpenTime} to {CloseTime}";
}
}
我想弄清楚的是如何最好地编写我的控制器和视图以显示如下,确保尊重任何模型绑定,验证等。See dotnetfiddle
目前,如果选择了Time
,我不打算保存Closed
值,并且当没有价值时让应用暗示Closed
,但我不确定我喜欢这个想法。
此外,样本中的时间间隔为30分钟,这可以/将通过某些应用设置更改,因此我不想对此进行硬编码。
如果您需要更多信息,请告诉我。
感谢。
答案 0 :(得分:1)
您遇到的第一个问题是您的'时间'是string
。虽然.NET的时间不是很好,但使用TimeSpan
是一个更好的选择,并且将映射到SqlServer TIME
数据类型。
您的观点模型应为
public class LocationTimesCollectionVM
{
public IEnumerable<SelectListItem> TimeOptions { get; set; }
public IEnumerable<LocationTimesVM> Days { get; set; }
}
public class LocationTimesVM
{
public DayOfWeek Day { get; set; }
[RequiredIfNotEmpty("ClosingTime", ErrorMessage = "An opening time is required if a closing time is specified")]
public TimeSpan? OpeningTime { get; set; }
[RequiredIfNotEmpty("OpeningTime", ErrorMessage = "An closing time is required if a opening time is specified")]
[NotEqualTo("OpeningTime", ErrorMessage = "The closing time cannot equal the opening time")]
public TimeSpan? ClosingTime { get; set; }
[DisplayFormat(DataFormatString = "{0:hh\\:mm}")]
public TimeSpan? OpeningHours { get; set; }
}
请注意,OpeningHours
属性是可选的,但包含计算的开放时间并将其显示在视图中可能很有用(并在OpeningTime
或{{1时使用javascript更新其值已被选中。
我还在foolproof库中包含了一些建议的条件验证属性,用于验证值
然后GET方法(对于ClosingTime
方法)
Create
您的观点(public ActionResult Create()
{
LocationTimesCollectionVM model = new LocationTimesCollectionVM
{
Days = Enum.GetValues(typeof(DayOfWeek)).Cast<DayOfWeek>().Select(x => new LocationTimesVM
{
Day = x
}
};
ConfigureViewModel(model);
return View(model);
}
[HttpPost]
public ActionResult Create(LocationTimesCollectionVM model)
{
if (!ModelState.IsValid)
{
ConfigureViewModel(model);
return View(model);
}
// ... initialize data models from view model, save and redirect.
}
private void ConfigureViewModel(LocationTimesCollectionVM model)
{
// Generate the SelectList
int increment = 30; // This would be your stored value (i.e. 15 or 30 or 60 min intervals)
TimeSpan interval = new TimeSpan(0, increment, 0);
TimeSpan time = new TimeSpan(0, 0, 0);
TimeSpan max = new TimeSpan(23, 59, 59);
List<SelectListItem> timeOptions = new List<SelectListItem>();
while (time < max)
{
timeOptions.Add(new SelectListItem
{
Value = time.ToString(),
Text = new DateTime(time.Ticks).ToString("t")
});
time = time.Add(interval);
}
model.TimeOptions = timeOptions;
}
)将是
Create.cshtml
需要位于@model LocationTimesCollectionVM
....
@using (Html.BeginForm())
{
....
<table>
<thead> ... </thead>
<tbody>
@Html.EditorFor(m => m.Days, new { TimeOptions = Model.TimeOptions })
</tbody>
</table>
....
}
文件夹中的EditorTemplate
LocationTimesVM
,并命名为/Views/Shared/EditorTemplates/
LocationTimesVM.cshtml