I want to bind a List to CheckBox and get the selected values. I need to display two such Checkbox tables and have to retrieve both the IDs.
Below is my ViewModel
you should add a third bool property to both of your models,
public bool IsSelected { get; set; }
and set it defaulted to false, and will get it true on posting back when you check the corresponding check box, and depending upon true values you can do what ever you want with corresponding selected values and texts as well
here is my code which i have used some where to acheive the same:
<td colspan="4" style="-webkit-column-count: 3; -moz-column-count:3; -ms-column-count:3; -o-column-count: 3; column-count: 3">
@{int i = 0;
}
@foreach (var item in Model.SurfaceTypeList)
{
<input name="SurfaceTypeList[@i].Text" type="hidden" value="@item.Text" />
<input name="SurfaceTypeList[@i].Value" type="hidden" value="@item.Value" />
<input data-val="true" id="SurfaceTypeList_@(i)__IsSelected" name="SurfaceTypeList[@i].IsSelected" type="checkbox" class="SurfaceType" value="true" checked="@item.IsSelected" />
@Html.Label(item.Text)
<br /><br />
i++;
}
</td>
<td colspan="2"></td>
model contains a property:
public List<SurfaceType> SurfaceTypeList { get; set; }
public class SurfaceType
{
public bool IsSelected { get; set; }
public string Text { get; set; }
public string Value { get; set; }
}
and here is how i retrieved the text/values:
foreach (var item in modelData.SurfaceTypeList)
{
if (item.IsSelected)
{
var surfaceType = new XElement("SurfaceType");
var id = new XElement("Id");
id.Add(item.Value);
surfaceType.Add(id);
var i = id.Value;
surfaceTypeList.Add(surfaceType);
}
}
Just to flesh out my comment above...
For a checkboxList - the viewmodel should include both an identifier property, and boolean selected property. If it doesn't already then either extend or create a new ViewModel class to fulfil this purpose - map your existing model to this specific viewmodel.
i.e. - Your Model Class(es)
public class UserRole
{
public int RoleID {get; set;}
public string RoleName {get; set;}
public bool Selected {get; set;}
}
public class UserSecurity
{
public int SecurityID {get; set;}
public string SecurityName {get; set;}
public bool Selected {get; set;}
}
public class UserRoleAndSecurityModel
{
public List<UserRole> RoleMaster {get; set;}
public List<UserSecurity> SecurityMaster {get; set;}
}
Your View:
Note that in addition to the checkboxes Html.HiddenFor()
has been included for each of the UserRole/UserSecurity ID properties, which allows MVC to bind the ID properties after postback.
@model UserRoleAndSecurityModel
@using (Html.BeginForm())
{
<div class="contentsecurity">
<div class="User_role">
<p class="Security_role">User Role</p>
@for (int i = 0; i < Model.RoleMaster.Count; i++)
{
@Html.CheckBoxFor(m => m.RoleMaster[i].Selected)
@Html.HiddenFor(m => m.RoleMaster[i].RoleId)
@Html.LabelFor(m => m.RoleMaster[i].Selected,
Model.RoleMaster[i].RoleName)
<br />
}
</div>
<div class="User_Page">
<p class="Security_role">Role Security</p>
@for (int i = 0; i < Model.SecurityMaster.Count; i++)
{
@Html.CheckBoxFor(m => m.SecurityMaster[i].Selected)
@Html.HiddenFor(m => m.SecurityMaster[i].SecurityId)
@Html.LabelFor(m => m.SecurityMaster[i].Selected,
Model.SecurityMaster[i].SecurityName)
<br />
}
</div>
<div class="bottombuttonsecurity">
<button type="submit" id="btnSave" name="Command" value="Save" style="background-color: #3d3c4c;border-radius: 8px;color: white;padding: 5px;border: 1px solid #3d3c4c;">Save</button>
</div>
</div>
and your controller should now use the new model above too!
I don't want to appear like I'm taking credit for James excellent work, but a new answer is all I can do. For reasons I do not understand, my edit that corrected compile errors in the code were rejected as not correcting critical issues. So I post this as a complete working answer.
The Models:
public class UserRole
{
public int RoleID {get; set;}
public string RoleName {get; set;}
public bool Selected {get; set;}
}
public class UserSecurity
{
public int SecurityID {get; set;}
public string SecurityName {get; set;}
public bool Selected {get; set;}
}
public class UserRoleAndSecurityModel
{
public List<UserRole> RoleMaster {get; set;}
public List<UserSecurity> SecurityMaster {get; set;}
}
And the view:
@model UserRoleAndSecurityModel
@using (Html.BeginForm())
{
<div class="contentsecurity">
<div class="User_role">
<p class="Security_role">User Role</p>
@for (int i = 0; i < Model.RoleMaster.Count; i++)
{
@Html.CheckBoxFor(m => m.RoleMaster[i].Selected)
@Html.HiddenFor(m => m.RoleMaster[i].RoleId)
@Html.LabelFor(m => m.RoleMaster[i].Selected,
Model.RoleMaster[i].RoleName)
<br />
}
</div>
<div class="User_Page">
<p class="Security_role">Role Security</p>
@for (int i = 0; i < Model.SecurityMaster.Count; i++)
{
@Html.CheckBoxFor(m => m.SecurityMaster[i].Selected)
@Html.HiddenFor(m => m.SecurityMaster[i].SecurityId)
@Html.LabelFor(m => m.SecurityMaster[i].Selected,
Model.SecurityMaster[i].SecurityName)
<br />
}
</div>
<div class="bottombuttonsecurity">
<button type="submit" id="btnSave" name="Command" value="Save" style="background-color: #3d3c4c;border-radius: 8px;color: white;padding: 5px;border: 1px solid #3d3c4c;">Save</button>
</div>
</div>
I would use https://www.nuget.org/packages/BeginCollectionItem/
This will help you get the right sequence in binding using GUID
Best Regard Burim