#Html.DropDownList not showing selected value - c#

I am trying to create one partial view to create drop down on every view. Have created one view model and partial view for the same. Its creating drop down properly but not showing selected value.
Below is View Model Class
public class drowDownVM
{
public string id { get; set; }
public string name { get; set; }
public string cssClass { get; set; }
public string keyColumnName { get; set; }
public string valueColumnName { get; set; }
public string selectedValue { get; set; }
public string viewbagName { get; set; }
public bool isMultipleSelect { get; set; }
public List<int> multipleselectedValue { get; set; }
}
Below is partial view to bind drop down
#if (Model != null)
{
if (ViewData != null && ViewData.Count > 0 && ViewData.Keys.Contains(Model.viewbagName))
{
string ddName = !(string.IsNullOrEmpty(Model.name)) ? Model.name : "default-name";
string viewBagName = !(string.IsNullOrEmpty(Model.viewbagName)) ? Model.viewbagName : ViewData.Keys.First();
string keyColumnName = !(string.IsNullOrEmpty(Model.keyColumnName)) ? Model.keyColumnName : "id";
string valueColumnName = !(string.IsNullOrEmpty(Model.valueColumnName)) ? Model.valueColumnName : "id";
string selectedVal = !(string.IsNullOrEmpty(Model.selectedValue)) ? Model.selectedValue : "";
List<int> multipleSelectVal = (Model.multipleselectedValue != null && Model.multipleselectedValue.Count > 0) ? Model.multipleselectedValue : new List<int>();
var cssClass = !(string.IsNullOrEmpty(Model.cssClass)) ? Model.cssClass : "";
if (!Model.isMultipleSelect)
{
<div>
#Html.DropDownList(ddName, new SelectList((System.Collections.IEnumerable)ViewData[viewBagName], keyColumnName, valueColumnName, 2), "--Select--", new { #class = cssClass, #data_Val = selectedVal })
</div>
}
else
{
#Html.ListBox(ddName, new MultiSelectList((System.Collections.IEnumerable)ViewData[viewBagName], keyColumnName, valueColumnName, multipleSelectVal), new { #class = cssClass, #multiple = "multiple"})
}
}
}
else
{
<p class="hidden">Model Data Not Found!</p>
}
Below is the code which calls partial view to bind drop down, first one is single select, second one is calling multiple select.
#Html.Partial("_dropdown", new drowDownVM() { cssClass = "form-control", id = "TargetTypeList", keyColumnName = "code_val", name = "TargetTypeList", selectedValue = "1", valueColumnName = "code_name", viewbagName = "TargetTypeList"})
#Html.Partial("_dropdown", new drowDownVM() { cssClass = "form-control", id = "TargetTypeList", isMultipleSelect = true, keyColumnName = "code_val", name = "TargetTypeList", selectedValue = "1", valueColumnName = "code_name", viewbagName = "TargetTypeList", multipleselectedValue = new List<int>() { 1, 2 } })

<div>
#Html.DropDownList(ddName, new SelectList((System.Collections.IEnumerable)ViewData[#ViewBag.ViewBagName], keyColumnName, valueColumnName, 2), "--Select--", new { #class = cssClass, #data_Val = selectedVal })
</div>

Related

How to Display different controls (CheckBox, RadioButton or TextBox) based on returned parameter in ASP.NET Razor View and Save response

