First of all, grab the ASP.NET MVC Kendo trial installer from the link below:
https://www.telerik.com/downloads/productfiles/bmmtd/TelerikUIForAspNetMvcSetup.2015.1.429.exe
Now once you are done with installation, please go through the following link so
we have all setup to try code that we go through in next section and ready to
hit F5!
http://docs.telerik.com/kendo-ui/aspnet-mvc/asp-net-mvc-5
Dynamic columns
Once I had a scenario to dynamically display search query result set based on the
result set I received. The result is of type dynamic and could have various columns
based on the keyword searched. I come up with following model to satisfy the
need of handling dynamic columns.
public class SearchResult {
public DataTable ResultData { get; set; }
public Dictionary<string, Type> ColumnsBind { get; set; }
}
Listing 1.0 SearchResult class
To populate search results, we will use following mock method which adds some sample
data and it will return object of class as per Listing 1.0.
public ActionResult SearchResults(string keyWord)
{
var result = new SearchResult();
result.ResultData = this.GetTable();
var colls = new Dictionary<string, System.Type>();
foreach (System.Data.DataColumn column in result.ResultData.Columns)
{
var t = System.Type.GetType(column.DataType.FullName);
colls.Add(column.ColumnName, t);
}
result.ColumnsBind = colls;
return this.View("SearchResults", result);
}
private DataTable GetTable()
{
var table = new DataTable("Result");
Random rnd = new Random();
var val = rnd.Next(3, 8);
for (int i = 0; i < val; i++)
{
table.Columns.Add("Column_" + i, typeof(string));
}
for (int i = 0; i < 10; i++)
{
var row = table.NewRow();
for (int j = 0; j < val; j++)
{
row["Column_" + j] = "field_" + j;
}
table.Rows.Add(row);
}
return table;
}
Listing 1.1 Action method and methods for mock data
We are going to use Razor view here named SearchResults. The code to use Kendo grid
is as following:
@Html.Kendo().Grid<dynamic>()
.Name( "SearchResultGrid" )
.Columns( columns => {
//Define the columns from
foreach ( var c in Model. ColumnsBind)
columns.Bound( c.Value, c.Key );
} )
.DataSource( model => model. ResultData)
)
Listing 1.2 Kendo Grid definition
Now once you run it, it should show you result in nice Kendo grid!
Column title from attribute
Often you need to display different title for your data grid column than the property
name. One way of doing so is doing it in JS as following:
columns.Bound(model => model.Identity).Title("User ID");
The other way around is to do it on server side by implementing AssociatedMetadataProvider.
This way, you can control column names from server side and saves your effort
to maintain them in view/JS for all the occurrences of the column.
Consider the class shown in Listing 1.3 below.
public class Employee
{
public string Identity { get; set; }
public string Address1 { get; set; }
[Display("Street address")]
public string Address2 { get; set; }
}
Listing 1.3 Employee class
In the custom metadata provider that we will develop just now, we want to give custom
title for Address related properties when they do not have Display attribute
set. So implementation of our custom metadata provider will be something like
following as per Listing 1.4
public class AddressMetadataProvider : AssociatedMetadataProvider
{
public AddressMetadataProvider()
: base()
{
}
protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType,
string propertyName)
{
var metaData = new ModelMetadata(this, containerType, modelAccessor, modelType, propertyName);
if (propertyName == null)
return metaData;
if (propertyName.StartsWith("Address") && attributes == null)
{
metaData.DisplayName = "Address line";
}
else
{
if (attributes != null)
{
foreach (var a in attributes)
{
var type = a.TypeId as Type;
if (type != null && type.Name == "DisplayAttribute")
{
var displayName = (a as DisplayAttribute).Name;
if (!string.IsNullOrEmpty(displayName))
metaData.DisplayName = displayName;
}
}
}
}
return metaData;
}
}
Listing 1.4 AddressMetadataProvider class
One more step is required to tell MVC framework to look for metadata using this provider.
To do so, register it in global.asax.cs as following:
protected void Application_Start()
{
ModelMetadataProviders.Current = new AddressMetadataProvider();
}
Listing 1.5 Register AddressMetadataProvider
Conditional client template
It is quite common to display different value or control altogether based on the
property values. For example, based on the user access level, you may want to
present him with various command buttons such as Process button. We can use Kendo
grid client template with set of conditions to do so. Code listing 1.6 shows
that
@(Html.Kendo().Grid(Model)
.Name("UserGrid")
.Columns(columns =>
{
columns.Bound(o => o.AccountManager).Title("Admin").ClientTemplate("# if (IsAdmin) { #" + @Html.ActionLink("Process", "ProcessRequest", "AdminController") + "# }else {#" + "No admin access" + "#} #");
})
Listing 1.6 Conditional client template
Radio button list from Enum
For your enum properties, sometimes you need a view where you present user with all
the enum values and allow single selection out of it. In such cases, developing
up EditorTemplate for the given type is the way to go. Here I will show you code
for developing one for Enum.
@model Enum
@{
// Looks for Display attribute on property
Func<Enum, string> GetDescription = enumField =>
{
Type type = en.GetType();
System.Reflection.MemberInfo[] memInfo = type.GetMember(en.ToString());
if (memInfo != null && memInfo.Length > 0)
{
object[] attrs = memInfo[0].GetCustomAttributes(typeof(System.ComponentModel.DataAnnotations.DisplayAttribute),
false);
if (attrs != null && attrs.Length > 0)
return ((System.ComponentModel.DataAnnotations.DisplayAttribute)attrs[0]).GetName();
}
return enumField.ToString();
};
var listItems = Enum.GetValues(Model.GetType()).OfType<Enum>().Select(e
=>
new SelectListItem()
{
Text = GetDescription(e),
Value = e.ToString(),
Selected = e.Equals(Model)
});
string prefix = ViewData.TemplateInfo.HtmlFieldPrefix;
int index = 0;
ViewData.TemplateInfo.HtmlFieldPrefix = string.Empty;
foreach (var li in listItems)
{
string fieldName = string.Format(System.Globalization.CultureInfo.InvariantCulture,
"{0}_{1}", prefix, li.Value);
<div>
@Html.RadioButton(prefix, li.Value, li.Selected, new { @id = fieldName })
@Html.Label(fieldName, li.Text)
</div>
}
ViewData.TemplateInfo.HtmlFieldPrefix = prefix;
}
Listing 1.7 EnumRadioButtonList EditorTemplate
The usage is quite simple.
@Html.EditorFor(model => model.EmployeeType, "EnumRadioButtonList")