如何查找所有复选框的已检查状态

时间:2010-05-27 14:07:57

标签: c# asp.net-mvc

这是我的问题。我有一个显示给用户的模型列表。左侧是每个型号的复选框,表示用户想要选择此型号(在这种情况下,我们正在构建用户可以添加到购物车中的产品)。该模型没有被选择的概念......它严格地包含有关产品的信息。

我已经和其他一些开发人员谈过了,我能想到的最好的是获得formcollection和字符串解析键值来确定是否选中了复选框。这似乎并不理想。我当时认为会有更强烈的约束,但我无法找到办法。

我尝试创建另一个模型,该模型具有一个布尔属性来表示被检查和模型的属性,并将该模型类型的列表传递给视图,并在控制器上创建一个ActionResult,接受新模型的列表/检查属性,但它返回null。我只是想像Web表单一样,应该继续解析复选框值吗?

以下是我在集合中包装模型所做的工作:


public class SelectableCollection[T] : IList[T] {}
public class SelectableTrack{
  public bool IsChecked{get;set;}
  public bool CurrentTrack{get;set;}
}

对于视图,我继承自


ViewPage[SelectableCollection[SelectableTrack]]

对于控制器,我将其作为ActionResult:


[HttpPost]
        public ActionResult SelectTracks(SelectableCollection sc) {

            return new EmptyResult();
        }

但是当我在ActionResult内部进行分解时,该集合为null。有什么原因导致它没有通过?

3 个答案:

答案 0 :(得分:1)

这是ViewModel有用的情况。您需要能够表示“选定”项目,这些项目不属于您的模型,但您可以将其添加到ViewModel。 ViewModels旨在为视图提供所有所需的信息,包括一些可能不属于模型的信息。

这是一个想法:是否可以将您的项目“包装”在一个表示选择的集合中?我正在考虑SelectableCollection<T>之类的东西(这可能来自ICollection<T>或其他一些通用集合类型。)您可以将其添加到ViewModel并将复选框绑定到它们。

答案 1 :(得分:1)

在你的情况下,我会添加一个ViewModel,它扩展你的模型,其概念是“被选中”。这将允许您使用MVC的模型绑定技术来避免在表单集合中进行挖掘。

在我发现AutoMapper之前,我非常不愿意加入ViewModel。现在我已经拥有了AutoMapper,我可以根据自己的应用需求制作尽可能多的ViewModel,并且可以轻松地将我的ViewModel映射回我的(DTO)模型以实现持久性。

另外,WRT ASP.NET MVC复选框,你应该熟悉如何处理Checkboxs的一些怪癖。有关其他详细信息,请参阅this question

我个人使用此方法从我的模型绑定器中的bindingContext获取bool值,其中正在使用复选框:

    public static bool? GetBool(ModelBindingContext bindingContext, string key)
    {
        var str = GetStr(bindingContext, key);
        bool tmp;

        if (string.IsNullOrEmpty(str))
            return null;

        str = str.ToLower().Trim();

        if (bool.TryParse(str, out tmp))
            return tmp;

        if (string.Compare(str, "no") == 0)
            return false;

        if (string.Compare(str, "yes") == 0)
            return true;

        if (string.Compare(str, "true,false") == 0)
            return true;

        return null;
    }
    public static string GetStr(ModelBindingContext bindingContext, string key)
    {
        if (string.IsNullOrEmpty(key))
            return null;

        var valueResult = bindingContext
            .ValueProvider
            .GetValue(bindingContext.ModelName + "." + key);

        if (valueResult == null && bindingContext.FallbackToEmptyPrefix)
            valueResult = bindingContext.ValueProvider.GetValue(key);

        return valueResult != null ? valueResult.AttemptedValue : null;
    }

答案 2 :(得分:0)

由于<%= Html.CheckBox() %>为每个复选框呈现<input name="yourName" type="hidden" value="false" />以跟踪未选中的复选框,因此我使用以下解决方案:

控制器

public ActionResult MyAction([Bind(Prefix = "CheckBox")] Dictionary<int, bool> myCheckBoxes)
{
}

视图模型

public List<CheckBox> MyCheckBoxes{ get; private set; }

MyCheckBoxes = modelRepository.GetMyCheckBoxes(userID);

存储库

public List<CheckBox> GetMyCheckBoxes(userID)
{        
    IDictionary<int, bool> selectedModels = new Dictionary<int, bool>();
    ModelRespository modelRespository = new ModelRespository();

    foreach (var model in modelRespository.GetUserSelectedModels(userID))
    {
        selectedModels.Add(model.ModelID);
    }

    return (from m in modelRespository.GetModels()
        select new CheckBox
        {
            ID = m.ModelID.ToString(),
            Text = m.Name,
            Checked = selectedModels.ContainsKey(m.ID)
        }).ToList();
}

查看

<% int i = 0; foreach (CheckBox c in Model.MyCheckBoxes)
   { %>
<p>
    <%= Html.Hidden(String.Format("CheckBox[{0}].Key", i), yourModelID)%>
    <%= Html.CheckBox(String.Format("CheckBox[{0}].Value", i), c.Checked)%>        
</p>
<% i++; } %>