Binding MVC CheckBoxList model to non-boolean
I want to bind a list box to a CheckBox and get the selected values. I need to display two such Checkbox tables and get both IDs.
Below is my ViewModel
public partial class ViewModel_Role_Security
{
public List<Roles> oRoleMaster { get; set; }
public List<Securities> oSecurityMaster { get; set; }
}
All three of these have these two values ββ1. ID 2. Name (in this case for the role identifier, RoleName | for securities - ID, SecurityName ...) // adding a third property of type bool is selected in order to work with eith flags and then you get it back these do not have a logical value
Using this ViewModel, I am binding these elements using the method below ...
public ActionResult AddingRoleSecurity()
{
ListRoles = new List<Roles>();
ListSecurities = new List<Securities>(); //And then populate them with data ...
var model = new ViewModel_Role_Security();
model.oRoleMaster = ListRoles;
model.oSecurityMaster = ListSecurities;
return View(model);
}
My corresponding cshtml file ...
@model KnackWFM.BusinessEntities.ViewModel_Role_Security
@using (Html.BeginForm())
{
<div class="contentsecurity">
<div class="User_role">
<p class="Security_role">User Role</p>
@for (int i = 0; i < Model.oRoleMaster.Count; i++)
{
<input id="@Model.oRoleMaster[i].RoleID" name="@Model.oRoleMaster[i].RoleName" type="checkbox" value="@(Model.oRoleMaster[i].RoleName)" />
<label for="@Model.oRoleMaster[i].RoleID">@Model.oRoleMaster[i].RoleName</label>
<br />
@Html.CheckBoxFor(Model.oRoleMaster[i].RoleID.selec)
}
</div>
<div class="User_Page">
<p class="Security_role">Role Security</p>
@for (int i = 0; i < Model.oSecurityMaster.Count; i++)
{
<input id="@Model.oSecurityMaster[i].SecurityID" name="@Model.oSecurityMaster[i].SecurityName" type="checkbox" value="@(Model.oSecurityMaster[i].SecurityName)" />
<label for="@Model.oSecurityMaster[i].SecurityID">@Model.oSecurityMaster[i].SecurityName</label>
<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>
}
For which I am getting the following output,
I would like to get the checked values ββas a model.
I have a HttpPost method like this, but it returns null values.
[HttpPost]
public ActionResult AddingRoleSecurity(ViewModel_Role_Security model)
{
return View();
}
Please let me know how do I get the checked values ββin the model?
Many thanks!
source to share
Just to state my comment above ...
For checkboxList - the viewmodel must include both an id property and a boolean selected property. If it doesn't already extend or create a new ViewModel class to fulfill this purpose - map the existing model to that specific ViewModel.
i.e. - Your model class (s)
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: Please note that besides checkboxes has Html.HiddenFor()
been enabled 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!
source to share
I would use https://www.nuget.org/packages/BeginCollectionItem/
This will help you get the correct binding sequence using the GUID
Best wishes Burim
source to share
you must add a third bool property for both of your models,
public bool IsSelected { get; set; }
and set it to its default value false and it will come back on post back when you check the corresponding checkbox and depending on the true values ββyou can do whatever you want with the corresponding selected values ββand texts.
here is my code i used somewhere to get the same thing:
<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 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 this is how I got 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);
}
}
source to share
I don't want to appear like I'm grateful to James for a great job, but a new answer is all I can do. For reasons I don't understand, my change to fix compilation errors in the code was rejected as not fixing critical issues. So I am posting this as a complete working answer.
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>
source to share