ListItem not highlighted even though selected is true - c#

I am creating a list of months for a list box. The controller captures the selected months and stores them in session for if the user navigates away from the page then returns.
Here is the controller:
public ActionResult Index(int[] Months)
{
if (Session["Months"] == null || Months!= null)
Session["Months"] = Months;
else if (Months== null)
Months= Session["Months"] as int[];
IList<SelectListItem> MonthsList = utility.GetMonths().OrderBy(r => r.Name)
.Select(r => new SelectListItem
{
Text = r.Name,
Value = r.Id.ToString(),
Selected = Months == null ? false : Months.Contains(r.Id)
}).ToList();
var model = new DataModel
{
SelectList = MonthsList,
Data = GetDataByMonths(Months)
};
return (model);
}
Here is the view:
#Html.ListBox("Months", Model.SelectList)
When the user selects items from the ListBox they are highlighted even after the form has been submitted. However when the user navigates away then returns the SelectListItems are correctly labeled as Selected = true but the DOM does not show this.
Any ideas on why this only doesnt work when session is used?
EDIT:
Tried:
#Html.ListBox("Months", new MultiSelectList(Model.Months, "Value", "Text", Model.SelectedMonths), new { size = 8 })
While debugging, the variables show the correct values, they are just not correctly highlighted in the DOM.

Did you try the SelectList type or MultiSelectList rather than an IEnumerable<SelectListItem>? I don't know of any other way to tell the ListBox which property is the value and which is the text.
i.e.
MultiSelectList list = new MultiSelectList(monthsList, "Value", "Text");
and return the list object?

I ended up creating the list box in html rather than using the #html.listbox()
<select name="Months" id="Months" multiple="multiple" size="8">
#foreach (var a in Model.Months)
{
<option value="#a.Value" #(a.Selected.ToString() == "True" ? "selected='selected'" : "")>#a.Text</option>
}
</select>

Related

MVC how to change dropdownlist item names

Been googling for a while, but I can't seem to get any closer.
I'm using MVC with an EF Database structure.
I want the dropdownlist items in the View to show up with different names than what they come up with.
Right now, the lambda query returns a list().
I want each item to get a string name depending on their current name. Eventually, the selected field needs to be used in another lambda as the Byte that it was.
Edit
//view
<p>
#using (Html.BeginForm("Index", "Home", FormMethod.Get))
{
<p>
#Html.DropDownList("vbType", (SelectList)ViewBag.Type, "" , new { onchange = "form.submit();" })
....
//controller
var typeLst = new List<byte>();
var typeQry = from t in db.model1
orderby t.TYPE
select t.TYPE;
typeLst.AddRange(typeQry.Distinct());
ViewBag.vbType = new SelectList(typeLst);
....
Thanks in advance.
You can create a SelectListItem to display in your dropdownlist.
Example:
#Html.DropDownListFor(model => model.YearStartedToPay,
Enumerable.Range(DateTime.Today.Year - 60, 61).OrderByDescending(x => int.Parse(x.ToString())).Select(n => new SelectListItem() { Text = n.ToString(), Value = n.ToString(), Selected = false }).ToList<SelectListItem>(),....)
In this case, I'm creating an Enumerable, that will be your list returned from EF, ordering and selecting as a SelectListItem.
You need to make use of dropdownlist's Value property. Make your list a type of SelectListItem.
Assign Text= [Your Required Text] and Value = [Current Name]

How to keep the selected value from the dropdown when the page is changed?

