How to Display the following
public ActionResult Index()
{
IEnumerable<int> items = Enumerable.Range(1000, 5);
ViewData["Collection"] = items;
return View();
}
in "View"
<ul>
<% foreach(int i in (IEnumerable)ViewData["Collection"]){ %>
<li>
<% =i.ToString(); }%>
</li>
</ul>
the foreach throws System.Web.HttpCompileException.
You had the closing brace of the foreach's loop in the wrong place. This is what you need:
<ul>
<% foreach (int i in (IEnumerable)ViewData["Collection"]) { %>
<li>
<%= i.ToString() %>
</li>
<% } %>
</ul>
And you also had some other extra punctuation in there as well (such as an extra semicolon).
Related
I have a table called "Tabel_Items" in database with these fields: id, parent, and child:
I want to generate html tags such as these:
<ul>
<li>parent1
<ul>
<li>child1</li>
<li>child2
<ul>
<li>child21</li>
<li>child22</li>
</ul>
</li>
</ul>
</li>
<li>parent2
<ul>
<li>child3</li>
</ul>
</li>
</ul>
I get my items with a LINQ query and pass them to view:
public ActionResult Index()
{
DataClasses1DataContext db = new DataClasses1DataContext();
var items = from i in db.Table_Items
select i;
return View(items);
}
How can I loop through the "items" in view and make a Tree list out of them?
I want a lambda expression to select those rows that have "parentId==null" at first. I test a code like this, but has an error:
#foreach (var i in Model)
{
#Html.DisplayFor(x => i.ItemName.Where(i.ParentId==null));
}
I solved my problem.Thank for me:
<ul>
#foreach (var x in Model.Where(f => f.ParentId == null))
{
<li>
#Html.DisplayFor(f => x.ItemName)
<ul>
#foreach (var y in Model.Where(c => c.ParentId == x.Id))
{
<li>
#Html.DisplayFor(c => y.ItemName)
<ul>
#foreach (var z in Model.Where(c => c.ParentId == y.Id))
{
<li>#Html.DisplayFor(c => z.ItemName)</li>
}
</ul>
</li>
}
</ul>
</li>
}
</ul>
It's a bit complicated so bear with me.
Let's say I've got an example of a controller edit action defined like:
Node nd = _repo.getNode(id);
List<Category> ac = new List<Category>();
ac.AddRange(_repo.getCategories());
SelectList acl = new SelectList(ac, "category_id", "category_name", ac.Where(cat => cat.category_id == nd.category_id).First());
ViewData["category_id"] = acl;
return View(nd);
The view is templated like so:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Myapp.Models.Node>" %>
<% if (ViewData.TemplateInfo.TemplateDepth > 1)
{ %>
<%= ViewData.ModelMetadata.SimpleDisplayText %>
<% }
else
{ %>
<table cellpadding="0" cellspacing="0" border="0">
<% foreach (var prop in ViewData.ModelMetadata.Properties.Where(pm => pm.ShowForEdit && !ViewData.TemplateInfo.Visited(pm)))
{ %>
<% if (prop.HideSurroundingHtml)
{ %>
<%= Html.Editor(prop.PropertyName) %>
<% }
else
{ %>
<tr>
<td>
<div class="editor-label" style="text-align: right;">
<%= prop.IsRequired ? "*" : ""%>
<%= Html.Label(prop.PropertyName)%>
</div>
</td>
<td>
<div class="editor-field">
<% if (ViewData.Keys.Contains(prop.PropertyName))
{
if ((ViewData[prop.PropertyName]).GetType().Name == "SelectList")
{ %>
<%= Html.DropDownList(prop.PropertyName, (SelectList)ViewData[prop.PropertyName])%>
<% }
else
{ %>
<%= Html.Editor(prop.PropertyName)%>
<% } %>
<% }
else
{ %>
<%= Html.Editor(prop.PropertyName)%>
<% } %>
<%= Html.ValidationMessage(prop.PropertyName, "*")%>
</div>
</td>
</tr>
<% } %>
<% } %>
</table>
<% } %>
So, what the template does is display a dropdown list for every property for which ViewData["property_name"] exists.
I've also defined DisplayName metadata attributes for every property of my Node class.
Now, the dropdown lists display fine and are being populated correctly, but:
The first value from a list is always selected, even though the SelectList selected value predicate is fine and does set a proper value (in the debugger at least).
Html.Label in the template returns a proper DisplayName for properties, but when I define a ViewData for them so as to display the dropdown list, the label resets to normal property name (ie. category_id instead of Category).
What gives? Can you think of any "neater" way to accomplish this functionality?
Allright, no one's answering so there's my answer, maybe it comes in handy for someone:
Do not use your property names for ViewData keys! It messes up with the view model, so your views get confused and start to behave strangely.
Actually, best avoid the magic strings mess entirely, but if you insist, just use something like ex.: ViewData[prop.PropertyName+"_list"]. Your views are going to be fine now.
I have three tabs on page and one user control.
I want to RenderPartial on each tab.
<script type="text/javascript">
$(document).ready(function() {
$("#tabs").tabs();
});
</script>
<div id="tabs">
<ul>
<li>Text 1</li>
<li>Text 2</li>
<li>Text 3</li>
</ul>
<div id="tabs-1">
<% Html.RenderPartial("usercontrol", Model); %>
</div>
<div id="tabs-2">
<% Html.RenderPartial("usercontrol", Model); %>
</div>
<div id="tabs-3">
<% Html.RenderPartial("usercontrol", Model); %>
</div>
</div>
how can i get values from different tabs.
If you want to recognize tab, which sent data back, you'll have to pass additional parameter to every partial view:
public class UserControlModel
{
ModelType ParentModel { get; set; }
string ID { get; set; }
}
<div id="tabs-1">
<% Html.RenderPartial("usercontrol", new UserControlModel { ParentModel = Model, ID = "tab1" }); %>
</div>
<div id="tabs-2">
<% Html.RenderPartial("usercontrol", new UserControlModel { ParentModel = Model, ID = "tab2" }); %>
</div>
<div id="tabs-3">
<% Html.RenderPartial("usercontrol", new UserControlModel { ParentModel = Model, ID = "tab3" }); %>
</div>
Then use Html.Hidden to store value in form in partial view and by checking value in post method, you can recognize tab.
Your partial view will have to inherit from ViewUserControl<TaskEditModel>:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<TaskEditModel>" %>
I render a list of items like:
<ul>
<li>Something 1</li>
<li>Something 2</li>
<li>Something 3</li>
<li>Something 4</li>
<li>Something 5</li>
</ul>
Depending on the route I want to add a class to one of the <li> tags so that I can highlight.
Maybe something like:
<ul>
<% if (this.Context.Request.RawUrl.Contains(something1Var)) { %>
<li class="highlight">
<% } else { <%>
<li>
<% } %>
Something 1</li>
<% if (this.Context.Request.RawUrl.Contains(something2Var)) { %>
<li class="highlight">
<% } else { <%>
<li>
<% } %>
Something 2</li>
<% if (this.Context.Request.RawUrl.Contains(something3Var)) { %>
<li class="highlight">
<% } else { <%>
<li>
<% } %>
Something 3</li>
<% if (this.Context.Request.RawUrl.Contains(something3Var)) { %>
<li class="highlight">
<% } else { <%>
<li>
<% } %>
Something 4</li>
<% if (this.Context.Request.RawUrl.Contains(something5Var)) { %>
<li class="highlight">
<% } else { <%>
<li>
<% } %>
Something 5</li>
</ul>
It does work but it seems a bit verbose. Can anyone suggest a better method of doing this sort of thing?
I'd argue that this kind of logic is better isolated in the controller. Consider making a lightweight class to represent your menu items, like this:
public class MenuLinkItem {
public string Text { get; set; }
public bool Highlight { get; set; }
}
Then in your controller method, build a list of these, set the CSS class on the highlighted element, and pass the result to the view via the ViewData:
public class MyController : Controller {
private MenuLinkItem MakeMenuLinkItem(string text, string urlFragment) {
return (new MenuLinkItem() {
Text = text,
Highlight = (this.Context.Request.RawUrl.Contains(urlFragment))
}
}
private IList<MenuLinkItem> GetMenuLinkItems() {
var items = new List<MenuLinkItem>();
items.Add(MakeMenuLinkItem("Something 1", something1var));
items.Add(MakeMenuLinkItem("Something 2", something2var));
items.Add(MakeMenuLinkItem("Something 3", something3var));
items.Add(MakeMenuLinkItem("Something 4", something4var));
items.Add(MakeMenuLinkItem("Something 5", something5var));
return(items);
}
public ActionResult Index() {
ViewData["menuLinkItems"] = GetMenuLinkItems();
/* other controller logic here */
return(View());
}
}
Then, in your actual view code, you render your menu like this:
<ul>
<% foreach(var item in (IList<LinkMenuItem>)ViewData["menuLinkItems"])) { %>
<li <%= item.Highlight ? "class=\"highlight\"" : ""%>><%=item.Text%></li>
<% } %>
</ul>
The controller's making the decisions about which links are highlighted, and the view is converting those decisions into an HTML/CSS representation that makes sense to your users.
Why does this code produce these results?
CODE:
<%# Control Language="C#"
Inherits="System.Web.Mvc.ViewUserControl< RoomsAlive.ViewModels.ProductCatalogViewModel >" %>
<div id="product_nav">
<ul>
<%--ADD PREV TAB--%>
<% if (Model.HasPreviousPage) %>
<% { %>
<li><%= Html.RouteLink("<<", "CatalogMenu", new { controller = "Catalog", action = "Index", style = (Model.GroupName), position = (Model.PageIndex - 1) })%></li>
<% } %>
<%--LOOP HERE--%>
<% foreach (RoomsAlive.Models.ProductMenuView myFPV in Model.ProductMenu)
{ %>
<li><%= Html.RouteLink(myFPV.Name, "CatalogMenu", new { controller = "Catalog", action = "Index", group = Model.GroupName })%></li>
<% } %>
<%--ADD NEXT TAB--%>
<% if (Model.HasNextPage) %>
<% { %>
<li><%= Html.RouteLink(">>", "CatalogMenu", new { controller = "Catalog", action = "Index", position = (Model.PageIndex + 1) })%></li>
<% } %>
</ul>
</div>
RESULTS:
<div id="product_nav">
<ul>
<li>LifeStyle</li>
<li>Rooms</li>
</ul>
</div>
BTW: If I use the <% %> form instead of the <%= %> form it produces this:
<div id="product_nav">
<ul>
<li></li>
<li></li>
</ul>
</div>
Why are you specifying the controller and action in the object part of the Actionlink?
Wouldn't it be best to do it this way:
<%= Html.RouteLink("<<", "Index", "Catalog", new { style = Model.GroupName, position = (Model.PageIndex - 1) }, null)%>
The second property of ActionLink is always the desired action name, and you are setting it to CatalogMenu, but then you're then creating an object that says "Index". For this reason (as I have no idea what you want 'CatalogMenu' to be), I have taken it out.
Please also note the null after the routeValues object. This is because the 10 constructors for Html.ActionLink, this one fits the best:
ActionLink(LinkText, ActionName, ControllerName, RouteValues, HtmlAttributes)
Also, if you use <% ... %> instead of <%= ... %>, then it will not output the link. This is because the ActionLink returns a string. All the '=' does in the tag is effectively a Response.Write.
Hope this explains it.