DropDownListFor from Simple List Model - c#

How can i implement simple DropDownList without Id.
public AddItemModel()
{
Types = new SelectList(new []{"Type1", "Type2", "Type3"});
}
public SelectList Types { get; set; }
#Html.DropDownListFor(x => x.AddItem, ???

You will need a property on your view model to hold the selected value and then you may try this:
public AddItemModel()
{
var data = new [] { "Type1", "Type2", "Type3" };
Types = data.Select(x => new SelectListItem
{
Value = x,
Text = x,
});
}
public IEnumerable<SelectListItem> Types { get; set; }
public string SelectedType { get; set; }
and then in your view:
#Html.DropDownListFor(x => x.SelectedType, Model.Types)

Related

Create a generic List<SelectListItem> function

I have two DbSets:
public DbSet<Reports.Models.Application> Application { get; set; }
public DbSet<Reports.Models.Category> Category { get; set; }
In the controller, I'm creating two List<SelectListItem>s:
var applications = _context.Application
.Select(listItem => new SelectListItem
{
Value = listItem.ID,
Text = listItem.Name
}
).ToList();
var categories = _context.Category
.Select(listItem => new SelectListItem
{
Value = listItem.ID,
Text = listItem.Name
}
).ToList();
I'd like to refactor this into a single, private method:
private List<SelectListItem> SelectList<T>(bool blankListItem = false)
{
var selectListItems = _context.<T> <------ doesn't compile
.Select(listItem => new SelectListItem
{
Value = listItem.ID,
Text = listItem.Name
}
).ToList();
if (blankListItem)
selectListItems.Insert(0, (new SelectListItem { Text = $"Choose {{T.ToString}}", Value = "" }));
return selectListItems;
}
And call it twice:
var applications = SelectList<Application>();
var categories = SelectList<Category>();
or
var applications = SelectList<Application>(true); // add "choose"
var categories = SelectList<Category>(true); // add "choose"
What's the right way to define the _context.<T> part? Perhaps this should be an extension method of the DbSet instead?
Maybe you can have your dbsets inherit a base class. which would be representing the generic type T.
Something like;
public class BaseClassForDbSets
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Application : BaseClassForDbSets
{
}
public class Category : BaseClassForDbSets
{
}
and then your private method;
private IEnumerable<SelectListItem> GetSelectList<T>(IEnumerable<T> dataSource, bool blankListItem = false) where T : BaseClassForDbSets
{
var selectListItems = dataSource
.Select(listItem => new SelectListItem
{
Value = listItem.Id.ToString(),
Text = listItem.Name
}
).ToList();
if (blankListItem)
selectListItems.Insert(0, (new SelectListItem { Text = $"Choose {nameof(T)}", Value = "" }));
return selectListItems;
}
Then you would call it like;
var applicationCollection = GetSelectList(_context.Application);
var categoryCollection = GetSelectList(_context.Category);
Do note - not tested
My solution uses a different approach, but same result.
Start with an interface:
public interface IBaseSelectItem
{
int Id { get; set; }
string Name { get; set; }
}
Have your entities (Application and Category) implement the interface:
public partial class Category : IBaseSelectItem
{
public int Id { get; set; }
public string Name { get; set; }
}
Create an extension on DbSet:
public static IList<SelectListItem> AsSelectList<T>(this DbSet<T> dbSet, bool useChooseValueOption) where T : class, IBaseSelectItem
{
var selectList = dbSet
.Select(c => new SelectListItem { Value = c.Id.ToString(), Text = c.Name })
.ToList();
if (useChooseValueOption)
selectList.Insert(0, new SelectListItem { Value = "0", Text = "-Choose Value-" });
return selectList;
}
Then use like this:
var categoriesSelectList = _dbContext.Categories.AsSelectList();

DropDownListFor not pre-selecting value from model

