I need to set the setectedValue of a DropDownList using razor, but because it's a list used several times in the same page, I can't set the selected value in the Controller, so how can I set it in the View?
Actual Controller List code:
ViewBag.CargaTipos = new SelectList(db.CargaTipos, "Id", "Nome").OrderBy(c => c.Text);
Actual View:
#Html.DropDownListFor(modelItem => item.CargaTipo.Id, (IEnumerable<SelectListItem>)ViewBag.CargaTipos)
Models:
[Table("Cargas")]
public class Carga
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
[ForeignKey("CargaTipo")]
public int CargaTipo_Id { get; set; }
[Display(Name = "Tipo de Carga")]
public virtual CargaTipo CargaTipo { get; set; }
}
[Table("CargaTipos")]
public partial class CargaTipo
{
public CargaTipo()
{
this.Cargas = new HashSet<Carga>();
}
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Nome { get; set; }
public virtual ICollection<Carga> Cargas { get; set; }
}
Cannot set SelectedValue property outside constructor of SelectedList class. Use this instead
ViewBag.CargaTipos = db.CargaTipos;
View
#Html.DropDownListFor(modelItem => item.CargaTipo.Id,new SelectList(ViewBag.CargaTipos,"Id","Nome",YOUR_SELECTED_VALUE))
I suggest you to do it with some JQuery code(you can also use JavaScript depending of you), but I advice JQuery. So you will need to reference link of JQuery lib in your Layout
<script>
$(document).ready(function ()
{
$("idOfyourDropDownList option[value=Id]').attr('selected','selected');
})
</script>
I think when you put this script on your solution, by default you will have item selected by default.
I hope it will help
You can try to use documented behavior of Html.DropDownListFor<> like this:
#Html.DropDownListFor(modelItem => modelItem.CargaTipo_Id,
(IEnumerable<SelectListItem>)ViewBag.CargaTipos)
Pay attention on using declared variable in expression. In your case it is modelItem.
And you have to use CargaTipo_Id from main model, not Id from referened model.
Related
I have a form that loads some Partial Views dinamically and one of these Partial Views will load multiple dropdownlists in the screen.
I have a ViewModel (principal): used in the main view
public class CupomFiscalDetalhesViewModel
{
//some properties
public IEnumerable<CupomItensViewModel> CupomItens { get; set; }
}
An intermediate ViewModel: the view model of the partial view:
public class CupomItensViewModel
{
public IEnumerable<TabelaPrecoViewModel> TabelasPreco { get; set; }
public TabelaPrecoViewModel TabelaPrecoSelecionada { get; set; }
}
Where TabelaPrecos is holding the values that I want to show in the DropDownList. and TabelaPrecoSelecionada will hold the selected value.
In the Controller, I'm used to put the values of an IEnumerable into a ViewBag, and use this ViewBag to generate the dropdownlist in the HTML, like this:
ViewBag.TabelaPrecoSelecionada = new SelectList
(
detalhesCupomFiscal.CupomItens.FirstOrDefault().TabelasPreco,
"IdTabela",
"NomeTabela"
);
But I have no idea how to generate multiple dropdowns for each option of CupomItensViewModel, without passing the id of the selected value of each dropdownlist to the controller action (by parameter).
In the Html, I use: but would need to change the name to get binding workin somehow.
#Html.DropDownList("TabelaPrecoSelecionada",(IEnumerable<SelectListItem>)ViewBag.TabelaPrecoSelecionada,
new { #class = "form-control dropdown" })
Does anyone has an Idea how to accomplish it?
I haven't test this but I would maybe create the select list inside your CupomItensViewModel
using System.Linq;
public class CupomItensViewModel
{
public IEnumerable<TabelaPrecoViewModel> TabelasPreco { get; set; }
public TabelaPrecoViewModel TabelaPrecoSelecionada { get; set; }
public IEnumerable<SelectListItem> TabelasPrecoSelectList
{
get
{
return TabelasPreco.Select(x => new SelectListItem()
{
Value = x.IdTabela
Text = x.NomeTabela
Selected = TabelaPrecoSelecionada.IdTabela
}
}
}
}
And Inside your view
#foreach(var item in Model.CupomItens)
{
#Html.DropDownList("TabelaPrecoSelecionada", item.TabelasPrecoSelectList, new { #class = "form-control dropdown" })
}
But if these dropdowns aren't going to be next to each other, I would make
public IEnumerable<CupomItensViewModel> CupomItens { get; set; }
List instead and using index to identify them. CupomItens[x]
Just my 2 cent without checking if it works. Hopefully it helps.
I need to populate a dropdown with some data i get from a SOAP server. The server provides me an array of the companies.
How would i use it to populate the DD ?
Here is my User class:
public class Usuario
{
public string Nome { get; set; }
public string Token { get; set; }
public IEnumerable<SelectListItem> Unidades { get; set; }
}
Here is where i receive the companies and send it to the view, i get it from another Action that is redirecting to this Action:
var usuario = TempData["objUsuario"] as UsuarioSSO;
if (usuario == null) return RedirectToAction("Index", "Login");
if (usuario.UsuarioUnidades == null)
{
ModelState.AddModelError("", "Usuário não possui unidades");
return View();
}
var model = new Models.Usuario
{
Unidades = usuario.UsuarioUnidades.ToList().Select(x => new SelectListItem
{
Value = x.CodigoEmitente.ToString(),
Text = x.NomeFantasia
})
};
return View(model);
Here is how i'm trying to display it:
#Html.DropDownListFor(x => x.Unidades, new SelectList(Model.Unidades))
I have already tried of everything but it won't work, i get some conversion errors and when i can make it work it won't display the content, it will only display the object inside the Text area
System.Web.Mvc.SelectListItem
You need to have one property for the selected item and the list of available items, e.g.:
public class Usuario
{
public string Nome { get; set; }
public string Token { get; set; }
public string Unidade { get; set; }
public IEnumerable<SelectListItem> Unidades { get; set; }
}
and then create the drop-down like:
#Html.DropDownListFor(x => x.Unidade, Model.Unidades)
You can directly supply the Unidades as it is already IEnumerable<SelectListItem>.
P.S.: I guessed the singular of Unidades as I do not speak your langauge, whatever it is. I recommend to ALWAYS use english in source code.
Your model needs a value type property to bind the selected option to. If CodigoEmitenteis typeof int then you model property needs to be
public int SelectedUnidades { get; set; }
and you need to assign the SelectList to another property in your view model or to a ViewBag property
ViewBag.UnidadesList = new SelectList(usuario.UsuarioUnidades, "CodigoEmitente", "NomeFantasia");
Then in the view
#Html.DropDownListFor(x => x.SelectedUnidades, (SelectList)ViewBag.UnidadesList)
I have here a scenario. I want to make an HTTP POST action in the form so here's how I did it.
public class Item
{
public Item()
{
Storages = new HashSet<Storage>();
}
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Storage> Storages { get; set; }
-- remove some lines for brevity --
}
public class Storage
{
public int Id { get; set; }
public string Name { get; set; }
--- remove some lines for brevity --
}
So basically, An Item has many Storage And so I created viewmodel.
public class CreateStockViewModel
{
public string Name { get; set; }
public int StorageId { get; set; }
-- remove some lines for brevity --
}
In my Controller. I have this
[HttpGet]
public ActionResult Create()
{
ViewBag.Storages = _storageService.All
.OrderBy(i => i.Name)
.ToSelectList(s => s.Name, s => s.Id);
return View();
}
In my View:
#model Wsfis.Web.ViewModels.ItemViewModels.CreateStockViewModel
#Html.DropDownList("Storages")
Now my problem is, when I submit the form. And have Quick Watch to the model being passed. It is Null or 0
public ActionResult Create(CreateStockViewModel item)
{
// some code
}
In a nutshell,
When I submit the form all fields are being bind except for the #Html.DropDownList. Where did I missed?
Some additional side note:
They say Views should be strongly typed. Then what should I pass in View then? (A sample code would be great. Thanks)
As for the ToSelectList method I copy this code (I hope it's alright)
Any help would be much appreciated. Thanks.
Your form input has a different name to your property so the default model binder doesn't know how to bind your model.
You could pass in a different name to use to the DropDownList helper, however I prefer to use the strongly typed helpers:
#Html.DropDownListFor(m => m.StorageId, ViewBag.Storages as IEnumerable<SelectListItem>)
Try like this:
ViewBag.StorageId = _storageService.All
.OrderBy(i => i.Name)
.ToSelectList(s => s.Name, s => s.Id);
in view:
#Html.DropDownList("StorageId")
it will now post the drop down list selected value in CreateStockViewModel object's StorageId property.
Can't get all my ViewModel properties back after the postback (After user entered some values on HttpPost)
There are numerous questions here related to losing data or getting nulls after the postback
I tried some of them and played around on my case, I think the scenario is a bit different,
Using a PartialView or Editor Templates(except a list property), Always the returned result properties are null.
In partialView approach always all the properties are null, I think maybe I missed a piece.
In the "custom editor template approach for the type", I'll have just "EnteredNums" List returned. (Maybe because these are what the template have EditorFor for them, but what is the solution here if that's the case?)
Don't know weather if it's important here or not, the application also uses Unity. I don't think it be the problem here.
The HttpGet Passed model is the same as HttpPost : DataVm
The name of the action is also the same : ProcessEnteredData
=================== Controller and action
[HttpPost]
public ActionResult ProcessEnteredData(DataVm vm)
{
if (ModelState.IsValid)
{
foreach (NumType num in vm.EnteredNums)
{
int i1 = num.Score1;
int i2 = num.Score2;
string profTitle = vm.Profile.Title;
Repository.Context.EnteredNums.Add(num);
}
return RedirectToAction("ShowTable");
}
else
{
return View(vm);
}
}
==============
The Partial View of Custom Editor Template are similar :
#model xxxx.NumType
#Html.LabelFor(m => m.TheTitle)
#Html.TextBoxFor(m => m.Score1)
#Html.TextBoxFor(m => m.Score2)
#Html.HiddenFor(m => m.Profile)
// Profile or ProfileId - Just used to see could it bring the property back or not as a test
============
NumType Model
[Key]
public int NumTypeId { get; set; }
[ForeignKey("Profile")]
[Required]
public int ProfileId { get; set; }
public int Score1 { get; set; }
public int Score2 { get; set; }
public int BoxId { get; set; }
public Box Box { get; set; } // something not important here
public virtual Profile Profile { get; set; }
============
The ViewModel
public class DataVm
{
public Profile Profile { get; set; }
public string TheTitle { get; set; }
public List<NumType> EnteredNums { get; set; }
// In the Editor template approach it's the only item with data and others are null
public List<Box> Boxes { get; set; }
}
=========
View for PartialView approach :
#model xxxx.DataVm
#using (Html.BeginForm("ProcessEnteredData", "Profile", FormMethod.Post))
{
#Html.AntiForgeryToken()
Model.EnteredNums = new List<NumType>();
foreach(var box in Model.Boxes)
{
NumType num = new NumType();
num.Profile = Model.Profile;
num.Box = box;
int iCount = Model.EnteredNums.Count;
Model.EnteredNums.Add(num);
#Html.Partial("NumView", Model.EnteredNums[iCount]);
}
<input type="submit" value="Do Process" />
}
===================
View for Editor for approach :
// instead of #Html.Partial :
#Html.EditorFor(m => m.EnteredNums[iCount]);
I have two models as below
public class Category
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int ID { get; set; },
[Required]
public string category { get; set; }
[Required]
public string Desc { get; set; }
}
public class Product
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int ID { get; set; },
public int CatID { get; set; },
[ForeignKey("CatID")]
public virtual Category Category { get; set; },
[Required]
public string Desc { get; set; },
public string DisplayName
{
get
{
return string.format("{0} - {1}",this.Category.category,this.Desc);
}
}
}
This is my Edit Action
public ActionResult Edit(int id)
{
ViewBag.PossibleCategories = categoryRepository.All;
return View(productRepository.Find(id));
}
[HttpPost]
public ActionResult Edit(Product product)
{
if (ModelState.IsValid) //<== This becomes false saying category.desc is required
{
productRepository.InsertOrUpdate(product);
productRepository.Save();
return RedirectToAction("Index");
}
else
{
ViewBag.PossibleCategories = categoryRepository.All;
return View();
}
}
I have a scaffolded a Edit view of product and it shows ID and DisplayName as Readonly. All the other fields a editable.
The edit view also has the product -> category -> category has a read-only text field
#Html.TextBoxFor(model => model.Category.category, new Dictionary<string, object>() { { "readonly", "true" } })
The Post back sends this and tries to create a new category. This is not required. The category link will be carried forward using the product.CatID.
How can i display these types of fields??
When the Edit view Post back the Model state appears as invalid because the product's category's desc is null (product -> category -> desc).
if i comment out the DisplayName property in Product this issue doesn't occur.
From my understanding, this is because the DiaplayName property refers to Category property and the view view doesn't have category.desc field so when the model is created back on the POST action, the desc is not populated. Adding the category.desc field to the view is one way of solving this problem.
Is there any other method to solve this?
Note: This is not the only model i'm having this issue. There are many complex models which have the same problem and to me having these fields also included in the view would make for (1) a very cluttered view (2) the amount of data making the round trip will be high.
Simple Solution
Check for null. Really you should be making this a habit anyway.
public string DisplayName
{
get
{
if(this.Category != null)
{
return string.format("{0} - {1}",this.Category.category,this.Desc);
}
else
{
return String.Empty;
}
}
}
Complex Solution
Instead of directly using your database model in your Views another solution is to create ViewModels. These are models meant specifically for your View. As a simplified example, let's take your Product model and create a ViewModel.
Create a folder for your ViewModels
Create ViewModel files that match your Controller
Create a ViewModel that you will use in your View
Say you have a Store Controller. This would be the file structure you would create.
Models
ViewModels
StoreViewModels.cs
Inside the StoreViewModels you would create a ViewModel called ProductViewModel which you would fill in with information from Product.
public class ProductViewModel
{
public int ID { get; set; }
public string Description { get; set; }
public string DisplayName { get; set; }
public ProductViewModel() { }
public ProductViewModel(Product product)
{
this.ID = product.ID;
this.Description = product.Description;
this.DisplayName = product.DisplayName;
}
}
In your View you reference ProductViewModel instead of Product. On the receiving end you then translate the ViewModel fields back to your Model. Let me know if you have any questions.