0

我想创建一个通用的复选框列表视图模型,所以我得到了这个:

public class ChckboxListViewModel<T>
{
    public List<CheckboxViewModel<T>> CheckboxList { get; set; }
    public IEnumerable<T> SelectedValues
    {
        get { return CheckboxList.Where(c => c.IsSelected).Select(c => c.Value); }
    }

    public ChckboxListViewModel()
    {
        CheckboxList = new List<CheckboxViewModel<T>>();
    }
}

public class CheckboxViewModel<T>
{
    public string Label { get; set; }
    public T Value { get; set; }
    public bool IsSelected { get; set; }

    public CheckboxViewModel(string i_Label, T i_Value, bool i_IsSelected)
    {
        Label = i_Label;
        Value = i_Value;
        IsSelected = i_IsSelected;
    }
}

不同的视图模型使用它来表示不同状态的过滤器:

public class FaultListFilters
{
    public string SearchKeyword { get; set; }
    public ChckboxListViewModel<Fault.eFaultStatus> StatusFilter { get; set; }

    public FaultListFilters()
    {
        SearchKeyword = null;
        StatusFilter = new ChckboxListViewModel<Fault.eFaultStatus>();

        StatusFilter.CheckboxList.Add(new CheckboxViewModel<Fault.eFaultStatus>(FaultManagementStrings.OpenStatus,Fault.eFaultStatus.Open,true));
        StatusFilter.CheckboxList.Add(new CheckboxViewModel<Fault.eFaultStatus>(FaultManagementStrings.InProgressStatus, Fault.eFaultStatus.InProgress, true));
        StatusFilter.CheckboxList.Add(new CheckboxViewModel<Fault.eFaultStatus>(FaultManagementStrings.ClosedStatus, Fault.eFaultStatus.Close, false));

    }
}

现在我找不到显示编辑器或为这种视图模型创建编辑器模板的正确方法,因为它是通用的。

我不想为然后创建一个单独的编辑器模板ChckboxListViewModel<int>,然后再为ChckboxListViewModel<Fault.eFaultStatus>等等..

在这种情况下使用泛型甚至是一个鹅的想法吗?

在 MVC 中是否有另一种表示和显示复选框列表的方法?

我已经完成了以下操作,但由于某种原因,该模型没有绑定:

@using (Html.BeginForm("FaultManagement", "Faults", FormMethod.Get, null))
{

    for (int i=0 ; i<Model.FaultListFilters.StatusFilter.CheckboxList.Count() ; i++)
    {
        @Html.HiddenFor(m => m.FaultListFilters.StatusFilter.CheckboxList[i].Value)
        @Html.CheckBoxFor(m => m.FaultListFilters.StatusFilter.CheckboxList[i].IsSelected)
        @Html.LabelFor(m=> m.FaultListFilters.StatusFilter.CheckboxList[i].IsSelected,Model.FaultListFilters.StatusFilter.CheckboxList[i].Label)
    }

    <input type="submit" />
}
4

2 回答 2

2

在这种情况下使用泛型甚至是一个鹅的想法吗?

不要认为它是。

在 MVC 中是否有另一种表示和显示复选框列表的方法?

我会编写一个自定义 HTML 助手:

public static class HtmlExtensions
{
    public static IHtmlString CheckboxListFor<TModel>(
        this HtmlHelper<TModel> html, 
        Expression<Func<TModel, IEnumerable<string>>> ex, 
        IEnumerable<string> possibleValues)
    {
        var metadata = ModelMetadata.FromLambdaExpression(ex, html.ViewData);
        var availableValues = (IEnumerable<string>)metadata.Model;
        var name = ExpressionHelper.GetExpressionText(ex);
        return html.CheckboxList(name, availableValues, possibleValues);
    }

    private static IHtmlString CheckboxList(this HtmlHelper html, string name, IEnumerable<string> selectedValues, IEnumerable<string> possibleValues)
    {
        var result = new StringBuilder();

        foreach (string current in possibleValues)
        {
            var label = new TagBuilder("label");
            var sb = new StringBuilder();

            var checkbox = new TagBuilder("input");
            checkbox.Attributes["type"] = "checkbox";
            checkbox.Attributes["name"] = name;
            checkbox.Attributes["value"] = current;
            var isChecked = selectedValues.Contains(current);
            if (isChecked)
            {
                checkbox.Attributes["checked"] = "checked";
            }

            sb.Append(checkbox.ToString());
            sb.Append(current);

            label.InnerHtml = sb.ToString();
            result.Append(label);
        }
        return new HtmlString(result.ToString());
    }
}