I am working on a project in C# (using mvc) and I had to make a dropdown filter in my view with only two choices: Yes and No.
Here is the code that populates the dropdown:
Service method:
public List<SelectListItem> cancelledForDp()
{
List<SelectListItem> cancelled = new List<SelectListItem>();
var data = new[]
{
new SelectListItem { Value = "1",Text = "Yes" },
new SelectListItem { Value = "NULL",Text = "No" }
};
cancelled = data.ToList();
return cancelled;
}
Controller:
ViewBag.cancelledDp = utilService.cancelledForDp();
View:
#Html.DropDownList("cancelled", (IEnumerable<SelectListItem>)ViewBag.cancelledDp, new { id = "chosenCancelled" })
The values in the column in the database table are: "1" and NULL (I mean the values connected with the filter). My filter works correctly.
When I filter with the value No, a few pages are returned. When I go to a different page than the first (2 or more), the value of the dropdown is not kept. It should be No, but instead it is Yes.
I searched for answers connected with my problem here, but did not find anything appropriate.
I guessed the problem is connected with NULL value so I tried this:
In the service:
public List<SelectListItem> cancelledForDp()
{
List<SelectListItem> cancelled = new List<SelectListItem>();
var data = new[]
{
new SelectListItem { Value = "1",Text = "Yes" },
new SelectListItem { Value = "2",Text = "No" }
};
cancelled = data.ToList();
return cancelled;
}
Controller:
if(cancelled == 2)
{
cancelled = null;
}
But I got the same results. When I selected No in the filter and went to the second page, Yes was in the dropdown instead of No.
I debugged and found that the value of the parameter cancelled of the method in the controller is null when I went to the second page.
How to keep the selected value from the dropdown when the page is changed?
Your code is generating <option> elements with values of "1" and "NULL". The text "NULL" is not the same as null value (which is recognized by an empty string - i.e. it has no value). If the value of property cancelled is null then the first option will be selected because there is no option element with an empty value (and because something has to be selected)
In order for it to be selected, your element needs to be <option value="">No</option> which you can generate using either
public IEnumerable<SelectListItem> cancelledForDp()
{
return new List<SelectListItem>()
{
new SelectListItem { Value = "1",Text = "Yes" },
new SelectListItem { Value = "",Text = "No" }
};
}
or
public IEnumerable<SelectListItem> cancelledForDp()
{
return new List<SelectListItem>()
{
new SelectListItem { Value = "1", Text = "Yes" },
};
}
and in the view use
#Html.DropDownList("cancelled", (IEnumerable<SelectListItem>)ViewBag.cancelledDp, "No", new { id = "chosenCancelled" })
where the 3rd parameter creates the labelOption with a null value.
As a side note, if your field can only store 2 values, then you should be using as database BIT field so that the property is
public bool IsCancelled { get; set; }
not int? cancelled (or is it string cancelled?)
and simply use
#Html.CheckBoxFor(m => m.IsCancelled)
in the view. I also recommend you always use the strongly typed ***For() methods.

Choosing selected item for dropdown list in action

I have a page which allows users to change their privacy settings for:
Their posted recipes
Their profile
Their posted lists
I am trying to form my code so that when the users load this page, the dropdown lists which they use to select their privacy settings display their current setting, so if they had their recipe privacy set to "Registered users", whenever they load the privacy settings page I want it to start off with "Registered users" selected.
Initially I create a list of SelectListItem instances called PrivacySettings
List<SelectListItem> PrivacySettings = new List<SelectListItem>();
PrivacySettings.Add(
new SelectListItem
{
Text="Anybody",
Value = "0"
});
PrivacySettings.Add(
new SelectListItem
{
Text = "Registered users",
Value = "1"
});
PrivacySettings.Add(
new SelectListItem
{
Text = "Only me",
Value = "2"
});
Then I create three separate SelectList instances. Here is the part where I am assigning the selected value for each of the lists to the first value which matches the user's saved setting.
SelectList RecipePrivacyList = new SelectList(
PrivacySettings,
"Value",
"Text",
PrivacySettings.First(x => x.Value == LoggedInUser.RecipePrivacy.ToString()));
SelectList ProfilePrivacyList = new SelectList(
PrivacySettings,
"Value",
"Text",
PrivacySettings.First(x => x.Value == LoggedInUserProfile.Privacy.ToString()));
SelectList ListPrivacyList = new SelectList(
PrivacySettings,
"Value",
"Text",
PrivacySettings.First(x => x.Value == LoggedInUser.ListPrivacy.ToString()));
Then I assign each of these to separate ViewData keys
ViewData["RecipePrivacy"] = RecipePrivacyList;
ViewData["ProfilePrivacy"] = ProfilePrivacyList;
ViewData["ListPrivacy"] = ListPrivacyList;
In my view I retrieve these and store them into variables
var ProfilePrivacy = (SelectList)ViewBag.ProfilePrivacy;
var RecipePrivacy = (SelectList)ViewBag.RecipePrivacy;
var ListPrivacy = (SelectList)ViewBag.ListPrivacy;
And finally I use the Html.DropDownList() helper method to create the lists using the aforementioned variables
#Html.DropDownList("profile-privacy", ProfilePrivacy, new { #class = "profile-privacy" })
When the view is loaded, the first value ("Anyone" or value 0) is selected regardless of the user's actual setting.
you have to set the selected item of the SelectList like that:
SelectList ListPrivacyList = new SelectList(
PrivacySettings,
"Value",
"Text",
PrivacySettings.First(x => x.Value == LoggedInUser.ListPrivacy.ToString()).Value);

