I have problem with dropdownlist. I want show text in selectedlist but select Id.
How I implement view? In view I must save selected data to model (odbiorca)
Controller:
var odbiorca = dbU.Uczniowie.OrderBy(d => d.Nazwisko).Select(m => m.Nazwisko + " " + m.Imie).ToList(); //return Names
var odbiorcaId= dbU.Uczniowie.OrderBy(d => d.Id).Select(m => m.Nazwisko + " " + m.Imie).ToList(); //return IDs
List<SelectListItem> items = new List<SelectListItem>();
for (int i=0;i<dbU.Uczniowie.Count();i++)
{
items.Add(new SelectListItem { Text = odbiorca[i], Value = odbiorcaId[i] });
}
ViewBag.odbiorca = items;
Model:
public class Uwaga
{
[Key]
[Required]
public string Id { get; set; }
[Required]
public string odbiorca { get; set; }
[Required]
public DateTime data { get; set; }
}
I tried this solution but the program saves text, but not value.
#Html.DropDownList("odbiorca", "----")
Both of your linq statements return the same values.
var odbiorca = dbU.Uczniowie.OrderBy(d => d.Nazwisko).Select(m => m.Nazwisko + " " + m.Imie).ToList(); //return Names
var odbiorcaId= dbU.Uczniowie.OrderBy(d => d.Id).Select(m => m.Nazwisko + " " + m.Imie).ToList(); //return IDs
both of these return a list of m.Nazwisko + " " + m.Imie there is no Id.
you should just use one query to get your select list
var list = dbU.Uczniowie.Select(a => new {Text= a.Nazwisko + " " + a.Imie, Value = a.Id}).ToList();
ViewBag.odbiorca = list.Select(a => new SelectListItem{ Text = a.Text, Value = a.Value.ToString()});
Try this approach. Lets take your model class:
public class Uwaga
{
[Key]
[Required]
public string Id { get; set; }
Required]
public string odbiorca { get; set; }
[Required]
public DateTime data { get; set; }
}
In the view you can use the same helper: #Html.DropDownList("odbiorca", "----")
But, in the controller you set the "id" and "text" columns through a SelectList object. Take the example in the default action in the controller:
public ActionResult Index()
{
//Creates a example list with multiple "Uwaga" items,
//but you might want to pull the data from the database
List<Uwaga> UwagaList = new List<Uwaga>();
for (int i = 1; i <= 10; i++)
{
Uwaga item = new Uwaga();
item.Id = i;
item.odbiorca = "odbiorca " + i;
UwagaList.Add(item);
}
//Create a SelectList object, the first parameter is the list created above.
//The second parameter is the "id" key and the thirth
//parameter is the text you want to display in the dropdown.
var SelectList = new SelectList(UwagaList, "Id", "odbiorca");
//Fill the dropdownlist "odbiorca" using ViewData.
ViewData["odbiorca"] = SelectList;
}
I hope it helps.
Related
I have the below code which pass 2 values (ProductId and ItemName) to SelectList (Dropdownlist) located on the View.
I need a way to pass 3 values (ProductId, Price, and ItemName).
public class Product
{
public int ProductId { get; set; }
public int Price { get; set; }
public string ItemName { get; set; }
public IList<ProductInvoice> ProductInvoices { get; set; }
}
public IActionResult Create()
{
IEnumerable<SelectListItem> items = _context.Products.Select(c => new SelectListItem
{
Value = c.ProductId.ToString() + "-" + c.Price,
Text = c.ItemName
});
ViewData["Products"] = items;
return View();
}
Code to generate drop down list:
#Html.DropDownList("SelectedProducts",new SelectList((System.Collections.IEnumerable)ViewData["Products"], "Value", "Text", new { #class = "form-control dropdown-list" }))
You can join every property you need by a delimiter and pass it to Value. Like this:
IEnumerable<SelectListItem> items = _context.Products.Select(c => new SelectListItem
{
Value = String.Join("$", new string[] { c.ProductId.ToString(), c.Price }),
Text = c.ItemName
});
and when fetching back, you can perform a split with the delimiter. Like this:
var myVal = value.Split("$");
string productId = myVal[0];
string price = myVal[1];
You made almost right thing, only if you want to see the price you have to concat it with Name, not with Id
public IActionResult Create()
{
var selectListItems= _context.Products.Select(c => new SelectListItem
{
Value = c.ProductId.ToString(),
Text = c.ItemName+ " - " + c.Price.ToString()
});
var items= new SelectList( selectListItems,"Value", "Text");
ViewData["Products"] = items;
var model=new Product();
return View( model);
}
and fix the view
#Html.DropDownListFor(m=> m.ProductId, (SelectList) ViewData["Products"], new { #class = "form-control dropdown-list" }))
i am struggling to find a different approach for this code.
I want to create a dropdown list to select a category.
As you can see it is not clean and does not work for multiple levels.
I am not an expert in .NET and would like to learn how a professional does this.
List<SelectListItem> list = new List<SelectListItem>();
foreach (Category item in db.CategorySet.Where(x => x.ParentCategory == null))
{
list.Add(new SelectListItem { Value = item.Id.ToString(), Text = item.Name });
foreach (Category subitem in item.SubCategories)
{
list.Add(new SelectListItem { Value = subitem.Id.ToString(), Text = " - " + subitem.Name });
foreach (Category subsubitem in subitem.SubCategories)
{
list.Add(new SelectListItem { Value = subsubitem.Id.ToString(), Text = " - - " + subsubitem.Name });
foreach (Category subsubsubitem in subsubitem.SubCategories)
{
list.Add(new SelectListItem { Value = subsubsubitem.Id.ToString(), Text = " - - - " + subsubsubitem.Name });
//...
}
}
}
}
public partial class Category
{
public Category()
{
this.Products = new HashSet<Product>();
this.SubCategories = new HashSet<Category>();
}
public int Id { get; set; }
public string Name { get; set; }
public string Icon { get; set; }
public Nullable<int> ParentCategoryId { get; set; }
public virtual ICollection<Product> Products { get; set; }
public virtual ICollection<Category> SubCategories { get; set; }
public virtual Category ParentCategory { get; set; }
}
Thank you in advance...
Seems like you are making hierarchial tree (using the "-", "- -", and so on).
Assuming your Categories is non-cyclic, you should consider using recursive function to solve your issue, passing your list as well as your printed prefix (the "-") or your "depth" on the recursive search.
Something like below would probably serve:
public void addCatToList(List<SelectedItemList> list, int depth, IEnumerable<Category> cats){
foreach (Category item in cats)
{
list.Add(new SelectListItem { Value = item .Id.ToString(), Text = printDash(depth) + item.Name });
addCatToList(list, depth + 1, item.SubCategories);
}
}
private string printDash(int number){
string dash = string.Empty;
for(int i = 0; i < number; ++i){
if (i == 0)
dash += " ";
dash += "- ";
}
return dash;
}
And then you call it the first time with depth = 0:
List<SelectListItem> list = new List<SelectListItem>();
addCatToList(list, 0, db.CategorySet.Where(x => x.ParentCategory == null));
In controller I have this code and at this moment I have DropDown list just for firstname.
Code is here:
ViewBag.patnikID = new SelectList(db.tbl_patnici, "pID", "firstname");
And now I need some code like this:
ViewBag.patnikID = new SelectList(db.tbl_patnici, "pID", ("firstname" + "lastname"));
How to do it?
Your tbl_patnici class
public class tbl_patnici
{
public int pID { get; set; }
public string firstname { get; set; }
public string lastname { get; set; }
//[NotMapped] If you use entityframework then you must use NotMapped attribute.
public string fullname { get { return this.firstname + " " + this.lastname; } }
}
ViewBag.patnikID = new SelectList(db.tbl_patnici, "pID", "fullname");
I would suggest you don't bind directly to the database source and instead bind to your own IEnumerable which has the properties you want. I often have a reusable "ListItem" class which has ID and Text properties and then use a function to populate the list with the data I want.
For example:
Create a new class:
public class ListItem
{
public int ID { get; set; }
public string Text { get; set; }
}
Create a helper function:
public List<ListItem> GetList()
{
// get "db" here.
return db.tbl_patnici.Select(x => new ListItem {
ID = x.pID,
Text = x.firstname + " " + x.lastname
});
}
Call it like so:
ViewBag.patnikID = new SelectList(GetList(), "ID", "Text");
You can check this:
#Html.DropDownListFor(model => model.pID, new SelectList(db.tbl_patnici, "pID", Model.firstname + " " + Model.lastname, Model.pID), new { style = " width:260px" })
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.
I had a program working perfectly. But the dropdownlist of this page had just one information of one column, so I had to add another columns to this dropdownlist, because of the users ask. When I did it, my ModelState started to be Invalid.
ERROR MESSAGE:
The parameter conversion from type 'System.String' to type 'SINCO_MVC.Models.SINCO_CONCESSAO'' failed because no type converter can convert between these types
Im not seeing the reason of this error.
View:
<div class="editor-field" id="IDCONCESSAO">
<%: Html.DropDownListFor(model => model.SINCO_CONCESSAO,
new SelectList(ViewBag.IDCONCESSAO, "Id", "Nome"), string.Empty,
new { #class = "select", style = "width: 250px;" }) %>
</div>
Controller (where I catch the information of the dropdownlist):
// GET: /Concessao/Create
[Authorize(Roles = "ADMINISTRADOR")]
public ActionResult Create(SINCO_LOCALIDADE_CONCESSAO model)
{
ViewBag.IDCONCESSAO = from p in db.SINCO_CONCESSAO.ToList()
join c in db.MUNICIPIOS_VIEW.ToList() on p.IDMUNICIPIO equals c.ID_MUNICIPIO
join d in db.SINCO_TIPO_CONCESSAO.ToList() on p.IDTIPOCONCESSAO equals d.IDTIPOCONCESSAO
select new
{
Id = p.IDCONCESSAO,
Nome = p.IDCONCESSAO + " - " + c.NOME_MUNICIPIO + " - " + d.DSTIPOCONCESSAO
};
PopulateItemChoices(model);
return View(model);
}
Controller (post method):
[Authorize(Roles = "ADMINISTRADOR")]
[HttpPost]
public ActionResult Create(SINCO_LOCALIDADE_CONCESSAO sinco_localidade_concessao, SINCO_CONCESSAO sinco_concessao)
{
if (ModelState.IsValid)
{
db.SINCO_LOCALIDADE_CONCESSAO.Add(sinco_localidade_concessao);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.IDCONCESSAO = from p in db.SINCO_CONCESSAO.ToList()
join c in db.MUNICIPIOS_VIEW.ToList() on p.IDMUNICIPIO equals c.ID_MUNICIPIO
join d in db.SINCO_TIPO_CONCESSAO.ToList() on p.IDTIPOCONCESSAO equals d.IDTIPOCONCESSAO
select new
{
Id = p.IDCONCESSAO,
Nome = p.IDCONCESSAO + " - " + c.NOME_MUNICIPIO + " - " + d.DSTIPOCONCESSAO
};
PopulateItemChoices(sinco_localidade_concessao);
return View(sinco_localidade_concessao);
}
Model:
namespace SINCO_MVC.Models
{
[MetadataType(typeof(SincoLocalidadeConcessaoMetaData))]
public partial class SINCO_LOCALIDADE_CONCESSAO
{
public List<int> SelectedItemIds { get; set; }
public IEnumerable<SelectListItem> ItemChoices { get; set; }
}
public class SincoLocalidadeConcessaoMetaData
{
[Display(Name = "ID LOCALIDADE:")]
public int[] IDLOCALIDADE { get; set; }
[Display(Name = "ID:")]
public int IDCONCESSAO { get; set; }
[Display(Name = "Localidade:")]
public virtual LOCALIDADES_VIEW LOCALIDADES_VIEW { get; set; }
public virtual MUNICIPIOS_VIEW MUNICIPIOS_VIEW { get; set; }
}
}
The reason you get that error message is because a dropdown list returns a value type and your trying to bind to a complex object. Your posting back the selected value of IDCONCESSAO (an int I assume) and trying to bind that to SINCO_CONCESSAO. You need to bind the dropdown to a property of SINCO_CONCESSAO, for example
Html.DropDownListFor(model => model.SINCO_CONCESSAO.ID, ....)