I am building a CRUD application (Multiple Choice answers for a form), the response to each question can be list of checkboxes, radio buttons, textboxes or mixture of 2 controls. Please How do I display the CheckBox in the Razor View and How do I display 2 types of Controls side by side and Save user response?
Here is my Model:
public class Question
{
public long Id { get; set; }
public string Title { get; set; }
public string Details { get; set; }
public bool HasMultiAnswers { get; set; }
public int NumberOfAnswers { get; set; }
public double TotalPoint { get; set; }
public String InputTypes { get; set; }
public System.Collections.Generic.List<Option> Options { get; set; }
}
public class Option
{
public int Id { get; set; }
public int Order { get; set; }
public string Details { get; set; }
public double point { get; set; }
}
Here is my controller
public ActionResult Index()
{
var questions = _context.Questions.ToList();
var questionModel = new List<Question>();
questions.ForEach(q =>
{
var model = new Question
{
Id = q.Id,
Title = q.Title,
Details = q.Details,
HasMultiAnswers = q.HasMultiAnswers,
NumberOfAnswers = q.NumberOfAnswers,
InputTypes = q.InputTypes, //New Line
Options = _context.Options.Where(f => f.point == 10).ToList()
};
questionModel.Add(model);
});
return View(questionModel);
}
#using (Html.BeginForm("Save", "Home", FormMethod.Post))
{
<div class="jumbotron">
#for (int i = 0; i < Model.Count(); i++)
{
var inputTypes = Model[i].InputTypes.Split(',').ToList();
<p>#Model[i].Details</p>
for (int j = 0; j < Model[i].Options.Count; j++)
{
for (int x = 0; x < inputTypes.Count; x++)
{
if (inputTypes[x] == "TextBox")
{
#Html.TextBoxFor(u => Model[i].Options[j].Details, new { #class = "form" })
}
else if (inputTypes[x] == "CheckBox")
{
// #Html.CheckBoxFor(u => Model[i].Options[j].Details, new { #class = "form" }) // - Throws Error
}
else if (inputTypes[x] == "RadioButton")
{
#Html.RadioButtonFor(u => Model[i].Options[j].Details, new { #class = "form" })
}
}
}
}
</div>
}

MVC5 Razor html.dropdownlistfor set selected when value is in array

