使用TModel转换为IEnumerable <selectlistitem>的通用函数

时间:2017-02-01 21:25:23

标签: c# asp.net-mvc asp.net-mvc-5

我找到了this文章,展示了如何将List转换为IEnumerable。有人可以向我解释是否可以将其转换为可以被许多列表使用的通用函数?

例如,我有一个

public class City
{
    public int CityId { get; set; }
    public string CityName { get; set; }
}
public class State 
{
    public int StateId { get; set; }
    public string StateName { get; set; }
    public string StateAbbreviation { get; set; }
}

然后我有这两个列表,我想显示一个下拉列表:

List<City> cities
List<State> states

我可以设置两种不同的方法来做类似的事情,但是我必须将这些代码复制/粘贴到多个列表中,这不是我想要的。

public static IEnumerable<SelectListItem> GetCitiesSelectList()
{
    IEnumerable<SelectListItem> cityList = GetCities().Select(x => new SelectListItem() { Text = x.CityName, Value = x.CityId.ToString() });
    return qList;
}

我想知道的是,如果有类似的东西,但是能够传入任何类型的列表并传入列表的文本和值?我知道你可以用TModel做点什么,但我不完全理解它,希望有人能把我推向正确的方向。

5 个答案:

答案 0 :(得分:1)

这个怎么样:

var cities = new SelectList(cityList, "CityId", "CityName");
var states = new SelectList(cityList, "StateId", "StateAbbreviation");

SelectList可以加入IEnumerable<SelectListItem>

答案 1 :(得分:1)

您编写的任何通用方法都不会比使用Linq var cityList = cities.Select(c => new SelectListItem { Name = c.CityName, Value = c.CityId.ToString() }); 简单得多:

public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> input,
    Func<T, string> valueFunc,
    Func<T, string> nameFunc)
{
    return input.Select(i => new SelectListItem
    {
        Value = valueFunc(i),
        Name = nameFunc(i)
    });
}

但如果你真的想让它变得通用,你可以这样做:

var cityList = cities.ToSelectList(c => c.CityId.ToString(), c => c.CityName);

并像这样使用:

<!DOCTYPE html>
<html>

<head>
<title>Test</title>
<style>
    body {
        height: 80%;
        width: 90%;
        font-family: Arial;
        font-weight: Bold;
    }

    .dot {
        width: 20px;
        height: 20px;
        background-color: green;
        position: absolute;
        color: white;
        z-index: 1px;
        border-radius: 50%;
        animation: dots 2s linear;
    }

    @keyframes dots {
        0% {
            width: 20px;
            height: 20px;
            opacity: 1;
            bottom: 0px;
        }
        100% {
/*              opacity: 0; */
            width: 0px;
            height: 0px;
            bottom: 100px;
        }
    }
</style>
</head>

<body>

<script>
    window.setInterval(function() {
        randomSquare();
    }, 100);

    var i = 0;

    function randomSquare() {

        //Set window height
        var w = window.innerWidth;
        var h = window.innerHeight;


        //Set dot x-position
        var x = Math.floor((Math.random() * w) + 1);
        var y = Math.floor((Math.random() * h) + 1);

        // Add a dot to follow the cursor
        dot = document.createElement('div');
        dot.className = "dot";
        dot.style.left = x + "px";
        dot.style.bottom = 10 + "px";

        i++;

        //Random color
        var COLOURS = ['#69D2E7', '#A7DBD8', '#E0E4CC', '#F38630',     '#FA6900', '#FF4E50', '#F9D423'];
//          var color = "blue";
        var color = COLOURS[Math.floor(Math.random() * COLOURS.length)];

        dot.style.backgroundColor = color;

        if (y < h * 0.97 && x < w * 0.97) {
            document.body.appendChild(dot);
        }
    };
</script>

</body>

</html>

答案 2 :(得分:0)

始终如一地命名您的模型将是最简单的方法。假设您有像{ Id , Name}这样的下拉列表,并使用该常用模型进行下拉转换。 公共类DropDown     {

    public IEnumerable<int> SelectedItems
    {
        get;
        set;
    }


    public IEnumerable<SelectListItem> Items
    {
        get;
        set;
    }


    public IEnumerable<string> SelectedItemsString
    {
        get;
        set;
    }
}

无论你想要转换成多少列表项,下拉列表都会将列表传递给使用下拉实体进行转换的辅助方法,然后返回你期望的内容!!

IEnumerable<SelectListItem> dropdownItems = new MultiSelectList(YourEntity, "ID", "Name", selectedId);
            DropDown fboDropDown = new DropDown { Items = dropdownItems, SelectedItems = selectedId };

可用于下拉和多选列表

答案 3 :(得分:0)

创建基类SelectListItem

public class SelectListItem
{
    public virtual string Text { get; set; }
    public virtual string Value { get; set; }
}

public class City : SelectListItem
{
    public int CityId { get; set; }
    public string CityName { get; set; }
    public override string Text
    {
        get { return CityName; }
        set { CityName = value; }
    }
    public override string Value
    {
        get { return CityId.ToString(); }
        set { CityId = (int)value; }
    }
}
public class State : SelectListItem
{
    public int StateId { get; set; }
    public string StateName { get; set; }
    public string StateAbbreviation { get; set; }
    public override string Text
    {
        get { return StateName; }
        set { StateName = value; }
    }
    public override string Value
    {
        get { return StateId.ToString(); }
        set { StateId = (int)value; }
    }
}

答案 4 :(得分:0)

@ miguelerm的答案很可靠。但是,如果您对属性使用字符串常量感到不舒服,可以为此转换创建扩展方法:

public static class EnumerableExtensions
{
    public static IEnumerable<SelectListItem> ToSelectList<T>(
       this IEnumerable<T> collection,
       Func<T, object> textSelector,
       Func<T, object> valueSelector)
    {
        // null checking omitted for brevity
        foreach (var item in collection)
        {
            yield return new SelectListItem()
            {
                Text = textSelector(item) as string,
                Value = valueSelector(item) as string
            };
        }
    }
}

您可以在Razor中使用它,如下所示:

@Html.DropDownListFor(m => m.SelectedCity, Model.Cities.ToSelectList(c => c.CityName, city => c.CityId))