Controller Code:
AccountsDetailsViewModel vOwnerVM = Mapper.Map<VehicleOwner, AccountsDetailsViewModel>(vOwner);
AccountsDetailsAccountViewModel vOwnerDetailsVM = Mapper.Map<VehicleOwner, AccountsDetailsAccountViewModel>(vOwner);
ViewBag.FleetType = new SelectList(VehicleOwnerFleetTypeFactory.GetTypes().OrderBy(l => l.Type), "Id", "Type");
vOwnerVM.AccountDetails = vOwnerDetailsVM;
Main ViewModel Code:
public class AccountsDetailsViewModel
{
public AccountsDetailsAccountViewModel AccountDetails { get; set; }
}
Main View Code
#model X.Views.Accounts.ViewModels.AccountsDetailsViewModel
#Html.Partial("DetailsAccount", #Model.AccountDetails)
Partial ViewModel Code:
[DisplayName("Fleet Type")]
public int FleetType { get; set; }
Partial View Code
#model X.Views.Accounts.ViewModels.AccountsDetailsAccountViewModel
#Html.DropDownListFor(model => model.FleetType,
(IEnumerable<SelectListItem>)ViewBag.FleetType)
#Html.DisplayFor(model => model.FleetType) (FOR DEBUG)
VehicleOwnerFleetType class
public class VehicleOwnerFleetType
{
public int Id { get; set; }
public string Type { get; set; }
}
public class VehicleOwnerFleetTypeFactory
{
static readonly VehicleOwnerFleetType[] Types = new VehicleOwnerFleetType[] {
new VehicleOwnerFleetType() {Id = 0, Type = "Unknown"},
new VehicleOwnerFleetType() {Id = 1, Type = "HGV"},
new VehicleOwnerFleetType() {Id = 2, Type = "Car"},
new VehicleOwnerFleetType() {Id = 3, Type = "Van"},
new VehicleOwnerFleetType() {Id = 4, Type = "Mixed"}
};
public static VehicleOwnerFleetType[] GetTypes()
{
return Types;
}
public static VehicleOwnerFleetType GetType(int id)
{
return Types.FirstOrDefault(m => m.Id == id);
}
}
Regardless of what the database shows, the dropdown does not display the correct value from the model, only ever the top value in the list.
However if I select a value and then submit the form to save the changes to the database, it does submit the correct value.
When returning the view of the viewmodel in the controller, the values mirror the database exactly, I cannot figure out why it is doing this.
Edit: The 'Sectors' dropdown is the ONLY one that auto-selects the correct value.
The problem is likely caused by the fact that your selectlist, and your VM's member variable have the same names.
model.FleetType
and
(IEnumerable<SelectListItem>)ViewBag.FleetType
Try to rename the select list to FleetTypeList or similar
Works fine for me. Check if you pass the model to the view.
#using WebApplication2.Controllers
#model WebApplication2.Controllers.MyModel
#{
ViewBag.Title = "Home Page";
ViewBag.FleetType = new SelectList(
VehicleOwnerFleetTypeFactory.GetTypes().OrderBy(l => l.Type),
"Id",
"Type");
}
<div>
<h2>---------------------------</h2>
#Html.DropDownListFor(model => model.FleetType,
(SelectList)ViewBag.FleetType)
<h2>---------------------------</h2>
</div>
and
using System.Web.Mvc;
namespace WebApplication2.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
return View(new MyModel { FleetType = 2 });
}
}
public class MyModel
{
public int FleetType { get; set; }
}
public class VehicleOwnerFleetTypeFactory
{
public static FleetType[] GetTypes()
{
return new[]
{
new FleetType {Id = 1, Type = "Type 1"},
new FleetType {Id = 2, Type = "Type 2"},
new FleetType {Id = 3, Type = "Type 3"}
};
}
}
public class FleetType
{
public int Id { get; set; }
public string Type { get; set; }
}
}

How to set propety which type is Enum based on the integer value of the Enum

