Good morning.
I have the following conditions in radiobutton
<td>
#Html.RadioButtonFor(model => model.ImagensSelecionadas, new { Checked = (Model.ImagemCapaSelecionada == item.Value ? "Checked" : "") })
</td>
idea is as follows.
I have an image gallery, Pardo'm doing editing where I can change the cover gallery
and am using the radio button to mark the cover and tried to make the following condition, that I posted up there
that has to compare the value of the Value of ImagemCapaSelecionada item.Value and when the values are equal
must to get the radio button. this condition is within a foreach loop like this:
# foreach (var item in Model.ImagensDaGaleria)
and do not use jQuery, I have to do without Jquery ..
how do I put this condition in the html help radio button??
or what is the best way to do this?
thank you
in this case I am not getting true or false values in the loop if I'm getting this imagemCapaSelecionada receives ai id ImagemCapaSelecionada querai compare the values of Item.value
example
imagemcapaSelecionada | value | status
1 5 not checked
1 1 checked
I think the following should work for you...
#Html.RadioButtonFor(model => model.ImagensSelecionadas, Model.ImagemCapaSelecionada == item.Value)
notice that the second parameter is the object value (i.e. a true or false value)
in the foreach loop...
#foreach(var item in Model.ImagensDaGaleria)
{
#Html.RadioButtonFor(model => model.ImagensSelecionadas, Model.ImagemCapaSelecionada == item.Value)
}
Related
I have a basic enum for gender with value assignemnts 1, 2 for male and female. This code worked for me in previous mvc, but I am getting errors in asp.net core
any pointers as whats wrong ?
thanks
#Html.DropDownListFor(c => c.Gender, Enum.GetValues(typeof(Accounts.i_EF.Accounts.Gender)).Cast<Accounts.i_EF.Accounts.Gender>().Select(c => SelectListItem { Text = c.ToString(), Value = c.ToString() } ))
if you are using MVC6, there is one method GetEnumSelectList which can be used to create the dropdown.
<select asp-for="Gender" asp-items="Html.GetEnumSelectList<Gender>()">
</select>
For your previous code, try to change to
#Html.DropDownListFor(c => c.Gender, Enum.GetValues(typeof(Gender)).Cast<Gender>().Select(c => new SelectListItem { Text = c.ToString(), Value = c.ToString() } ))
Ensure that your project is referencing 'Microsoft.NET.Sdk.Web' and the 'PreserveCompilationContext' property is not set to false.
For this, try to clean and rebuild your project. If not work, restart your VS.
My model contains an array of zip code items (IEnumerable<SelectListItem>).
It also contains an array of selected zip codes (string[]).
In my HTML page, I want to render each selected zip code as a drop down with all the zip code options. My first attempt did not work:
#foreach (var zip in Model.ZipCodes) {
Html.DropDownList( "ZipCodes", Model.ZipCodeOptions )
}
I realized that although that would produce drop downs with the right "name" attribute, it wouldn't know which element of ZipCodes holds the value for that particular box, and might just default to the first one.
My second attempt is what really surprised me. I explicitly set the proper SelectListItem's Selected property to true, and it still rendered a control with nothing selected:
#foreach (var zip in Model.ZipCodes) {
Html.DropDownList( "ZipCodes", Model.ZipCodeOptions.Select( x => (x.Value == zip) ? new SelectListItem() { Value = x.Value, Text = x.Text, Selected = true } : x ) )
}
There, it's returning a new IEnumerable<SelectListitem> that contains all the original items, unless it's the selected item, in which case that element is a new SelectListItem with it's Selected property set to true. That property is not honored at all in the final output.
My last attempt was to try to use an explicit index on the string element I wanted to use as the value:
#{int zipCodeIndex = 0;}
#foreach (var zip in Model.ZipCodes) {
Html.DropDownList( "ZipCodes[" + (zipCodeIndex++) + "]", Model.ZipCodeOptions )
}
That doesn't work either, and probably because the name is no longer "ZipCodes", but "ZipCodes[x]". I also received some kind of read-only-collection error at first and had to change the type of the ZipCodes property from string[] to List<string>.
In a forth attempt, I tried the following:
#for (int zipCodeIndex = 0; zipCodeIndex < Model.ZipCodes.Count; zipCodeIndex++)
{
var zip = Model.ZipCodes[zipCodeIndex];
Html.DropDownListFor( x => x.ZipCodes[zipCodeIndex], Model.ZipCodeOptions )
}
That produces controls with id like "ZipCodes_1_" and names like "ZipCodes[1]", but does not select the right values. If I explicitly set the Selected property of the right item, then this works:
#for (int zipCodeIndex = 0; zipCodeIndex < Model.ZipCodes.Count; zipCodeIndex++)
{
var zip = Model.ZipCodes[zipCodeIndex];
Html.DropDownListFor( x => x.ZipCodes[zipCodeIndex], Model.ZipCodeOptions.Select( x => (x.Value == zip) ? new SelectListItem() { Value = x.Value, Text = x.Text, Selected = true } : x ) )
}
However, the problem with that approach is that if I add a new drop downs in JavaScript and give them all the name "ZipCodes", then those completely override all the explicitly indexed ones, which never make it to the server. It doesn't seem to like mixing the plain "ZipCodes" name with explicit array elements "ZipCodes[1]", even though they map to the same variable when either is used exclusively.
In the U.I., user's can click a button to add a new drop down and pick another zip code. They're all named ZipCodes, so they all get posted to the ZipCodes array. When rendering the fields in the loop above, I expect it to read the value of the property at the given index, but that doesn't work. I've even tried remapping the SelectListItems so that the proper option's "Selected" property is true, but it still renders the control with nothing selected. What is going wrong?
The reason you first 2 snippets do not work is that ZipCodes is a property in your model, and its the value of your property which determines what is selected (not setting the selected value in the SelectList constructor which is ignored). Since the value of ZipCodes is an array of values, not a single value that matches one of the option values, a match is not found and therefore the first option is selected (because something has to be). Note that internally, the helper method generates a new IEnumerable<SelectListItem> based on the one you provided, and sets the selected attribute based on the model value.
The reason you 3rd and 4th snippets do not work, is due to a known limitation of using the DropDownListFor() method, and to make it work, you need to use an EditorTemplate and pass the SelectList to the template using AdditionalViewData, or construct a new SelectList in each iteration of the loop (as per your last attempt). Note that all it needs to be is
for(int i = 0; i < Model.ZipCodes.Length; i++)
{
#Html.DropDownListFor(m => m.ZipCodes[i],
new SelectList(Model.ZipCodeOptions, "Value", "Text", Model.ZipCodes[i]))
}
If you want to use just a common name (without indexers) for each <select> element using the DropDownList() method, then it needs to be a name which does not match a model property, for example
foreach(var item in Model.ZipCodes)
{
#Html.DropDownList("SelectedZipCodes",
new SelectList(Model.ZipCodeOptions, "Value", "Text", item))
}
and then add an additional parameter string[] SelectedZipCodes in you POST method to bind the values.
Alternatively, use the for loop and DropDownListFor() method as above, but include a hidden input for the indexer which allows non-zero based, non consecutive collection items to be submitted to the controller and modify you script to add new items using the technique shown in this answer
Note an example of using the EditorTemplate with AdditionalViewData is shown in this answer
I have converted my MVC3 application to MVC5, I had to change all views to razor. Having a challenge with a select list:
In ASPX view that works I am using the following:
<select id="Profession" name="Profession" style="width: 235px; background-color: #FFFFCC;">
<% List<string> allProfessions = ViewBag.AllProfessions;
string selectedProfession;
if (Model != null && !String.IsNullOrEmpty(Model.Profession))
selectedProfession = Model.Profession;
else
selectedProfession = allProfessions[0];
foreach (var aProfession in allProfessions)
{
string selectedTextMark = aProfession == selectedProfession ? " selected=\"selected\"" : String.Empty;
Response.Write(string.Format("<option value=\"{0}\" {1}>{2}</option>", aProfession, selectedTextMark, aProfession));
}%>
</select>
In Razor I am using:
<select id="Profession" name="Profession" style="width: 235px; background-color: #FFFFCC;">
#{List<string> allProfessions = ViewBag.AllProfessions;
string selectedProfession;}
#{if (Model != null && !String.IsNullOrEmpty(Model.Profession))
{selectedProfession = Model.Profession;}
else {selectedProfession = allProfessions[0];}
}
#foreach (var aProfession in allProfessions)
{
string selectedTextMark = aProfession == selectedProfession ?
"selected=\"selected\"" : String.Empty;
Response.Write(string.Format("<option value=\"{0}\" {1}>{2}</option>",
aProfession, selectedTextMark, aProfession));
}
</select>
The list shows up at the top of the page, I can't figure out where is the problem. Would appreciate your assistance.
Don't create your dropdown manually like that. Just use:
#Html.DropDownListFor(m => m.Profession, ViewBag.AllProfessions, new { style = "..." })
UPDATE
I tried your solution but got this error: Extension method cannot by dynamically dispatched
And, that's why I despise ViewBag. I apologize, as my answer was a little generic. Html.DropDownList requires the list of options parameter to be an IEnumerable<SelectListItem>. Since ViewBag is a dynamic, the types of its members cannot be ascertained, so you must cast explicitly:
(IEnumerable<SelectListItem>)ViewBag.AllProfessions
However, your AllProfessions is a simple array, so that cast won't work when the value gets inserted at run-time, but that can be easily fixed by casting it to a List<string> and then converting the items with a Select:
((List<string>)ViewBag.AllProfessions).Select(m => new SelectListItem { Value = m, Text = m })
There again, you see why dynamics are not that great, as that syntax is rather awful. The way you should be handling this type of stuff is to use your model or, preferably, view model to do what it should do: hold domain logic. Add a property to hold your list of profession choices:
public IEnumerable<SelectListItem> ProfessionChoices { get; set; }
And then, in your controller action, populate this list before rendering the view:
var model = new YourViewModel();
...
model.ProfessionChoices = repository.GetAllProfessions().Select(m => new SelectListItem { Value = m.Name, Text = m.Name });
return View(model);
repository.GetAllProfessions() is shorthand for whatever you're using as the source of your list of professions, and the Name property is shorthand for how you get at the text value of the profession: you'll need to change that appropriately to match your scenario.
Then in your view, you just need to do:
#Html.DropDownListFor(m => m.Profession, Model.ProfessionChoices)
Given that you don't have this infrastructure already set up, it may seem like a lot to do just for a drop down list, and that's a reasonable thing to think. However, working in this way will keep your view lean, make maintenance tons easier, and best of all, keep everything strongly-typed so that if there's an issue, you find out at compile-time instead of run-time.
I believe it's happening because of the Response.Write. Try this:
#Html.Raw(string.Format("<option value=\"{0}\" {1}>{2}</option>", aProfession,
selectedTextMark, aProfession))
MVC 3 VB.NET razor. I have a view that has 4 dropdown boxes in it.. This is for setting up a staff member.. If that staff member is to work certain classes then that class will be set for each day. If he is not then the value needs to stay null. This is a edit view so it may have to be accessed multiple times and still keep the original selectlist values if none changed. The below is what I have right now that is working only on its face. The Old selected value is shown first. However this isnt being returned on the save... The only way that it will save correctly is if I select the value that was set in each box then click save. The next problem is that not all staff members will have classes to work on every one of the 4 days. So how do I set a value to null and keep it that way unless a class Is actually selected..
Dim _staff As confstaff = db.confstaffs.Single(Function(a) a.id = id)
ViewBag.role = _staff.Conf_Role.ToString
ViewBag.confRole = db.conf_roles.ToList
ViewData("tue_Class") = New SelectList(db.courses.ToList.Where(Function(r) r.course_day = "Tuesday").Select(Function(r) r.course_ref), New With {.value = _staff.tue_class})
ViewData("wed_Class") = New SelectList(db.courses.ToList.Where(Function(r) r.course_day = "Wednesday").Select(Function(r) r.course_ref), New With {.value = _staff.wed_class})
ViewData("thur_Class") = New SelectList(db.courses.ToList.Where(Function(r) r.course_day = "Thursday").Select(Function(r) r.course_ref), New With {.value = _staff.thur_class})
ViewData("fri_Class") = New SelectList(db.courses.ToList.Where(Function(r) r.course_day = "Friday").Select(Function(r) r.course_ref), New With {.value = _staff.fri_class})
Return View(_staff)
And the view is:
<label>Tuesday Class</label>
#Html.DropDownList("tue_class", "Select One")
<label class="small_spacing">Wednesday Class</label>
#Html.DropDownList("wed_class", "Select One")
<label class="small_spacing">Thursday Class</label>
#Html.DropDownList("thur_class", "Select One")
<label class="small_spacing">Friday Class</label>
#Html.DropDownList("fri_class", "Select One")
I already expect someone to point out that I should use a view model instead of viewbag but I dont see how a view model would be practical with there being over 100 different courses but I am open for ideas...
Any Ideas???????
if you look at your page source after the page is loaded you will see your top item set from your viewbag value has no value only text so when it is submitted it thinks you are submitting blank. I ran into this before.
What you need to do is to manually create each of your dropdown lists by iterating through the collection and setting the one that matches your viewbag item to selected, that way you can be sure a selected item has a selected value. I have some Razr code around here somewhere. Will update when I find it.
EDIT
<select name="Type1" id="Type1">
<option value=""></option>
#foreach (var name in ViewBag.BackOfficeTypes)
{
if (name == ViewBag.SelectedType1Value)
{
<option value="#name" selected="selected">#name</option>
}
else
{
<option value="#name">#name</option>
}
}
</select>
I have several of these on the same page building from different sets of items. Hope this helps.
EDIT 2
If you want to do it all from codebehind I am not a VB guy but here is a way to do it but you need to change your linq statement to manually create the list items instead of dumping from the toList Method.
var courses = db.getCourses();
IEnumerable<SelectListItem> selectList =
from c in courses
where c.course_day = "Tuesday"
select new SelectListItem
{
Selected = (c.CourseID == selectedCourseID),
Text = c.Name,
Value = c.CourseID.ToString()
};
If you can translate this into the VB equivalent it might solve your issue instead of building them in the Razor end.
All,
I've read through a lot of posts about Checkboxes and ASP.MVC but I'm not that much wiser.
My scenario:
I have a strongly typed View where I pass a collection of summary objects to the view for rendering in a for-each. This summary object contains label data based on a unique id. I also add a checkbox to the row so do so via:
<td>
<%= Html.CheckBox("markedItem", Model.MarkedItem, new { TrackedItemId = Model.Id })%>
</td>
When I perform a POST to get the submitted results my action method takes the strongly typed ViewModel back but the original summary object that I used to create the list is not populated.
Ok, this is annoying, but I can understand why so I'll live with it.
What I then do is to add a new property to my ViewModel called "MarkedItem" which is a string collection.
On postback this marked item is filled with the before and after states if the checkbox has changed but nothing to tell me which key they were for. Just to clarify, if I send this
TrackedItemId = A, Value = false
TrackedItemId = B, Value = true
TrackedItemId = C, Value = false
and set the page to this:
TrackedItemId = A, Value = true
TrackedItemId = B, Value = true
TrackedItemId = C, Value = false
I will get back this:
MarkedItem[0] = true
MarkedItem[1] = false
MarkedItem[2] = true
MarkedItem[3] = false
in other words [0] is the new value and [1] is the old value, [2] and [3] represent values that haven't changed.
My questions are:
Is this right - that I get before and after in this way? Is there any way to only send the latest values?
How can I get hold of the custom attribute (TrackedItemId) that I've added so that I can add meaning to the string array that is returned?
So far I like MVC but it not handling simple stuff like this is really confusing. I'm also a javascript noob so I really hope that isn't the answer as I'd like to return the data in my custom viewmodel.
Please make any explanations/advice simple :)
<p>
<label>
Select project members:</label>
<ul>
<% foreach (var user in this.Model.Users)
{ %>
<li>
<%= this.Html.CheckBox("Member" + user.UserId, this.Model.Project.IsUserInMembers(user.UserId)) %><label
for="Member<%= user.UserId %>" class="inline"><%= user.Name%></label></li>
<% } %></ul>
and in the controller:
// update project members
foreach (var key in collection.Keys)
{
if (key.ToString().StartsWith("Member"))
{
int userId = int.Parse(key.ToString().Replace("Member", ""));
if (collection[key.ToString()].Contains("true"))
this.ProjectRepository.AddMemberToProject(id, userId);
else
this.ProjectRepository.DeleteMemberFromProject(id, userId);
}
}
With thanks to Pino :)
ok, one hack I've come up with - I really hate that I have to do this but I don't see another way round it and I'm sure it will break at some point.
I've already implemented by own ModelBinder to get round some other issues (classes as properties for example) so have extended it to incorporate this code. We use Guid's for all our keys.
If there are any alternatives to the below then please let me know.
Html
<%= Html.CheckBox("markedItem" + Model.Id, false)%>
C#
(GuidLength is a const int = 36, Left and Right are our own string extensions)
//Correct checkbox values - pull all the values back from the context that might be from a checkbox. If we can parse a Guid then we assume
//its a checkbox value and attempt to match up the model. This assumes the model will be expecting a dictionary to receive the key and
//boolean value and deals with several sets of checkboxes in the same page
//TODO: Model Validation - I don't think validation will be fired by this. Need to reapply model validation after properties have been set?
Dictionary<string, Dictionary<Guid, bool>> checkBoxItems = new Dictionary<string, Dictionary<Guid, bool>>();
foreach (var item in bindingContext.ValueProvider.Where(k => k.Key.Length > GuidLength))
{
Regex guidRegEx = new Regex(#"^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$");
if (guidRegEx.IsMatch(item.Key.Right(GuidLength)))
{
Guid entityKey = new Guid(item.Key.Right(GuidLength));
string modelKey = item.Key.Left(item.Key.Length - GuidLength);
Dictionary<Guid, bool> checkedValues = null;
if (!checkBoxItems.TryGetValue(modelKey, out checkedValues))
{
checkedValues = new Dictionary<Guid, bool>();
checkBoxItems.Add(modelKey, checkedValues);
}
//The assumption is that we will always get 1 or 2 values. 1 means the contents have not changed, 2 means the contents have changed
//and, so far, the first position has always contained the latest value
checkedValues.Add(entityKey, Convert.ToBoolean(((string[])item.Value.RawValue).First()));
}
}
foreach (var item in checkBoxItems)
{
PropertyInfo info = model.GetType().GetProperty(item.Key,
BindingFlags.IgnoreCase |
BindingFlags.Public |
BindingFlags.Instance);
info.SetValue(model, item.Value, null);
}