I'm developing an ASP.NET MVC 5 application, with C# and .NET Framework 4.6.1.
I have this View:
#model MyProject.Web.API.Models.AggregationLevelConfViewModel
[...]
#Html.DropDownListFor(m => m.Configurations[0].HelperCodeType, (SelectList)Model.HelperCodeTypeItems, new { id = "Configurations[0].HelperCodeType" })
The ViewModel is:
public class AggregationLevelConfViewModel
{
private readonly List<GenericIdNameType> codeTypes;
private readonly List<GenericIdNameType> helperCodeTypes;
public IEnumerable<SelectListItem> CodeTypeItems
{
get { return new SelectList(codeTypes, "Id", "Name"); }
}
public IEnumerable<SelectListItem> HelperCodeTypeItems
{
get { return new SelectList(helperCodeTypes, "Id", "Name"); }
}
public int ProductionOrderId { get; set; }
public string ProductionOrderName { get; set; }
public IList<Models.AggregationLevelConfiguration> Configurations { get; set; }
public AggregationLevelConfViewModel()
{
// Load CodeTypes to show it as a DropDownList
byte[] values = (byte[])Enum.GetValues(typeof(CodeTypes));
codeTypes = new List<GenericIdNameType>();
helperCodeTypes = new List<GenericIdNameType>();
for (int i = 0; i < values.Length; i++)
{
GenericIdNameType cType = new GenericIdNameType()
{
Id = values[i].ToString(),
Name = EnumHelper.GetDescription((CodeTypes)values[i])
};
if (((CodeTypes)values[i]) != CodeTypes.NotUsed)
codeTypes.Add(cType);
helperCodeTypes.Add(cType);
}
}
}
And Models.AggregationLevelConfiguration is:
public class AggregationLevelConfiguration
{
public byte AggregationLevelConfigurationId { get; set; }
public int ProductionOrderId { get; set; }
public string Name { get; set; }
public byte CodeType { get; set; }
public byte HelperCodeType { get; set; }
public int PkgRatio { get; set; }
public int RemainingCodes { get; set; }
}
I need to set selected value in these properties:
public IEnumerable<SelectListItem> CodeTypeItems
{
get { return new SelectList(codeTypes, "Id", "Name"); }
}
public IEnumerable<SelectListItem> HelperCodeTypeItems
{
get { return new SelectList(helperCodeTypes, "Id", "Name"); }
}
But I can't set it in new SelectList(codeTypes, "Id", "Name"); or new SelectList(helperCodeTypes, "Id", "Name"); because the selected value are in Configurations array: fields AggregationLevelConfiguration.CodeType and AggregationLevelConfiguration.HelperCodeType.
I think I have to set selected value in the View, but I don't know how to do it.
How can I set the selected values?
Unfortunately #Html.DropDownListFor() behaves a little differently than other helpers when rendering controls in a loop. This has been previously reported as an issue on CodePlex (not sure if its a bug or just a limitation)
The are 2 option to solve this to ensure the correct option is selected based on the model property
Option 1 (using an EditorTemplate)
Create a custom EditorTemplate for the type in the collection. Create a partial in /Views/Shared/EditorTemplates/AggregationLevelConfiguration.cshtml (note the name must match the name of the type
#model yourAssembly.AggregationLevelConfiguration
#Html.DropDownListFor(m => m.HelperCodeType, (SelectList)ViewData["CodeTypeItems"])
.... // other properties of AggregationLevelConfiguration
and then in the main view, pass the SelectList to the EditorTemplate as additionalViewData
#using (Html.BeginForm())
{
...
#Html.EditorFor(m => m.Configurations , new { CodeTypeItems = Model.CodeTypeItems })
...
Option 2 (generate a new SelectList in each iteration and set the selectedValue)
In this option your property CodeTypeItems should to be IEnumerable<GenericIdNameType>, not a SelectList (or just make codeTypes a public property). Then in the main view
#Html.DropDownListFor(m => m.Configurations[0].HelperCodeType, new SelectList(Model.CodeTypeItems, "Id", "Name", Model.Configurations[0].HelperCodeType)
Side note: there is no need to use new { id = "Configurations[0].HelperCodeType" - the DropDownListFor() method already generated that id attribute
I wrote this class to overcome an issue I was having with selecting an option in an html select list. I hope it helps someone.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
namespace Login_page.Models
{
public class HTMLSelect
{
public string id { get; set; }
public IEnumerable<string> #class { get; set; }
public string name { get; set; }
public Boolean required { get; set; }
public string size { get; set; }
public IEnumerable<SelectOption> SelectOptions { get; set; }
public HTMLSelect(IEnumerable<SelectOption> options)
{
}
public HTMLSelect(string id, string name)
{
this.id = id;
this.name = name;
}
public HTMLSelect(string id, string name, bool required, IEnumerable<SelectOption> options)
{
this.id = id;
this.name = name;
this.required = required;
}
private string BuildOpeningTag()
{
StringBuilder text = new StringBuilder();
text.Append("<select");
text.Append(this.id != null ? " id=" + '"' + this.id + '"' : "");
text.Append(this.name != null ? " name=" + '"' + this.name + '"' : "");
text.Append(">");
return text.ToString();
}
public string GenerateSelect(IEnumerable<SelectOption> options)
{
StringBuilder selectElement = new StringBuilder();
selectElement.Append(this.BuildOpeningTag());
foreach (SelectOption option in options)
{
StringBuilder text = new StringBuilder();
text.Append("\t");
text.Append("<option value=" + '"' + option.Value + '"');
text.Append(option.Selected != false ? " selected=" + '"' + "selected" + '"' + ">" : ">");
text.Append(option.Text);
text.Append("</option>");
selectElement.Append(text.ToString());
}
selectElement.Append("</select");
return selectElement.ToString();
}
}
public class SelectOption
{
public string Text { get; set; }
public Boolean Selected { get; set; }
public string Value { get; set; }
}
}
And
public IEnumerable<SelectOption> getOrderTypes()
{
List<SelectOption> orderTypes = new List<SelectOption>();
if (this.orderType == "OptionText")
{
orderTypes.Add(new SelectOption() { Value = "1", Text = "OptionText", Selected = true });
} else
{
orderTypes.Add(new SelectOption() { Value = "2", Text = "OptionText2" });
}
}
And to use it:
#{
Login_page.Models.HTMLSelect selectElement = new Login_page.Models.HTMLSelect("order-types", "order-types");
}
#Html.Raw(selectElement.GenerateSelect(Model.getOrderTypes()));
I leave this in case it helps someone else. I had a very similar problem and none of the answers helped.
We had in a view this line at the top:
IEnumerable<SelectListItem> exitFromTrustDeed = (ViewData["ExitFromTrustDeed"] as IEnumerable<string>).Select(e => new SelectListItem() {
Value = e,
Text = e,
Selected = Model.ExitFromTrustDeed == e
});
and then below in the view:
#Html.DropDownListFor(m => m.ExitFromTrustDeed, exitFromTrustDeed, new { #class = "form-control" })
We had a property in my ViewData with the same name as the selector for the lambda expression and for some reason that makes the dropdown to be rendered without any option selected.
We changed the name in ViewData to ViewData["ExitFromTrustDeed2"] and that made it work as expected.
Weird though.

load one item per page [ Pagination ]

I have a viewpage like below
this is the controller method for above view
public ActionResult Add_Product()
{
var model = new AddNewProduct
{
ListProductFields = db.AB_ProductTypeCategoryField.ToList()
};
return View(model);
}
this is model class for above view
public class AddNewProduct
{
public string Product_ID { get; set; }
public string ProductTypeID { get; set; }
public string ProductCategoryID { get; set; }
public string Subsidary_ID { get; set; }
public IList<AB_ProductTypeCategoryField> ListProductFields { get; set; }
}
public partial class AB_ProductTypeCategoryField
{
public string Field_Value_EN { get; set; }
public string Field_Value_AR { get; set; }
}
this is viewpage
#model albaraka.Models.AddNewProduct
#using (Html.BeginForm())
{
#for (int i = 0; i < Model.ListProductFields.Count; i++)
{
#Html.TextAreaFor(m => m.ListProductFields[i].Field_Value_EN, new { #class = "form-control summernote", #row = 5 })
#Html.TextAreaFor(m => m.ListProductFields[i].Field_Value_AR, new { #class = "form-control summernote", #row = 5 })
}
}
Now I want to add pagination for above view page and limit one ListProductFields per one page , for that I following this Tutorial
So I change my code to like this
public ActionResult Add_Product(int? page)
{
var dummyItems = db.AB_ProductTypeCategoryField.Select(x => "Item " + x);
var pager = new PaginationModel.Pager(dummyItems.Count(), page);
var model = new AddNewProduct
{
Items = dummyItems.Skip((pager.CurrentPage - 1) * pager.PageSize).Take(pager.PageSize).ToList(),
Pager = pager
};
return View(model);
}
But then I'm getting following Run-time Error
Values of type 'AB_ProductTypeCategoryField' can not be converted to string.
Just try with following code , so you cannot use Skip method alone. so have use OrderBy before it
var dummyItems = db.AB_ProductTypeCategoryField;
var pager = new PaginationModel.Pager(dummyItems.Count(), page);
var model = new AddNewProduct
{
ListProductFields = dummyItems.OrderBy(i => i.SomeProperty).Skip((pager.CurrentPage - 1) * pager.PageSize).Take(pager.PageSize).ToList(),
Pager = pager
};
return View(model);
The issue of your observation is below line
var dummyItems = db.AB_ProductTypeCategoryField.Select(x => "Item " + x);
Since you are trying to select object with string concatenate operation ("Item " + x) that's why exception is thrown as AB_ProductTypeCategoryField is an object. I don't think you require "Item " + x at all.
You can change AddNewProdcut action implementation as
public ActionResult Add_Product(int? page)
{
var pager = new PaginationModel.Pager(dummyItems.Count(), page);
var model = new AddNewProduct
{
ListProductFields = db.AB_ProductTypeCategoryField.Skip((pager.CurrentPage - 1) * pager.PageSize).Take(pager.PageSize).ToList(),
Pager = pager
};
return View(model);
}

Recursive call of #helper method in ASP.NET MVC Razor, code inside the #helper method is skipped during execution

I am trying to populate the nested Ordered list using #functions & #helper features in ASP.NET MVC Razor.
I am successful in creating nested list using #functions, but when I tried to the same with #helper method execution is not going inside the helper method.
Model:
public class NavigationMenuModels
{
public int ID { get; set; }
public int? ParentID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public List<NavigationMenuModels> SubNavigationMenu { get; set; }
}
View Model:
public class NavigationMenuViewModel
{
public NavigationMenuViewModel()
{
ListMenu = new List<NavigationMenuModels>();
}
public string ListName { get; set; }
public List<NavigationMenuModels> ListMenu { get; set; }
}
Controller:
public ActionResult NavigationMenu()
{
//Menu
NavigationMenuModels objMenu = new NavigationMenuModels() { ID = 1, ParentID = null, Name = "Menu", Description = "Menu" };
//Menu Items
List<NavigationMenuModels> objMenuItems = new List<NavigationMenuModels>();
objMenuItems.Add(new NavigationMenuModels() { ID = 1, ParentID = 1, Name = "Home", Description = "Home" });
objMenuItems.Add(new NavigationMenuModels() { ID = 2, ParentID = 1, Name = "About", Description = "About" });
objMenuItems.Add(new NavigationMenuModels() { ID = 3, ParentID = 1, Name = "Help", Description = "Help" });
objMenuItems.Add(new NavigationMenuModels() { ID = 4, ParentID = 1, Name = "Contact", Description = "Contact" });
objMenu.SubNavigationMenu = objMenuItems;
//Admin
NavigationMenuModels objAdmin = new NavigationMenuModels() { ID = 2, ParentID = null, Name = "Admin", Description = "Admin" };
//Admin Items
List<NavigationMenuModels> objAdminItems = new List<NavigationMenuModels>();
objAdminItems.Add(new NavigationMenuModels() { ID = 1, ParentID=2, Name = "User Permissions", Description = "User Permissions" });
objAdminItems.Add(new NavigationMenuModels() { ID = 2, ParentID=2, Name = "Security", Description = "Security" });
objAdmin.SubNavigationMenu = objAdminItems;
//Account
NavigationMenuModels objAccount = new NavigationMenuModels() { ID = 3, ParentID = null, Name = "Account", Description = "Account" };
//Account Items
List<NavigationMenuModels> objAccountItems = new List<NavigationMenuModels>();
objAccountItems = null;
objAccount.SubNavigationMenu = objAccountItems;
NavigationMenuViewModel objNavigationMenu = new NavigationMenuViewModel();
objNavigationMenu.ListName = "Master Navigation";
objNavigationMenu.ListMenu.Add(objMenu);
objNavigationMenu.ListMenu.Add(objAdmin);
objNavigationMenu.ListMenu.Add(objAccount);
return View(objNavigationMenu);
}
CSHTML:
#using LearnAngularJs_App1.Models
#using System.Text
#model LearnAngularJs_App1.Models.NavigationMenuViewModel
#{
ViewBag.Title = "NavigationMenu";
}
#functions
{
public static HtmlString GetNestedListHtml(NavigationMenuViewModel Crudeinput)
{
StringBuilder sb = new StringBuilder();
var orderedList = new TagBuilder("ol");
foreach (NavigationMenuModels NavMenu in Crudeinput.ListMenu)
{
var listItem = new TagBuilder("li");
listItem.SetInnerText(NavMenu.Name);
sb.AppendLine(listItem.ToString(TagRenderMode.Normal));
if (NavMenu.SubNavigationMenu != null)
{
if (NavMenu.SubNavigationMenu.Count > 0)
{
sb.AppendLine(BuildNestedList(NavMenu.SubNavigationMenu));
}
}
}
orderedList.InnerHtml = sb.ToString();
return new HtmlString(orderedList.ToString(TagRenderMode.Normal));
}
public static string BuildNestedList(List<NavigationMenuModels> SubMenuList)
{
var sb = new StringBuilder();
var orderedList = new TagBuilder("ol");
if (SubMenuList.Count > 0)
{
foreach (NavigationMenuModels SubNavgationMenuitem in SubMenuList)
{
var listItem = new TagBuilder("li");
listItem.SetInnerText(SubNavgationMenuitem.Name);
sb.AppendLine(listItem.ToString(TagRenderMode.Normal));
if (SubNavgationMenuitem.SubNavigationMenu != null)
{
if (SubNavgationMenuitem.SubNavigationMenu.Count > 0)
{
sb.AppendLine(BuildNestedList(SubNavgationMenuitem.SubNavigationMenu));
}
}
}
}
orderedList.InnerHtml = sb.ToString();
return orderedList.ToString(TagRenderMode.Normal);
}
}
#helper BuildNestedListHelper(List<NavigationMenuModels> Crudeinput)
{
if (Crudeinput.Any())
{
<ol>
#foreach (NavigationMenuModels NavMenu in Crudeinput)
{
<li>
#NavMenu.Name
#if (NavMenu.SubNavigationMenu != null)
{
BuildNestedListHelper(NavMenu.SubNavigationMenu);
}
</li>
}
</ol>
}
}
<h2>NavigationMenu</h2>
<div>
<div><span>Bind Navigation Menu using razor ##funtions</span></div>
<div>
#GetNestedListHtml(Model)
</div>
</div>
<div>
<div><span>Bind Navigation Menu using razor ##helper</span></div>
<div>
#BuildNestedListHelper(Model.ListMenu)
</div>
</div>
When a recursive call to the helper method is made execution is going to the method, but the execution is skipped.
just add "#" in front of the method when recursive call.

ViewData Int32 must be of type IEnumerable when viewing from stored procedure

I don't know if it is because of the stored procedure I did. But I always get this error
The ViewData item that has the key 'Department' is of type
'System.Int32' but must be of type 'IEnumerable'.
Here's my code :
(VIEW)
<div class="col-lg-4">
<%: Html.DropDownListFor(m => m.Department, Model.Departments, "Please Select", ((ViewBag.Role >= 2 && ViewBag.Role <= 5) ? (object)new { #class="form-control", #onchange="onChangeDepartment(this.value);" }:(object)new { #class="form-control", #disabled="disabled" }))%>
</div>
(MODEL)
public bool LoadDepartmentsFromDB()
{
WorkflowEntities entity = new WorkflowEntities();
List<SelectListItem> departments = new List<SelectListItem>();
List<SelectListItem> supervisors = new List<SelectListItem>();
foreach (sp_DepartmentMaster_GetAll_Result sp_depts in entity.sp_DepartmentMaster_GetAll()) {
departments.Add(new SelectListItem {
Value = sp_depts.DepartmentId.ToString()
, Text = sp_depts.DepartmentName
, Selected = sp_depts.DepartmentId == Department
});
supervisors.Add(new SelectListItem {
Value = sp_depts.SupervisorId.ToString()
, Text = sp_depts.SupervisorName
, Selected = sp_depts.DepartmentId == Department
});
if (sp_depts.DepartmentId == Department) this.Supervisor = sp_depts.SupervisorId;
}
this.Departments = departments;
this.Supervisors = supervisors;
return true;
}
Did I missed something ?
Added :
public IEnumerable<SelectListItem> Departments { get; set; }
Stored Procedure Property
public partial class sp_DepartmentMaster_GetAll_Result
{
public int DepartmentId { get; set; }
public string DepartmentName { get; set; }
public int SupervisorId { get; set; }
public string SupervisorName { get; set; }
}

Categories

Resources