Tree view control in teleric - c#

I am working on asp.net mvc 3. I am using the Teleric Controls for the Tree view structure in my application. I want to buil/ construct the Tree view in Controller . and populate it to its view.
Some how which is the best method to prepare the Tree view in Controller and pass to View OR I can use Teleric Tree view object model ,build the tree and pass it to View vai ViewData. But how to convert ViewData to Telerik Treeview Control ?

Html.Telerik().TreeView()
.Name("TreeView")
.BindTo((IEnumerable)ViewData["Customers"], mappings =>
{
mappings.For(binding => binding
.ItemDataBound((item, customer) =>
{
item.Text = customer.ContactName;
item.Expanded = ((string[])ViewData["ExpandedNodes"])
.Contains(item.Text);
})
.Children(customer => customer.Orders));
})
.ClientEvents(events => events
.OnCollapse("updateTreeViewState")
.OnExpand("updateTreeViewState")
Taken from
http://www.telerik.com/support/kb/aspnet-mvc/treeview/persisting-treeview-state-in-cookie.aspx

Related

GridMVC Grid Throws Cast exception?

I'm trying to create a simple Grid using GridMVC
Here is my Controller code.
public ActionResult Index()
{
var approvals = new List<Host_Apps>();
approvals = db.Host_Apps.ToList();
return View(approvals);
}
HTML:
#{
Layout = null;
}
#model List<TrackMiPD.Models.Host_Apps>
#using GridMvc.Html
<h2>Index</h2>
<body>
<div>
#Html.Grid(Model,"Index").Columns(columns =>
{
columns.Add(data => data.ApprovalId).Titled("First Name").SetWidth(110);
columns.Add(data => data.Name).Titled("Last Name").SetWidth(110);
columns.Add(data => data.State).Titled("Age").Sortable(true);
columns.Add(data => data.City).Titled("Birth Date").Sortable(true);
}).WithPaging(20)
</div>
</body>
I tried passing IEnumerable instead of List. I vaguely remember long agao I was working with GridMVC that after setting layout= Null it started working So ive put Layout as Null
Here is the error I get
The model item passed into the dictionary is of type
'GridMvc.Html.HtmlGrid1[TrackMiPD.Models.Host_Apps]', but this
dictionary requires a model item of type
'System.Collections.Generic.List1[TrackMiPD.Models.Host_Apps]'.
Try creating a wrapper class for List of Host_Apps, That would have a list of Host_Apps. Then pass it as model to your view.
During access in view access it as:
#Html.Grid(Model.Host_Apps)
The same problem I had but was able to walk away with this.

Telerik (Kendo) UI for ASP.NET MVC TreeView Issues

