Создать собственное расширение HTML, которое будет работать как ListBoxFor, но вместо этого выводить флажки? - PullRequest
1 голос
/ 03 января 2012

Я пытаюсь создать (или даже лучше найти) собственный метод расширения html, который работает в поместье, аналогичном ListBoxFor, но отображает группу флажков вместо нескольких выбранных.

Что лучшеспособ идти об этом?Мне любопытно, как работает метод ListBoxFor, когда ему передают только выражение и перечислимые элементы SelectListItems, в которых выбраны только элементы по умолчанию.Не передается модель, так как он узнает, когда выбирать правильные предметы (как-то кажется, что способен это сделать)?Кроме того, как он пишет атрибуты HTML на основе анонимного объекта?

1 Ответ

2 голосов
/ 03 января 2012

Вы не предоставили никаких подробностей и конкретного примера того, чего вы пытаетесь достичь.Вы не предоставили исходный код, который пытались решить, чтобы решить возникшую проблему.В следующий раз, когда вы зададите вопрос о StackOverflow, сделайте это, чтобы сделать ваш вопрос более значимым и сфокусированным на конкретной проблеме.

В любом случае, вот пример.Предположим, что вы определили модель представления:

public class MyViewModel
{
    public IEnumerable<string> SelectedValues { get; set; }
    public IEnumerable<SelectListItem> Values { get; set; }
}

и контроллер, который заполнит эту модель представления значениями и, надеюсь, в действии POST получит выбранные значения в представлении:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var model = new MyViewModel
        {
            SelectedValues = new[] { "1", "3" },
            Values = new[]
            {
                new SelectListItem { Value = "1", Text = "item 1" },
                new SelectListItem { Value = "2", Text = "item 2" },
                new SelectListItem { Value = "3", Text = "item 3" },
            }
        };
        return View(model);
    }

    [HttpPost]
    public ActionResult Index(MyViewModel model)
    {
        // model.SelectedValues will contain the ids of items that were checked
        // in the checkbox list
    }
}

и затем просмотр:

@model MyViewModel

@using (Html.BeginForm())
{
    @Html.CheckBoxListFor(x => x.SelectedValues, Model.Values, null)
    <button type="submit">OK</button>
}

ОК, пока все хорошо.Последняя часть - попытаться реализовать этот помощник CheckBoxListFor.Очевидно, что в зависимости от ваших конкретных требований и контекста может быть много возможных способов сделать это (см. Мое замечание в начале ответа).Итак, вот лишь несколько примеров реализации, которые могут помочь вам начать:

public static class HtmlExtnsions
{
    public static IHtmlString CheckBoxListFor<TModel, TProperty>(
        this HtmlHelper<TModel> htmlHelper, 
        Expression<Func<TModel, TProperty>> expression, 
        IEnumerable<SelectListItem> selectList,
        object htmlAttributes
    )
    {
        var name = ExpressionHelper.GetExpressionText(expression);
        string fullHtmlFieldName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
        var values = GetModelStateValue(htmlHelper.ViewData, fullHtmlFieldName, typeof(string[]));
        if (values == null)
        {
            values = htmlHelper.ViewData.Eval(fullHtmlFieldName);
        }

        if (values != null)
        {
            var collection =
                from object value in values as IEnumerable
                select Convert.ToString(value, CultureInfo.CurrentCulture);
            var hashSet = new HashSet<string>(collection, StringComparer.OrdinalIgnoreCase);
            var list = new List<SelectListItem>();
            foreach (var item in selectList)
            {
                item.Selected = ((item.Value != null) ? hashSet.Contains(item.Value) : hashSet.Contains(item.Text));
                list.Add(item);
            }
            selectList = list;
        }

        var sb = new StringBuilder();
        foreach (var item in selectList)
        {
            var checkbox = new TagBuilder("input");
            checkbox.Attributes["type"] = "checkbox";
            checkbox.Attributes["name"] = fullHtmlFieldName;
            checkbox.Attributes["value"] = item.Value;
            checkbox.GenerateId(fullHtmlFieldName);
            if (item.Selected)
            {
                checkbox.Attributes["checked"] = "checked";
            }
            sb.Append(checkbox.ToString(TagRenderMode.SelfClosing));
            sb.Append(item.Value);
        }

        return new HtmlString(sb.ToString());
    }

    private static object GetModelStateValue(ViewDataDictionary viewData, string key, Type destinationType)
    {
        ModelState modelState;
        if (viewData.ModelState.TryGetValue(key, out modelState) && modelState.Value != null)
        {
            return modelState.Value.ConvertTo(destinationType, null);
        }
        return null;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...