如何在ViewModel上创建可变长度下拉列表而不重复c#中的代码?

时间:2017-07-05 23:49:29

标签: c# arrays list viewmodel dropdownlistfor

我是新手开发人员,我需要填充一个包含日期的下拉列表,以便网站访问者可以选择这些日期以检索某些数据。

这个名单很不寻常,因为它必须从上个月到一年前倒退。因此,上个月将是列表中的第一个条目,并且每个月都会跟随。例如,如果今天是2017年7月5日,则下拉列表将如下所示:

return "Blog %s published on %s" %(self.title, self.pub_date)

每个月的列表都会变长,所以我无法将固定长度编码到列表中。我提出了以下代码,但它不会构建:

Jun 2017
May 2017
Apr 2017
Mar 2017
Feb 2017
Jan 2017
Dec 2016
and so on . . .

我在“item”变量上遇到了几个构建错误,我不知道如何修复它们:

1 - 错误的数组声明符:要声明一个托管数组,等级说明符在变量的标识符之前。要声明固定大小的缓冲区字段,请在字段类型之前使用fixed关键字。数组大小不能在变量声明中指定(尝试使用' new'表达式初始化)

2 - 在这个范围内已经定义了一个名为'item'的局部变量(我知道我需要摆脱dup,但这只是我整体逻辑问题的一个症状)。

3 - 无法将带有[]的索引应用于SelectListItem类型的表达式

显然,c#并不喜欢我尝试在列表项上使用索引,例如" item [y]"。我以为我很聪明,但这种做法完全是炸弹。

我搜索了这个网站以及互联网并阅读了我找到的所有示例,但找不到符合我需求的解决方案。任何人都可以就如何解决这个逻辑提供一些指导吗?

我相信我已经彻底解释了这个问题,但如果我缺乏准确性或清晰度,请提前接受我的道歉。我很乐意回应有关更多信息的请求。

[RequireLogin]
public ActionResult Index()
{
    bool firstItem = true;
    int x = -1;
    int y = 1;
    int daysFromStartDate = beginDate.Date.Subtract(currentDate).Days;
    List<SelectListItem> items = new List<SelectListItem>();

    while (daysFromStartDate >= 30)
    {
        DateTime previousMonth = DateTime.Now.Date.AddMonths(x);
        string pMonth = previousMonth.ToString("MMM");
        string pYear = previousMonth.ToString("YYYY");
        Int32.TryParse(pMonth, out thisMonth);
        Int32.TryParse(pYear, out thisYear);
        if (firstItem)
            firstItem = false;
            SelectListItem item[y] = new SelectListItem() { Text = pMonth + " " + pYear, Value = pMonth, Selected = true };  //<- #1
        else
            SelectListItem item[y]= new SelectListItem() { Text = pMonth + " " + pYear, Value = pMonth, Selected = false };  //<- #2
        items.Add(item[y]);                                                                                                  //<- #3
        x = x--;
        y = y++;
    }
    ViewBag.MonthList = items;
    return View();
}

这是一个粘性的(无论如何对我来说)。然而,Vlad Stryapko让我走上了正确的轨道,并且通过一些微调,我得到了他的解决方案(我接受了)。还有另一个问题,但与我原来的帖子无关,所以我会为此发布一个单独的问题。这是我的最终代码:

我的ViewModel

                      *******QUESTION EDIT***********

我的Html视图

        public SelectList MonthList { get; set; }


        public SelectList ReverseMonthsLists()
        {
            var stringViewOfDates = GetDates().Select(_ => _.ToString("MMM yyyy")).ToList();

            var list = new List<SelectListItem>();
            list.Add(new SelectListItem { Selected = true, Text = stringViewOfDates[0], Value = stringViewOfDates[0] });

            for (int i = 1; i < stringViewOfDates.Count(); i++)
            {
                list.Add(new SelectListItem { Selected = false, Text = stringViewOfDates[i], Value = stringViewOfDates[i] });
            }
            var selectList = new SelectList(list);
            return selectList;
        }


        public static IEnumerable<DateTime> GetDates()
        {
            DateTime startDate = new DateTime(2017, 6, 1).Date;
            var currentDate = DateTime.Now.Date;

            int numberOfMonthsToShow = (currentDate.Year - startDate.Year) * 12 + currentDate.Month - startDate.Month;
            if (numberOfMonthsToShow == 0)
                numberOfMonthsToShow = 1;

            var dates = new List<DateTime>(numberOfMonthsToShow);
            for (int i = 0; i < numberOfMonthsToShow; i++)
            {
                dates.Add(currentDate);
                currentDate = currentDate.AddMonths(-1);
            }
            return dates;
        }