I am using MVC 5 and the latest version of Telerik (formerly Kendo) UI for ASP.NET MVC. I am working with hierarchical data. I am attempting to create the TreeView in the _Layout view and populate it with urls or action links.
My current code:
In the _Layout View:
#Html.Partial("_ProductTree")
"_ProductTree" Partial View:
#(Html.Kendo().TreeView().Name("ProductTree")
.DataSource(d => d
.Model(m => m
.Id("ProductId")
.HasChildren("Categories"))
.Read(r => r.Action("_ProductTree", "Home")))
.DataTextField("ProductName"))
Action Method:
[ActionName("_ProductTree")]
public JsonResult GetProductTree()
{
var products = _productBusinessService.GetProducts();
var result = products.Select(p => new
{
p.ProductID,
p.ProductName,
Categories= c.Categories.Any()
}).OrderBy(t => t.ProductName);
return Json(result, JsonRequestBehavior.AllowGet);
}
I am having a number of issues:
When I expand a parent node that has children, the TreeView is hitting the action method and appending the entire tree to the child, instead of just displaying the children.
I need to be able to nest the TreeView two-deep, for example Product > Category > Type.
I am trying to figure out how to aggregate or project the data using LINQ to do a two-deep higherarchy.
I tried turning off LoadOnDemand but that made the TreeView call the action method once for each record in the Product list.
I have tried inserting the TreeView Razor code directly into the _Layout view (not using a partial view). I realize that I may need to move the action method into a base controller class and inherit it in every controller to stop it from appending the list to the parent node. If I cant get this working soon, I may have to either use Kendo UI Professional or an open source alternative.
Some of you may be tempted to say that this question has been answered elsewhere. None of the posts I have found address the issues of populating and displaying nested (more than one deep) hierarchical data using the Telerik TreeView.
There is this post
Nested DataSources and TreeView with kendo ui
But it is for the JavaScript version of the TreeView (not the UI for MVC) version and it has not been answered.
Thank you in advance for your help!
The solution in code:
The _Layout view:
#Html.Partial("_ProductTree")
or
#RenderSection("productTree", false)
then in the content view
#section productTree
{
#Html.Partial("_ProductTree")
}
the _ProductTree partial view
#(Html.Kendo().TreeView().Name("ProductTree")
.DataSource(d => d
.Model(m => m
.Id("Id")
.HasChildren("HasChildren")
.Children("Children"))
.Read(r => r.Action("_ProductTree", "Home")))
.DataTextField("Name"))
I moved the action method to a BaseController abstract class that can be inherited by any controller that needs to display the ProductTree TreeView. The data was pulled from a ProductService and a CategoryService and aggregated using LINQ projection into anonymous objects:
[ActionName("_ProductTree")]
public JsonResult GetProductData()
{
var products = _productBusinessService.GetProducts();
foreach (var product in product)
{
foreach (var category in product.Categories)
{
category.ProductTypes =
_productService.GetProductTypes(category.CategoryId);
}
}
var productTreeData = products.Select(p => new
{
Id = p.ProductId,
Name = p.ProductName,
HasChildren = p.Categories.Any(),
Children = p.Categories.Select(c => new
{
Id = c.CategoryId,
Name = c.CategoryName,
HasChildren = c.ProductTypes.Any(),
Children = c.ProductTypes.Select(t => new
{
Id = t.ProductTypeId,
Name = t.ProductTypeName,
HasChildren = false
}).OrderBy(t => t.Name).ToList()
}).OrderBy(c => c.Name).ToList()
}).OrderBy(p => p.Name).ToList();
return Json(productTreeData, JsonRequestBehavior.AllowGet);
}
The result is a 3-deep, fully populated, sorted Telerik UI for ASP.NET Treeview containing the names and IDs of Product >> Category >> ProductType. Turning LoadOnDemand on or off did not seem to make a difference in this case. It should make a difference when using Bind in a TreeView.
I hope this helps!

ASP Entity Framework Show data from another model

I have a table called TestAnswer and one called question
This is the Create Script created by Entity Framework. I have added some viewbags
ViewBag.TestAnswerQuestion gives me values from the Question table as a select list. I want to show them as normal text e.g. #Html.DisplayFor(model => model.QuestionText) in my razor view for TestAnswer
How can i get the questions to show in my TestAnswer create view
// GET: /TestAnswer/Create
public ActionResult Create()
{
ViewBag.CurrentTestUser = User.Identity.Name;
ViewBag.CurrentTestUserId = User.Identity.GetUserId();
**ViewBag.TestAnswerQuestion = new SelectList(db.Questions.Where(t => t.QuestionID == 2), "QuestionID", "QuestionText");**
ViewBag.TestAnswerTestID = new SelectList(db.Tests, "TestID", "TestUser");
return View();
}
Looks like you need to pass a Model back to your View when returning from your Controller action method.
If I understand you correctly, you want to return a Question entity to your TestAnswer/Create view, perhaps something like:
var model = db.Questions.Find(t.QuestionID);
...
return View(model);
Then you can reference the model from the View template:
#Html.DisplayFor(model => model.QuestionText)
If you want to show a select list of Answers to the Question, your Question entity could have a collection of Answer entities as a public property, then you can simply navigate from a Question to its Answers.
The best advise I can give you is to consider the Entities and their relationships carefully, and model them as POCO classes. Depending on what you are trying to achieve, you may want tot return a View Model, when is a transformation of you entity model to another form that is optimized for the View.

