I have a list of parent objects as the source of the Parent Webgrid. Parent object has an int ID, string name, and List of Children. Child object has int ID and string Description. Each parent has from 0 to many children.
#ParentGrid.GetHtml(htmlAttributes: new { #id = "gridParent" }, tableStyle: "table2",
columns: new[]
{
//columns for parent items here refer to item.ID, item.name, and are ommitted for brevity
MeetingDetailsGrid.Column(header: "Descriptions",
format: (item) => {
WebGrid subGrid = new WebGrid(source: item.Descriptions);// The source is parent.ListofChildren
return subGrid.GetHtml(htmlAttributes: displayHeader: false, tableStyle: "table3", columns: new[]
{
subGrid.Column("ID","ID"),
subGrid.Column("Description","Description", format: #<div><span>
#Html.TextBox("desc_"+(int)item.ID,(string)item.Description)</span></div>)
//Use of item here is not allowed because its used in the enclosing scope
}
The child grid is given the source of item.Descriptions, so item is the parent object in the ChildGrid.GetHtml() call. Then within the column definitions I get an exception using item to refer to the child items. The examples I see for nested grids have not shown how to refer to the child items, but instead just use the field names which I assume automates the binding, but is then not editable. If I change the (item) => to something else like (desc) => then I cant provide the source to the child grid as the parent objects list of children.
Related
Im passing a list from controller to view,my controller is:
var myreslt = (from d in DB.MasterDatas
select new
{
categoryName = d.Country,
subCategories = d.City
}).ToList();
in the view im using kendo and want to show the above data in a tree view using the following code,but it only shows the name of the category(countries)and not the subset
var inline = new kendo.data.HierarchicalDataSource({
data: result,
schema: {
model: {
children: "subCategories"
}
}
});
$("#treeview-right").kendoTreeView({
dataSource: inline,
});
I am trying to use a Kendo Grid generically as a partial view. Kendo requires either a type defined or a datatable to instantiate the grid in a razor view
#(Html.Kendo().Grid<object>() or #(Html.Kendo().Grid(dataTable)
My issue is i want to use the Grid for whatever object, not a specific one.
#(Html.Kendo().Grid<object>()
.Name(Model.MetricName)
.Resizable(resizing => resizing.Columns(true))
.Reorderable(reorder => reorder.Columns(true))
.Sortable(sorting => sorting.Enabled(true))
.Pageable(pager => pager.PageSizes(new int[] { 10, 15, 20, 50 }))
.ColumnMenu()
.DataSource(dataSource => dataSource
.Ajax()
.Read(read => read.Action(Model.MetricName, "AdHocReport", new { metricId = Model.MetricId }))
)
)
by using Object i am able to dynamically load the data returned from the ajax .read method. However the issue is with dates. They are returned in JSON format.
Ive tried this method and I still get JSON string representation of the date
Kendo ASP.NET MVC helper Grid generic class
Is there a way to define the type of grid from a string representation of the type? So lets say i have a string property on the viewModel that is the type of the grid. How can i say Grid ?
ive tried using reflection to instantiate the type but i get the infamous "you are using a variable like a type"
This is driving me nuts... any and all help would be greatly appreciated
So i found the way to make this work and bind correctly and as mentioned above my mrmashal it has to do with using dataTables.
#(Html.Kendo().Grid(Model.GridTable)
here is the viewModel property
public DataTable GridTable { get; set; }
To make this dynamic i use reflection to define the dataTable based upon the properties of a the class i want to populate the grid with
Type elementType = Type.GetType(className, true);
var properties = elementType.GetProperties();
DataTable dataTable = new DataTable();
foreach (PropertyInfo info in properties)
{
dataTable.Columns.Add(new DataColumn(info.Name, Nullable.GetUnderlyingType(info.PropertyType) ?? info.PropertyType));
}
viewModel.GridTable = dataTable;
However, the key is making sure that the data returned from the AJAX read was a dataTable, not an IEnumerable type.
DataTable dataTable = ToDataTable<AssetLocationHistoryMetricData>(metricData);
var result = dataTable.ToDataSourceResult(request);
and this is what i used to convert the List to a dataTable
public static DataTable ToDataTable<T>(IEnumerable<T> items)
{
DataTable dataTable = new DataTable(typeof(T).Name);
//Get all the properties
PropertyInfo[] Props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo prop in Props)
{
//Setting column names as Property names
dataTable.Columns.Add(prop.Name);
}
foreach (T item in items)
{
var values = new object[Props.Length];
for (int i = 0; i < Props.Length; i++)
{
//inserting property values to datatable rows
values[i] = Props[i].GetValue(item, null);
}
dataTable.Rows.Add(values);
}
//put a breakpoint here and check datatable
return dataTable;
}
I have categories table, see its design:
And I want to display this nested categories inside dropdown list like this image:
Can anybody help me to find a solution?
You should retrieve all your categories, ordered by ParentId and then by Name if you need that. You should do this either in your controller or better trough a Service layer that talks to your repository or EntityFramework Datacontext. You didn't specify your data access strategy.
Then in your controller, you'll have to iterate over all categories and create each item taking into account the parent relationship. For example, if you iterate over "top categories" you could then add all child categories of the current category. If you have more than 1 level nesting, you would have to use recursion.
Pseudo-code written directly here, probably won't compile as-is:
//Assume you want to produce a SelectList to use in your View, let's use a view model like the following
public class CategoryViewModelItem
{
public string Value {get;set;}
public string Text {get;set;}
}
In your controller/service layer:
List<CategoryViewModelItem> items = new List<CategoryViewModelItem>();
//get all of them from DB
List<Category> allCategories = dataContext.Categories.ToList();
//get parent categories
List<Category> parentCategories = allCategories.Where(c => c.ParentId == null)
.OrderBy(c => c.Title);
foreach(var cat in parentCategories)
{
//add the parent category to the item list
items.Add(new CategoryViewModelItem { Value = cat.Id, Text = cat.Title });
//now get all its children (separate function in case you need recursion)
GetSubTree(allCategories, cat, items);
}
private void GetSubTree(IList<Category> allCats, Category parent, IList<CategoryViewModelItem> items)
{
var subCats = allCats.Where(c => c.ParentId == parentId);
foreach(var cat in subCats)
{
//add this category
items.Add(new CategoryViewModelItem { Value = cat.Id, Text = parent.Title + " >> " + cat.Title });
//recursive call in case your have a hierarchy more than 1 level deep
GetSubTree(allCats, cat, items);
}
}
Then to render your SelectList, you could send the SelectList as your model (or part of it) for your view:
//in your controller's action
SelectList select = new SelectList(items, "Value", "Text");
return View(select);
And use that in your View:
#Html.DropDownList("Categories", #Model)
I'm trying to set the selected Value for a drop down list.
In Controller I have
ViewData["productType"] = new SelectList(myDropDownList);
And in the View:
<%= Html.DropDownList("productType", ViewData["productType"] as SelectList, "defaultValue")%>
So far So good, but the problem is that now I have "defaultValue" twice in my drop down list. so I have all my values in dropdownlist including the "defaultValue". but this code will add the "defaultValue" as the first element. and I see two samples of it.
I like to set the selected valiue to "defaultValue" without adding it twice.
I tried
ViewData["productType"] = new SelectList(myDropDownList, "defaultValue" );
but it didn't work.
Can anyone please tell me what to do?
You should not be using the same name as first argument for the dropdown as the second one. In your example you have used productType for storing both the selected value and the list of available values. In order to render a DropDown in ASP.NET MVC you need 2 properties:
<%= Html.DropDownList(
"selectedProductType",
ViewData["productType"] as SelectList,
"defaultValue"
) %>
and inside your controller action you could set those 2 properties:
ViewData["selectedProductType"] = "abc";
ViewData["productType"] = new SelectList(myDropDownList);
this assumes that you already have an element with value="abc" inside your dropdown list of product types. The value will then be automatically preselected.
I would recommend you an alternative approach though for rendering dropdown lists. It consists of getting rid of view data and introducing view models and using the strongly typed version of the helper:
public class ProductViewModel
{
public string SelectedProductType { get; set; }
public IEnumerable<SelectListItem> ProductTypes { get; set; }
}
then you will have a controller action that will populate this view model and pass it to the view:
public ActionResult SomeAction()
{
var model = new ProductViewModel();
// preselected an element with value = "type2"
model.SelectedProductType = "type2";
// bind the available product types
model.ProductTypes = new SelectList(
// Obviously those could come from a database or something
new[] {
new { Value = "type1", Text = "product type 1" },
new { Value = "type2", Text = "product type 2" },
new { Value = "type3", Text = "product type 3" },
new { Value = "type4", Text = "product type 4" },
},
"Value",
"Text"
);
// pass the view model to the view
return View(model);
}
and finally inside your strongly typed view:
<%= Html.DropDownListFor(
x => x.SelectedProductType,
Model.ProductTypes,
"defaultValue"
) %>
I have a create method in my controller and this opens up a view. On the view the user can enter data to populate the model. Some of that data comes from select lists. These select lists are populated from the database.
What I would like to know is should I:
a) Get data for the select lists in the controller, populate a field like this:
public IEnumerable<SelectListItem> Statuses { get { return GetStatusType(); } }
pass Statuses to the model and then do a for () to loop through statuses and create a select list and options HTML
b) Do nothing in the controller and in the view have the following in the model:
<select id="Q_StatusID" name="Q.StatusID">#Html.Raw(
SelectHelper.Status(false, #Model.PageMeta.StatusID))</select>
Where the SelectHelper is C# code that gets all the select list and options HTML.
c) Some better way:
I would go with the first one. some thing like this
a helper method
public List<SelectListItem> getAllSelectList(List<Items> lists)
{
List<SelectListItem> selectListItems = new List<SelectListItem>();
foreach (Term term in lists)
{
selectListItems.Add(new SelectListItem() { Text = term.yourselectfield, Value = term.your value });
}
return selectListItems;
}
on your controller
//assuming you GetStatusType() method will return list of objects
ViewData.selectlist=getAllSelectList(GetStatusType());
on your view, if you are using Razor
#Html.DropDownList("selectlist", null, "Choose")
or
<%: Html.DropDownList("selectlist", null, "Choose") %>
Create a static Look-up class & static method for your GetStatusType there.
Cache all the status types after first time loading from your database.
Call GetAllStatusType from the view to display.
I would create a view model, which has a IEnumerable< Statuses > property. Then in your view to display the select element :
#Html.DropDownListFor(model => model.PageMeta.StatusID, new SelectList(Model.Statuses, "Id", "Name"), "Some default which has no value")
Where Id and Name are set to the appropriate properties in your Statuses model.