I have a page that contains a list a companies. Each company is appart of a group, like such:
But here's the catch, groups can be disabled, if they are, that would not change the display of the list but it does have an impact on my edition page.
As you can see, there is a DropDownList containing my groups. But if a group is disabled it does not show up on the list because I retrieve said list like such:
public IEnumerable<SelectListItem> ListGroupEnabled()
{
List<SelectListItem> X = _entities.Groups.Where(p => p.IsEnabled).ToList().Select(c => new SelectListItem { Value = c.GroupId.ToString(), Text = c.Name }).ToList();
return X;
}
But here's what I wish to achieve:
If I were to edit a company that was appart of a disabled group, I still want that group (and only that group) to appear in the DDList among enabled groups.
This is for the sake of logic, it wouldn't make sense to simply not have the group a company is appart off in its list.
How may I change the code I showed up above in order to keep the group the company is appart off in my list?
Hello SelectListItem have Properties such as Disabled you can set it before send. referrence
fix your code at below.
public IEnumerable<SelectListItem> ListGroupEnabled()
{
List<SelectListItem> X = _entities.Groups.Select(c => new SelectListItem { Value = c.GroupId.ToString(), Text = c.Name , Disabled = c.IsEnabled }).ToList();
return X;
}
You need to pass in the current group id and include that in your where clause:
public IEnumerable<SelectListItem> ListGroupEnabled(int? currentGroupId = null)
{
return _entities.Groups.Where(
p =>
p.IsEnabled ||
(currentGroupId.HasValue && p.GroupId == currentGroupId.Value)
).Select(c => new SelectListItem { Value = c.GroupId.ToString(), Text = c.Name }).ToList();
}
You also don't need to call ToList before selecting. That actually makes the query less optimized as without that, Entity Framework can just select the columns it needs (GroupId and Name).
Related
In table I have 4 Columns GroupName, Display, Value and ID
How can I just show a specific data in display. I only want to show some of the groupNames Data
for example I only want to show Groupname = company and display = Forbes
Here's my linq
sample = (from c in smsDashboardDBContext.CodeDefinitions
orderby c.Display ascending
select new CodeDefinitionDTO
{
GroupName = c.GroupName,
Display = c.Display,
Value = c.Value,
Id = c.Id
}).ToList();
You can add a where statement in the query.
where c.GroupName == "company" && c.Display == "Forbes"
I only want to show some of the groupNames Data for example I only want to show Groupname = company and display = Forbes
Before the ToList, use a Where to keep only those items that you want to show:
var company = ...
var forbes = ...
var result = smsDashboardDBContext.CodeDefinitions
.OrderBy(codeDefinition => codeDefintion.Display)
.Select(codeDefinition => new CodeDefinitionDTO
{
Id = codeDefinition.Id,
GroupName = codeDefinition.GroupName,
Display = codeDefinition.Display,
Value = codeDefinition.Value,
})
.Where(codeDefinition => codeDefition.GroupName == company
&& codeDefintion.Display == forbes);
In words:
Order all codeDefinitions that are in the table of CodeDefintions by ascending value of property codeDefintion.Display.
From every codeDefinition in this ordered sequence make one new CodeDefinitionDTO with the following properties filled: Id, GroupName, Display, Value
Frome every codeDefintion in this sequence of CodeDefinitionDTOs, keep only those codeDefinitions that have a value for property GroupName that equals company and a value for property Display that equals forbes.
There is room for improvement!
Suppose your table has one million elements, and after the Where, only five elements are left. Then you will have sorted almost one million elements for nothing. Consider to first do the Where, then the Order and finally a Select.
In LINQ, try to do aWhere as soon as possible: all following statements will have to work on less items
In LINQ, try to do a Select as late as possible, preferrably just before the ToList / FirstOrDefault / ... This way the Select has to be done for as few elements as possible
So first the Where, then the OrderBy, then the Select, and finally the ToList / FirstOrDefault, etc:
var result = smsDashboardDBContext.CodeDefinitions
.Where(codeDefinition => ...);
.OrderBy(codeDefinition => codeDefintion.Display)
.Select(codeDefinition => new CodeDefinitionDTO
{
...
});
Here is an example of what some locations look like in my database:
ID, DepartmentId, LocationName
8,2,Main Warehouse
12,2, Filter Cellar
When I use the following code, it grabs the entire query and puts it as the value for my HTML dropdown list.
public ActionResult GetLocations(int id)
{
List<SelectListItem> locations = new List<SelectListItem>();
//based on the input coming to this method ( product id)
var incident = new AccidentSupervisorViewModel();
incident.Locations = DB.Locations.ToList().Select(i => new SelectListItem
{
Text = i.LocationName,
Value = i.DepartmentId.ToString()
}
).Where(i => i.Value == id.ToString());
var departmentId = from loc in DB.Locations where loc.DepartmentId == id select loc.DepartmentId;
for (var x = 0; x < incident.Locations.Count(); x++) {
locations.Add(new SelectListItem {
Text = incident.Locations.ElementAt(x).Text,
Value = departmentId.ToString()
});
}
return Json(locations,JsonRequestBehavior.AllowGet);
}
This is most likely happening because I have a syntax error, but I haven't used linq much for queries so any help is appreciated.
It appears you've not 'done' anything with the IQueryable<T> that is generated by Linq. Linq generates the query but doesn't do anything with it until the IQueryable<T> or other IEnumerable is iterated over. See Deferred Execution and Classification of Standard Query Operators by Manner of Execution.
In your case, since you're looking for a single value, you'll need to pop in the following line after you first declare departmentId:
var department = departmentId.FirstOrDefault();
This will pop out the first or default value from the IQueryable<T> you made.
I have the following code populate for dropdownlist. Is there any way i can add an item called "Select Value" in the following
private void PopulateCustStatus()
{
ViewData["custStatus"] = new HEntities().COptions
.Select(e => new ConfOptModel
{
OptID = e.OptID,
OptName = e.OptName,
ConfigTypeID = e.ConfigTypeID
})
.Where(e => e.ConfigTypeID == 2)
.OrderBy(e => e.OpName);
}
The problem with what you're trying to do, I think, is that your "no selection" option (e.g. "Select Value") doesn't have the same "shape" as the model being created in PopulateCustStatus().
You probably want to use an IEnumerable<SelectListItem>:-
var selectList =
new HEntities().COptions
.Where(e => e.ConfigTypeID == 2)
.OrderBy(e => e.OpName)
.Select(e => new SelectListItem()
{
Text = e.OptName,
Value = e.OptID,
Selected = false
});
This gives you a little bit more flexibility. Then you can insert a "Select value" item on top like:-
var noSelection = new SelectListItem()
{
Text = "Select value",
Value = 0,
Selected = true
};
ViewData["selectedCustStatus"] =
new[] { noSelection }.Concat(selectList);
Note: If you want to preserve a previously selected value, you'll have to pass it into the function and make sure the matching SelectListItem gets its Selected property set to true.
Hope this helps!
You're returning a list of ConfOptModel object so unless there's a property to indicate a "selected" value then you can't.
If I don't create models specifically for the View (i.e. use domain objects as the "Model" instead of a "ViewModel") I usually add the selected item to the view state :
ViewData["selectedCustStatus"] = selectedID;
And then use that value when creating the DropDownList in the markup.
Another option is to return a list of SelectListItem objects instead of domain (ConfOptModel) objects. That puts a little of the view logic in the controller so use whichever you're more comfortable with.
I have the following class:
public static IEnumerable<SelectListItem> GetDatastore()
{
return new[]
{
new SelectListItem { Value = "DEV", Text = "Development" },
new SelectListItem { Value = "DC1", Text = "Production" },
};
}
What I need is to execute a function to return the Datastore name. Something like
var abc = getDatastoreName("DEV").
Do I need to do this with LINQ or is there some easy way? How could I code this function?
public static string getDatastoreName(string name)
{
var result = GetDatastore().SingleOrDefault(s => s.Value == name);
if (result != null)
{
return result.Text;
}
throw /* some exception */
}
The Value property of SelectListItem is usually unique and hence I have SingleOrDefault(). If that is not the case then you can switch to using FirstOrDefault().
A simple LINQ query can find the value you want:
var val = dataStore.Where(d => d.Value == "DEV").FirstOrDefault();
//`val` will be the item, or null if the item doesn't exist in the list
But this is only good for small lists of items -- it's worst-case Order N.
If you wanted a better search, you could store your data as a dictionary with the keys being used as item values, for example, and databind against that rather than against a list of SelectListItems. That would allow you to look up the values constant time.
For most cases, simple LINQ will be fine. If you have a big list, or you're querying that list frequently... consider an alternative.
Maybe you are searching something like this
i have "Details" page that works perfectly:
#Html.DisplayFor(model => model.Code1dItems.SingleOrDefault(m => m.Value == model.Code1Id.ToString()).Text, new { #class = "Width100P" })
In my model :
Code1Id is int value and it comes from database Code1dItems is IEnumerable
value like 'GetDatastore' and returns ID->string, ID value matches with Code1d and Text->string
depending on your question you should use :
string abc = GetDatastore.SingleOrDefault(m => m.Value == "DEV").Text
if you get value from database you should use my code example.
I'm having problems with getting selected items in a select-list.
Product product = _pr.GetProducts().ByProductID(productID).First();
product.Categories.Load();
ICollection<Category> allCategories = _cr.GetCategories().ToList();
List<SelectListItem> Categories = (from category in allCategories
select
new SelectListItem
{
Selected = product.Categories.Contains(category),
Value = category.CategoryID.ToString(),
Text = category.Categoryname
}).ToList();
Categories return 4 items, and selected is false on all....... If I hover "product.Categories" there are 3 items there, which is correct.... but somehow it doesnt get set to true.
What might be wrong?
/M
The overload of Contains() that you're using is going to use the default object comparison, which will only match the exact same instance unless you've overridden Equals() and GetHashCode(). One option is to create a custom CategoryEqualityComparer and pass it to this overload of Contains(). Or, you could just join the categories on ID:
Product product = _pr.GetProducts().ByProductID(productID).First();
product.Categories.Load();
ICollection<Category> allCategories = _cr.GetCategories().ToList();
List<SelectListItem> Categories = (
from category in allCategories
join pc in product.Categories
on category.CategoryID equals pc.CategoryID into j
select
new SelectListItem
{
Selected = j.Any(),
Value = category.CategoryID.ToString(),
Text = category.Categoryname
}).ToList();
I see that you set 'allCategories' to a _cr.GetCategories collection - are you sure the product contains categories from that collection? It looks like your Categories field doesn't contain any of the product categories. Can you post what is in each collection?