Html.DropDownList - How do you concatenate two different fields from a database table to display as an item in a DDL via MVC?

I'm using ASP.NET MVC- I've got a DropDownList rendered in a user control (ascx page). Here's the code from the ascx page:
<%: Html.DropDownList("climed_pharm_fk",
new SelectList(ViewData["Pharmacies"] as IEnumerable,
"pharm_pk", "pharm_name", Model.climed_pharm_fk))%>
<%= Html.ActionLink("Add New", "Create", "PharmacyMaintenance",
new { Area = "" },
new { target="_blank" })%>
Currently, "pharm_name" shows up in the drop down list. That's great and all, but I am needing "pharm_name" as well as "pharm_phone". I tried stuff like:
<%: Html.DropDownList("climed_pharm_fk",
new SelectList(ViewData["Pharmacies"] as IEnumerable,
"pharm_pk","pharm_name,pharm_phone",Model.climed_pharm_fk))%>
<%= Html.ActionLink("Add New", "Create", "PharmacyMaintenance",
new { Area = "" },
new { target="_blank" })%>
But that didn't work obviously. How does one go about doing this? Thanks in advance!
Try this:
<%: Html.DropDownList(
"climed_pharm_fk",
new SelectList
(
(ViewData["Pharmacies"] as IEnumerable)
.Select
(
a=> new
{
a.pharm_pk,
pharm_name = a.pharm_name + a.pharm_phone
}
),
"pharm_pk",
"pharm_name,pharm_phone",
Model.climed_pharm_fk)
)
%>
Passing the list of objects in viewdata is not a good practice. Views (or partial vies) should not contain logic as well. Also, you seem to be having a Model bound to partial (ascx) view as you are using Model.climed_pharm_fk.
Instead bind the partial view to a ViewModel, which will have the instance of whatever object the current Model is referencing and also, the list of "Pharmacies". Then you can have a property in view model returning the collection of pharmacy names. In the Get part of property you can move the code which collects all the 'pharm_name + pharm_phone' and return as collection of single string.

MVC3 Dynamic List Views

In MVC3, I've been able to rely on Html.DisplayForModel() to generate display's for my data. Using this method, and various templates, I have a single View for displaying several of my Models. What I'm wondering though, is there a way I can get this to work on Lists for my models?
For example, I have a model called Networks. My view to list out multiple networks looks like this:
#model PagedList<Network>
<div id="networkList">
#Html.Grid(Model).Columns(column => {
column.For(x => Html.ActionLink(x.Id.ToString(), "NetworkDetails", new { id = x.Id })).Named("Network ID");
column.For(x => x.Name);
column.For(x => x.Enabled);
}).Attributes(Style => "text-align: center")
#Html.AjaxPager(Model, new PagerOptions() { PageIndexParameterName="page", ShowDisabledPagerItems = false, AlwaysShowFirstLastPageNumber=true },
new AjaxOptions() { UpdateTargetId = "networkList" })
</div>
I'm wondering if it is possible to use a single template when generating lists for my models. I could rely on attributes to know which properties I would like to generate in my list, ie: [ListItem].
The head scratcher for me is, how can I pass a dynamic model to an extension method? If it's of any help, the Html.Grid extension is from MVCContrib. Has anyone else done something similar? It would be great to rely on a template as it would really chop down on the amount of code.
You can achieve it for EditorFor() using the following (it might be similar with your Grid extension method assuming it can take the template name parameter):
// in the main view
#Html.EditorFor(o => o.InvoiceId, "TemplateName", new { Property = "InvoiceId" })
#Html.EditorFor(o => o.Title, "TemplateName", new { Property = "Title" })
// in the template view
#model object
#{ var property = (string)this.ViewData["Property"]; }
Alternatively you can just pass in the name of the template and use this code in the template
var prefix = ViewData.TemplateInfo.HtmlFieldPrefix;
if (prefix.EndsWith("InvoiceId")) { ... }

Categories