ユーザーが選択できる月のリストをレンダリングする Html.DropDownList があります。ページが最初に表示された場合 (基本的にリクエスト パラメーターなし)、デフォルトで現在の月が選択されるようにします。これでは仕事に行けません。現在の月に関係なく、常に 1 月が最初に選択されます。
これに関するやや奇妙な点は、実際の月の値ではなく、月の値がオフセット値として選択されることです。したがって、現在の月が 4 月の場合、月のリストは次のようになります。
1 月 = -3、2 月 = -2、3 月 = -1、4 月 = 0、5 月 = 1、6 月 = 2 など
(私はこのようにして、年を直接指定せずに他の年にラップアラウンドできるようにしたので、C# メソッドのパラメーターの既定値を利用できました。)
私のコントローラーアクションは次のように宣言されています:
public ActionResult Index(string mode, int? locationID = 0, int monthOffset = 0)
monthOffset 引数は、選択された月を表すことになっています。デフォルト値が 0 であることに注意してください。これは、基本的に現在の月 + 0 を意味するはずです。ただし、HTML がレンダリングされると、実際の値が 0 の項目 (4 月) ではなく、選択されたリストの最初の項目 (1 月) が常に表示されます。1 月の値は -3 です。
SelectList オブジェクトで正しい月が選択されていることを確認しましたが、HTML でその選択がレンダリングされません。int 型が紛らわしい場合に備えて、 monthOffset 引数を文字列として設定しようとしましたが、効果はありませんでした。
MVC は値 0 を認識し、SelectList で実際に「0」が発生する場所に関係なく、これが常にリストの最初の項目を意味すると想定するのだろうか...?
これが実際の GET アクションです。関係ないことも多いと思います。主に注目すべきは MonthOffsetList 関数です。
public ActionResult Index(string mode, int? locationID = 0, int monthOffset = 0)
{
ViewBag.LocationID = new SelectList(db.MyLocations(WebSecurity.CurrentUserName, true), "ID", "Name", locationID);
// does not show current month on initial view
ViewBag.MonthOffset = MonthOffsetList(monthOffset);
if (mode == null || mode.Equals("m"))
{
DateTime viewDate = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1).AddMonths(monthOffset);
int year = viewDate.Year;
int month = viewDate.Month;
DateTimeFormatInfo dtf = new DateTimeFormatInfo();
ViewBag.ViewMonth = dtf.GetMonthName(month) + " " + year.ToString();
return View(new CalendarModel(year, month));
}
else
{
ViewBag.ViewMonth = "Next 30 Days from this week";
return View(new CalendarModel());
}
}
private SelectList MonthOffsetList(int selectedValue)
{
List<SelectListItem> results = new List<SelectListItem>();
int month = 0;
int year = DateTime.Today.Year;
DateTimeFormatInfo dtf = new DateTimeFormatInfo();
for (int offset = 1 - DateTime.Today.Month; offset < 13; offset++)
{
month++;
if (month > 12)
{
month = 1;
year++;
}
results.Add(new SelectListItem()
{
Value = offset.ToString(),
Text = (year == DateTime.Today.Year) ? dtf.GetMonthName(month) : dtf.GetMonthName(month) + " " + year.ToString()
});
}
return new SelectList(results, "Value", "Text", selectedValue);
}
ビューの関連部分は次のとおりです。
@using (Html.BeginForm())
{
<p class="center">
Location:
@Html.DropDownList("locationID", ViewBag.LocationID as SelectList, "(all)", new { onchange = "this.form.submit();" })
View:
@Html.RadioButton("mode", "m", Request["mode"].IsEmpty() || Request["mode"].Equals("m"), new { id = "view_m", onclick="this.form.submit();" })
@Html.Label("view_m", "Whole Month:")
<input type="submit" value="<<" onclick="this.form.MonthOffset.value--;" />
// does not render current month correctly initially
@Html.DropDownList("MonthOffset", ViewBag.MonthOffset as SelectList, new { onchange = "this.form.submit();" })
<input type="submit" value=">>" onclick="this.form.MonthOffset.value++;" />
@Html.RadioButton("mode", "w", !Request["mode"].IsEmpty() && Request["mode"].Equals("w"), new { id = "view_w", onclick="this.form.submit();" })
@Html.Label("view_w", "Continuous from this week")
</p>
}