ASP.MVC 1.0 Checkbox值与ViewModel和特定ID

时间:2010-02-08 13:46:59

标签: asp.net-mvc checkbox checkboxlist

所有

我已经阅读了很多关于Checkboxes和ASP.MVC的帖子,但我并没有那么明智。

我的情景:

我有一个强类型视图,我将一组摘要对象传递给视图,以便在for-each中进行渲染。此摘要对象包含基于唯一ID的标签数据。我还在行中添加了一个复选框,所以请通过以下方式添加:

<td>
    <%= Html.CheckBox("markedItem", Model.MarkedItem, new { TrackedItemId = Model.Id })%>
</td>

当我执行POST以获取提交的结果时,我的action方法返回强类型的ViewModel,但是我没有填充用于创建列表的原始摘要对象。

好的,这很烦人,但我明白为什么所以我会忍受它。

我接下来要为我的ViewModel添加一个名为“MarkedItem”的新属性,这是一个字符串集合。

在回发时,如果复选框已更改,则此标记项目将填充之前和之后状态,但没有任何内容可以告诉我它们用于哪个键。只是为了澄清,如果我发送这个

  • TrackedItemId = A,Value = false
  • TrackedItemId = B,Value = true
  • TrackedItemId = C,Value = false

并将页面设置为:

  • TrackedItemId = A,Value = true
  • TrackedItemId = B,Value = true
  • TrackedItemId = C,Value = false

我会回来的:

  • MarkedItem [0] = true
  • MarkedItem [1] = false
  • MarkedItem [2] = true
  • MarkedItem [3] = false

换句话说,[0]是新值,[1]是旧值,[2]和[3]表示未更改的值。

我的问题是:

  1. 这是对的 - 我以这种方式前后得到了吗?有没有办法只发送最新的值?
  2. 如何获取我添加的自定义属性(TrackedItemId),以便我可以为返回的字符串数组添加含义?
  3. 到目前为止,我喜欢MVC,但它不处理像这样的简单的东西真的很混乱。我也是一个javascript noob,所以我真的希望这不是答案,因为我想在我的自定义视图模型中返回数据。

    请简单解释/建议:)

2 个答案:

答案 0 :(得分:0)

<p> 
<label> 
   Select project members:</label> 
<ul> 
    <% foreach (var user in this.Model.Users) 
       { %> 
    <li> 
        <%= this.Html.CheckBox("Member" + user.UserId, this.Model.Project.IsUserInMembers(user.UserId)) %><label 
            for="Member<%= user.UserId %>" class="inline"><%= user.Name%></label></li> 
    <% } %></ul> 

并在控制器中:

    // update project members        
foreach (var key in collection.Keys)     
{        
        if (key.ToString().StartsWith("Member")) 
        { 
                int userId = int.Parse(key.ToString().Replace("Member", ""));    
                if (collection[key.ToString()].Contains("true"))         
                        this.ProjectRepository.AddMemberToProject(id, userId); 
                else 
                        this.ProjectRepository.DeleteMemberFromProject(id, userId); 
        } 
} 

感谢Pino:)

答案 1 :(得分:0)

好吧,我已经想到了一个黑客 - 我真的很讨厌我必须这样做但是我没有看到另一种方式,我确信它会在某个时候突破。

我已经通过自己的ModelBinder实现了一些其他问题(例如类作为属性),所以扩展它以包含此代码。我们将Guid用于所有钥匙。

如果有以下任何替代方式,请告诉我。

HTML

<%= Html.CheckBox("markedItem" + Model.Id, false)%>

C#

(GuidLength是一个const int = 36,Left和Right是我们自己的字符串扩展名)

//Correct checkbox values - pull all the values back from the context that might be from a checkbox. If we can parse a Guid then we assume
//its a checkbox value and attempt to match up the model. This assumes the model will be expecting a dictionary to receive the key and 
//boolean value and deals with several sets of checkboxes in the same page

//TODO: Model Validation - I don't think validation will be fired by this. Need to reapply model validation after properties have been set?    
Dictionary<string, Dictionary<Guid, bool>> checkBoxItems = new Dictionary<string, Dictionary<Guid, bool>>();

foreach (var item in bindingContext.ValueProvider.Where(k => k.Key.Length > GuidLength))
{
    Regex guidRegEx = new Regex(@"^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$");
        if (guidRegEx.IsMatch(item.Key.Right(GuidLength)))
        {
            Guid entityKey = new Guid(item.Key.Right(GuidLength));
            string modelKey = item.Key.Left(item.Key.Length - GuidLength);

            Dictionary<Guid, bool> checkedValues = null;
            if (!checkBoxItems.TryGetValue(modelKey, out checkedValues))
            {
                checkedValues = new Dictionary<Guid, bool>();
                checkBoxItems.Add(modelKey, checkedValues);
            }
        //The assumption is that we will always get 1 or 2 values. 1 means the contents have not changed, 2 means the contents have changed
        //and, so far, the first position has always contained the latest value
            checkedValues.Add(entityKey, Convert.ToBoolean(((string[])item.Value.RawValue).First()));
        }
}

foreach (var item in checkBoxItems)
{
    PropertyInfo info = model.GetType().GetProperty(item.Key,
            BindingFlags.IgnoreCase |
            BindingFlags.Public |
            BindingFlags.Instance);

        info.SetValue(model, item.Value, null); 
}