然后你可以有一个视图模型:

public class FaultListFiltersViewModel
{
    public IEnumerable<string> SelectedStatusFilters { get; set; }
    public IEnumerable<string> AvailableStatusFilters
    {
        get
        {
            return new[] { "Label 1", "Label 2", "Label 3" }
        }
    }
}

在视图内部,您可以使用帮助器:

@Html.CheckBoxListFor(x => x.SelectedStatusFilters, Model.AvailableStatusFilters)
于 2013-03-30T09:22:57.877 回答
0

这是另一个实现,它将更好地支持引导按钮组标签(因为它需要将它们分开)和枚举类型选择值。

    public static IHtmlString CheckboxListFor<TModel, TKey>(this HtmlHelper<TModel> helper, Expression<Func<TModel, IEnumerable<TKey>>> ex, Dictionary<TKey, string> i_PossibleOptions, object i_LabelHtmlAttributes)
        where TKey : struct, IConvertible
    {
        var metadata = ModelMetadata.FromLambdaExpression(ex, helper.ViewData);
        var selectedValues = (IEnumerable<TKey>)metadata.Model;
        var name = ExpressionHelper.GetExpressionText(ex);
        return helper.CheckboxList(name, selectedValues, i_PossibleOptions, i_LabelHtmlAttributes);
    }

    private static IHtmlString CheckboxList<TKey>(this HtmlHelper helper, string name, IEnumerable<TKey> i_SelectedValues, Dictionary<TKey, string> i_PossibleOptions, object i_LabelHtmlAttributes)
        where TKey : struct, IConvertible
    {
        if (!typeof(TKey).IsEnum) throw new ArgumentException("T must be an enumerated type");

        var result = new StringBuilder();

        foreach (var option in i_PossibleOptions)
        {
            var label = new TagBuilder("label");
            label.MergeAttributes(new RouteValueDictionary(i_LabelHtmlAttributes));
            label.Attributes["for"] = string.Format("{0}",option.Key.ToString());
            label.InnerHtml = option.Value;

            var checkbox = new TagBuilder("input");
            checkbox.Attributes["type"] = "checkbox";
            checkbox.Attributes["name"] = name;
            checkbox.Attributes["id"] = string.Format("{0}", option.Key.ToString());
            checkbox.Attributes["value"] = option.Key.ToString();

            bool isChecked = ((i_SelectedValues != null) && (i_SelectedValues.Contains(option.Key)));
            if ( isChecked )
            {
                checkbox.Attributes["checked"] = "checked";
            }

            result.Append(checkbox);
            result.Append(label);
        }
        return new HtmlString(result.ToString());
    }

然后视图模型看起来像这样:

public class FaultListFilters
{
    [Display(ResourceType = typeof(FaultManagementStrings), Name = "SearchKeyword")]
    public string SearchKeyword { get; set; }
    public Dictionary<Fault.eFaultStatus, string> PossibleFaultStatuses 
    {
        get 
        {
            var possibleFaultStatuses = new Dictionary<Fault.eFaultStatus, string>();
            possibleFaultStatuses.Add(Fault.eFaultStatus.Open, FaultManagementStrings.OpenStatus);
            possibleFaultStatuses.Add(Fault.eFaultStatus.InProgress, FaultManagementStrings.InProgressStatus);
            possibleFaultStatuses.Add(Fault.eFaultStatus.Close, FaultManagementStrings.ClosedStatus);
            return possibleFaultStatuses;
        }
    }
    public IEnumerable<Fault.eFaultStatus> SelectedFaultStatuses { get; set; }

    public FaultListFilters()
    {
        SearchKeyword = null;
        SelectedFaultStatuses = new[] { Fault.eFaultStatus.Open, Fault.eFaultStatus.InProgress };
    }
}

并且用法保持不变(除了我添加了标签html属性)

    <div class="btn-group">
    @Html.CheckboxListFor(m => m.FaultListFilters.SelectedFaultStatuses, Model.FaultListFilters.PossibleFaultStatuses, new { Class="btn"})
</div>
于 2013-03-30T12:45:01.243 回答