I am working on an ASP.NET MVC4 application using EF 5 and Code First. One of my entities looks like this :
public enum PageTypes
{
LinkPage = 10,
FileListPage = 20,
TableValuePage = 30
}
public class Page
{
public int PageID { get; set; }
public string Title { get; set; }
public PageTypes Type { get; set; }
public DateTime Date { get; set; }
}
in my view I have dropDown where these values are hardcoded (taken from a viewmodel):
public class PagesViewModel
{
public PageViewModel()
{
TypeOfPage = new List<ListItem> {
new ListItem { Text = "LinkPage ", Value = "10" },
new ListItem { Text = "FileListPage ", Value = "20" },
new ListItem { Text = "TableValuePage ", Value = "30" } };
}
//some other properties
public string SelectedValue { get; set; }
public List<ListItem> TypeOfPage { get; set; }
}
and the actual visualization in the view:
#Html.DropDownListFor(m => m[i].SelectedValue, new SelectList(Model[i].TypeOfPage, "Value", "Text")})
So when I get the model in my controller how can I actually set the Page Type based on the SelectedValue from the ViewModel :
new Page { //other properties.., Type = ???? }
It's deceptively simple:
var enumValue = (EnumType)integer;
So in your case, the selected value from your drop down will be a string, so first you will need to int.Parse it to an integer, then do your cast as above to put it in your property assignment.
new Page { Type = (PageTypes)integerFromDropDown, ... }

MVC SelectLists using ViewBag SelectedItem not being set

I have the following code:
public class OrganisationController : Controller
{
//
// GET: /Organisation/
public ActionResult Update()
{
var fisherman = new RoleType {Id = 1, Name = "Fisherman"};
var manager = new RoleType {Id = 2, Name = "Manager"};
var deckhand = new RoleType {Id = 3, Name = "Deckhand"};
var roleTypes = new List<RoleType>
{
fisherman, manager, deckhand
};
ViewBag.Roles = new SelectList(roleTypes, "Id", "Name");
return View(
new Organisation
{
Name = "Fish Co.",
People = new List<Person>
{
new Person
{
Name = "Squid",
RoleType = fisherman
},
new Person
{
Name = "Michael",
RoleType = manager
},
new Person
{
Name = "John",
RoleType = deckhand
}
}
});
}
[HttpPost]
public ActionResult Update(Organisation org)
{
return View();
}
}
public class Organisation
{
public string Name { get; set; }
public IList<Person> People { get; set; }
}
public class Person
{
public string Name { get; set; }
public RoleType RoleType { get; set; }
}
public class RoleType
{
public int Id { get; set; }
public string Name { get; set; }
}
In Update.cshtml
#model Models.Organisation
<form action="" method="post" enctype="multipart/form-data">
#Html.EditorFor(x => x.Name)
#Html.EditorFor(x => x.People)
<input type="submit"/>
</form>
In the EditorTemplates Person.cshtml:
#model Models.Person
#Html.EditorFor(x => x.Name)
#if(Model != null)
{
#Html.DropDownListFor( x => x.RoleType.Id, (SelectList)ViewBag.Roles)
}
I was expecting to be able to get to a page where I can update the organisation name, the people names and their roles. The trouble is that I can't get the selected item to be set for the dropdowns. I thought x => x.RoleType.Id would do this for me.
Does anyone know how I can get this to work?
Try this constructor: SelectList Constructor (IEnumerable, String, String, Object)
public SelectList(
IEnumerable items,
string dataValueField,
string dataTextField,
Object selectedValue
)
Something like this:
#Html.DropDownListFor( x => x.RoleType.Id, new SelectList((List<RoleType>)ViewBag.Roles, "Id", "Name", Model.RoleType.Id))

Html.DropDownlistFor selectedValue

Having a hard time getting this dropDownList to Bind. This is simply a list of states. The Model.State is "TX", but my dropdownlist is showing "AK", which is the first value in the list. Any thoughts?
<%: Html.DropDownListFor(
model => model.State,
new SelectList(
muniSynd.getStatecodesDropDown(),
"Value",
"Text",
Model.State.ToString().Trim()
)
)
%>
In my muniSynd class, which is a wrapper of my dataContext.....
public IList<StateCodeViewModel> getStatecodesDropDown()
{
var states = from p in this._MuniDc.Statecodes
select new StateCodeViewModel
{
Value = p.Statecode1.ToString().Trim(),
Text = p.Statecode1.ToString().Trim()
};
return states.ToList();
}
public class StateCodeViewModel
{
public string Value{get;set;}
public string Text{get;set;}
}
Im using LinqToSQL, here is the object
[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.Statecodes")]
public partial class Statecode
{
private string _Statecode1;
public Statecode()
{
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Name="Statecode", Storage="_Statecode1", DbType="NVarChar(3)")]
public string Statecode1
{
get
{
return this._Statecode1;
}
set
{
if ((this._Statecode1 != value))
{
this._Statecode1 = value;
}
}
}
}
I've tried to replicate your problem, but my example below works fine:
public class HomeController : Controller
{
public ActionResult Index()
{
var viewModel = new IndexViewModel();
viewModel.State = "TX";
return this.View(viewModel);
}
public static IList<StateCodeViewModel> getStatecodesDropDown()
{
var stateCodes = new List<string> { "AX", "GH", "TX" };
var states = from p in stateCodes
select new StateCodeViewModel
{
Value = p,
Text = p
};
return states.ToList();
}
}
public class IndexViewModel
{
public string State { get; set; }
}
public class StateCodeViewModel
{
public string Value { get; set; }
public string Text { get; set; }
}
View
#using MVCWorkbench.Controllers
#model IndexViewModel
#{
ViewBag.Title = "title";
}
#Html.DropDownListFor(model => model.State,
new SelectList(HomeController.getStatecodesDropDown(),
"Value",
"Text",
Model.State.ToString().Trim()
)
)
Not sure what to suggest other then check that the State value is in the dropdown list. Also this could be a case-sensitivity issue perhaps?

Categories