代码现在编译,但我得到的是&#34; System.Web.Mvc.SelectListItem&#34;在我的下拉列表中。我会在另一个帖子中提出这个问题,因为我不相信我可以在这里提出第二个问题。

5 个答案:

答案 0 :(得分:1)

给出一个通用函数来获取日期列表: -

public static IEnumerable<string> ReverseMonthList(string format, DateTime start, int count)
    {
        return Enumerable.Range(0, count).Select(n => start.AddMonths(-(n + 1)).ToString(format));
    }

然后

var from = new DateTime(2016, 7, 5);
var now = new DateTime(2017, 7, 5);
var monthsSinceStart = ((now.Year - @from.Year) * 12) + now.Month - @from.Month;
var dates = ReverseMonthList("MMM yyyy", now, monthsSinceStart);

给出

enter image description here

答案 1 :(得分:1)

使用LINQ并向后退:

var ans = Enumerable.Range(1, 12).Select(p => start.AddMonths(-p).ToString("MMM yy")).ToList();

答案 2 :(得分:0)

我还没有得到你需要的东西,这里有一个如何建立一个从当前日期开始并包含12个月的日期列表的例子。

public static IEnumerable<DateTime> GetDates()
{
    var currentDate = DateTime.Now;
    var numberOfMonthsToShow = 12;
    var dates = new List<DateTime>(numberOfMonthsToShow);
    for (int i = 0; i < numberOfMonthsToShow; i++)
    {
        dates.Add(currentDate);
        currentDate = currentDate.AddMonths(-1);
    }
    return dates;
}

如果您想从上个月开始,请将currentDate初始化为DateTime.Now.AddMonths(-1)

接下来,您必须构建这些日期的字符串表示形式。对于您的格式,请使用Y格式选择器。

 var stringViewOfDates = GetDates().Select(_ => _.ToString("MMM yyyy"));

现在你有了你的字符串,你可以将它们添加到SelectList。我现在没有ASP.NET MVC,但它应该是非常简单的。类似的东西:

var list = new List<SelectListItem>();
list.Add(new SelectListItem { Selected = true, Text = stringViewOfDates[0], Value = stringViewOfDates[0]})

for (int i = 1; i < stringView.Count(); i++)
{
  list.Add(new SelectListItem { Selected = false, Text = stringViewOfDates[i], Value = stringViewOfDates[i]);
}

var selectList = new SelectList(list);

你有很多代码对于以前几个月的任务来说似乎是多余的。请尝试我提供的那个或解释为什么你需要这么复杂的代码。我可能会错过你的一些逻辑。

答案 3 :(得分:0)

  

这个列表很不寻常,因为它必须从上个月到一年前填充。

这很容易做到。首先 - 生成日期。您有开始日期(上个月)和所需的总月数(12)。然后将每个日期投影到SelectListItem

var today = DateTime.Today;
var startOfMonth = new DateTime(today.Year, today.Month, 1);

var items = from i in Enumerable.Range(1, 12)
            let date = startOfMonth.AddMonths(-i)
            select new SelectListItem { 
                Text = date.ToString("MMM yyyy"), 
                Value = date.ToString("MMM"), 
                Selected = i == 1
            };

ViewBag.MonthList = items.ToList();

注意:

  1. 您应该计算相对于当月开始的日期。否则,您可能会遇到2月29日的问题。
  2. 使用字符串格式以您想要的格式生成日期。不要格式化部分日期并将它们连接起来。
  3. 年份格式字符串为小写yyyy
  4. SelectListItem item[y] = ...语法不正确。这是任务和声明的混合。如果要在列表中指定项目,则应按索引item[y] = ...引用该项目。但是,如果列表包含足够的项目,您应该检查。实际上你真正需要做的是在列表中添加一个项目,这是通过items.Add(...)实现的。
  5. 考虑学习LINQ - 它允许您编写查询(以声明方式)以轻松过滤,投影等数据

答案 4 :(得分:0)

这是一个控制台应用

   var startDate = DateTime.Now.Date;

    var days = new List<Tuple<string, string>>();

    int totalMonths = 12;

    for (int i = 1; i < totalMonths; i++)
    {
        var tempDay = startDate.AddMonths(-i);
        days.Add(new Tuple<string, string>($"{tempDay.ToString("MMM")} {tempDay.ToString("yyyy")}", tempDay.ToString("MMM")));
    }

    foreach (var d in days)
    {
        Console.WriteLine(d.Item1);
    }

输出 2017年6月 2017年5月 2017年4月 2017年3月 2017年2月 2017年1月 2016年12月 2016年11月 2016年10月 2016年9月 2016年8月

出于测试目的,我使用了元组。使用listitem类。对于项目选择,使用单独的循环或在生成方法中使用 if 条件。