DropDownListFor() not setting to the model value

I'm looping over my model but the value that is coming from the model isn't what's showing in the drop down list as the selected item. Instead the list is always just showing the first entry.
#Html.DropDownListFor(modelItem => item.RecordType, Model.RecordTypes, new { id="recordType_" + item.TransactionID })
item.RecordType has a value of 5 from the model (I print it out so I know it's that value). However the drop down shows "Initial" (which is a value of 4) instead of "Firm" (which is the valu eof 5 which is what our model item value is). The list in the source is defined as:
<select data-val="true" data-val-number="The field RecordType must be a number." id="recordType_63" name="item.RecordType">
<option value="4">Initial</option>
<option value="5">Firm</option>
<option value="6">Announced</option>
<option value="7">N/A</option>
</select>
How do I set the drop down to be what the model value is?
public IEnumerable<SelectListItem> RecordTypes
{
//get { return new SelectListItem(recordTypes, "RECORD_TYPE_ID", "RECORD_TYPE"); }
get
{
return (from r in recordTypes
select new SelectListItem { Text = r.RECORD_TYPE, Value = r.RECORD_TYPE_ID.ToString() });
}
}
You can do that by creating a SelectList in your Html.DropDownListFor like:
#Html.DropDownListFor(modelItem => item.RecordType, new SelectList(Model.RecordTypes, item.RecordType), new { id="recordType_" + item.TransactionID });
This passes your IEnumerable<SelectListItem> into the constructor along with a parameter, in this case item.RecordType, letting it know which item to select.
EDIT: In response to comment
You could use the overload of SelectList which allows you to specify the DataTextField and DataValueField in your case these would be Text and Value respectively.
or
Re-work your Model.RecordTypes to return a SelectList and do the necessary work in there, you could use a method and pass in the value to select. Something like:
public SelectList RecordTypes(object selectedValue)
{
return new SelectList(recordTypes, "RECORD_TYPE", "RECORD_TYPE_ID", selectedValue);
}
Hope that helps.
When you are assembling your RecordTypes SelectListItem collection, make sure to set Selected = true for the currently selected item-- it will not set it for you.
Assuming the RecordType variable on your view model mates up against the RECORD_TYPE_ID variable of your data set, you can update creation of variable to:
from r in recordTypes
select new SelectListItem { Text = r.RECORD_TYPE, Value = r.RECORD_TYPE_ID.ToString(), Selected = r.RECORD_TYPE_ID == this.RecordType }
If you are re-using the RecordTypes variable across multiple dropdowns on the view, you're going to have to change your approach and create the IEnumerable<SelectListItem> for each dropdown. Suchas:
#Html.DropDownListFor(modelItem => item.RecordType, RecordTypes.Select(rt => new SelectListItem { Text = rt.Text, Value = rt.Value, Selected = rt.Value == item.RecordType}))

trying to set a dropdown in MVC

I almost have this solved but need a little push.
Here's what I have:
In the database I have a field called active that is a bit field (True/False)
I have placed a dropdownlist on the View form like this:
<%= Html.DropDownList("lstActive", new SelectList((IEnumerable)ViewData["ActiveList"])) %>
In my controller, I simply have this code to generate the True/False in the dropdown:
List<string> activeList = new List<string>();
activeList.Add("True");
activeList.Add("False");
ViewData["ActiveList"] = new SelectList(activeList);
I want to bind to the field in the database called active and select it in the dropdown. When I view it like this I get this:
alt text http://rjmueller.net/sitesimages/temp/dropdown.gif
So the questions are these:
Obviously I am not pointing to the Value and Text property but what is that in this case?
And how do I select the value that is in the database?
Any help would be appreciated.
First, this is probably better suited to radio buttons, not a select. Second, you really ought to have a view model with a property that is an IEnumerable<SelectListItem> that supplies the values for the select. You can construct that directly in the model.
var model = new ViewModel();
model.ActiveList = new List<SelectListItem>
{
new SelectListItem { Text = "Yes", Value = "true" },
new SelectListITem { Text = "No", Value = "false" }
};
model.Active = false; // this will be the default
return View( model );
Then in your view (strongly-typed to your view model type):
<%= Html.DropDownListFor( m => m.Active, Model.ActiveList ) %>
Using radio buttons, you can omit the list (since there are only the two choices).
<%= Html.RadioButtonFor( m => m.Active, true ) %> Yes
<%= Html.RadioButtonFor( m => m.Active, false ) %> No
Here's a couple of suggestions for you.
First, your DropdownList's name is "lstActive", so if you create a List<SelectListItem> called "lstActive" and pass that back in ViewData, you don't have to do anything fancy with boxing. Then your declaration looks like:
<%= Html.DropDownList("lstActive") %>
easy, huh?
In your controller, you create your List. Here's a method I've used:
private List<SelectListItem> GetAccounts(User user)
{
var items = new List<SelectListItem>();
foreach (Account account in user.Accounts)
{
var item = new SelectListItem();
item.Text = account.Name;
item.Value = account.AccountId.ToString();
if (ActiveAccount == account.AccountId)
item.Selected = true;
items.Add(item);
}
return items;
}
Basically, what I'm trying to point out is that you can set a property on your SelectListItem that you wish to be displayed as selected. Here, I'm using my own code for Users and Accounts, but you'd substitute your own data based on your db query.
First thing, you're recreating a SelectList the ViewData data, you should declare the DropBox as follows:
<%= Html.DropDownList("lstActive", ViewData["ActiveList"]) %>
Second, instead of creating a generic list on the controller, create a SelectList and add SelectListItems to it:
var activeList = new SelectList
{
new SelectListItem { Text = "True", Value = true },
new SelectListItem { Text = "False", Value = false }
};
ViewData["ActiveList"] = activeList;
This should clarify:
Drop-down Lists and ASP.NET MVC
For each select list element you need to set the Text and Value properties...
One solution could be as follows:
Model:
public class NameValue
{
public string Name { get; set; }
public string Value { get; set; }
}
Controller:
string currentActiveValue = myDB.active.ToString();
List<NameValue> yesNoList = new List<NameValue>
{
new NameValue { Name = "Yes", Value = "True" },
new NameValue { Name = "No", Value = "False" }
};
SelectList myActiveList = new SelectList(yesNoList, "Name", "Value", currentActiveValue);
ViewData["ActiveList"] = myActiveList;
View:
div>Is Active: <%= Html.DropDownList("ActiveList") %></div>

Categories

Resources