Introduction
The code is used to create a multiple column auto complete for ASP.NET MVC3 Application.
Background
ASP.NET MVC3 doesn't support a combo-box or multiple column drop-down list. So i had made a custom action control in MVC 3. by using it we can achieve functionality of multiplle column combox in asp.net MVC.
To achieve we our application uses Entity framework model (.edmx) generated through database 'ProEnhance' in SQL Server 2008 r2.
Code uses Json result to bind data using ajax binding.
Using the code
1. First of all we have to create a simple database that contains Two simple tables employee and projects. Shown below is the script to generate the table.
USE [ProEnhance]
GO
CREATE TABLE [dbo].[EmployeeMast](
[Id] [int] IDENTITY(1,1) NOT NULL,
[EmpCode] [varchar](50) NULL,
[MachineCode] [varchar](50) NULL,
[FirstName] [nvarchar](150) NULL,
[LastName] [nvarchar](150) NULL,
[DisplayName] [nvarchar](400) NULL,
[Address] [nvarchar](250) NULL,
[ProjectId] [int] NULL,
CONSTRAINT [PK_EmployeeMast] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[ProjectMast](
[Id] [int] IDENTITY(1,1) NOT NULL,
[ProjectName] [nvarchar](150) NULL,
[ProjectDesc] [nvarchar](500) NULL,
[PlatformId] [int] NULL,
CONSTRAINT [PK_ProjectMast] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
2. Now Controller creates Edmx for the above database
3. Create controller to create custom control. Following is controller code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ComboDemo.Models;
namespace ComboDemo.Controllers
{
public class CustomeControlsController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult MultiColumnComboBox(string SearchFor, string ControlId)
{
ViewBag.ProcId = SearchFor.Trim();
ViewBag.ControlBlockId = "block" + ControlId.Trim();
ViewBag.ControlId = ControlId.Trim();
ViewBag.ControlTxtId = "txt" + ControlId.Trim();
return View();
}
public JsonResult LoadComboData(string strSearch, string SearchFor)
{
ProEnhanceEntities db = new ProEnhanceEntities();
strSearch = strSearch.Trim();
if (SearchFor.Trim() == "employee")
{
var res = (from E in db.EmployeeMasts
where E.DisplayName.ToLower().Contains(strSearch.ToLower()) || E.EmpCode.ToLower().Contains(strSearch.ToLower()) || E.Address.ToLower().Contains(strSearch.ToLower())
select new
{
E.EmpCode,
E.DisplayName,
E.Address
}).ToList();
return Json(res, JsonRequestBehavior.AllowGet);
}
if (SearchFor.Trim() == "project")
{
var res = (from P in db.ProjectMasts
where P.ProjectDesc.ToLower().Contains(strSearch.ToLower()) || P.ProjectName.ToLower().Contains(strSearch.ToLower())
select P).ToList();
return Json(res, JsonRequestBehavior.AllowGet);
}
return Json(null, JsonRequestBehavior.AllowGet);
}
}
}
4. Create View For MultipleColumnCombobox Action. Following is code for it. With jQuery to generate autocomplete for Input control.
@{
Layout = null;
}
<style type="text/css">
table td
{
padding: 3px 5px;
margin: 0;
}
a:link
{
text-decoration: none;
cursor: pointer;
}
.tdHeader
{
background-color: #CEF6F5;
}
.DataBlock
{
max-width: 520px;
min-width: 215px;
max-height: 200px;
overflow: auto;
background-color: #fff;
}
.renderpart
{
z-index: 99999;
position: absolute;
}
</style>
<input type="hidden" id="@ViewBag.ProcId" name="@ViewBag.ProcId" value=""/>
<input type="hidden" id="@ViewBag.ControlId" name="@ViewBag.ControlId" value=""/>
<input type="text" name="@ViewBag.ControlTxtId" id="@ViewBag.ControlTxtId" autocomplete="off"/>
<div class="@ViewBag.ControlTxtId renderpart">
<div class="DataBlock">
<div id="@ViewBag.ControlBlockId" style="max-width: 520px;">
</div>
</div>
</div>
<script src="../../Scripts/jquery-1.7.1.js" type="text/javascript"></script>
<script src="../../Scripts/json.debug.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
$(".renderpart").hide();
var txtid = "#" + '@ViewBag.ControlTxtId';
var renderpart = "." + '@ViewBag.ControlTxtId';
var selectlinkvalueid = ".Get" + '@ViewBag.ProcId';
$(selectlinkvalueid).live("click", function () {
var value = $(this).attr('id');
var valueText = $(this).attr('title');
$("#@ViewBag.ControlId").val(value);
$(txtid).val(valueText);
$(renderpart).slideUp("slow");
});
$(txtid).keyup(function () {
var value = $(txtid).val();
var Procvalue = '@ViewBag.ProcId';
var controlid = "#" + '@ViewBag.ControlBlockId';
value = encodeURI(value);
if (value.length > 2) {
$.ajaxSetup({ cache: false });
$.getJSON("/CustomeControls/LoadComboData", { strSearch: " " + value, ProcId: " " + Procvalue }, function (data) {
$(controlid).html("");
var activecols = $("#hdnActiveColumns").val();
var htmlrow = "";
var tempprocId = '@ViewBag.ProcId';
var jsondata = JSON.stringify(data);
$(controlid).html(CreateDynamicTable(jsondata, tempprocId));
$(renderpart).slideDown("slow");
});
$.ajaxSetup({ cache: true });
}
else {
$(renderpart).slideUp("slow");
}
});
$(txtid).focusin(function () {
var txtid = "#" + '@ViewBag.ControlTxtId';
var value = $(txtid).val();
var Procvalue = '@ViewBag.ProcId';
var controlid = "#" + '@ViewBag.ControlBlockId';
value = encodeURI(value);
if (value.length > 2) {
$.ajaxSetup({ cache: false });
$.getJSON("/CustomeControls/LoadComboData", { strSearch: " " + value, ProcId: " " + Procvalue }, function (data) {
$(controlid).html("");
var htmlrow = "";
var tempprocId = '@ViewBag.ProcId';
var jsondata = JSON.stringify(data);
$(controlid).html(CreateDynamicTable(jsondata, tempprocId));
$(renderpart).slideDown("slow");
});
$.ajaxSetup({ cache: true });
}
else {
$(renderpart).slideUp("slow");
}
});
function CreateDynamicTable(objArray, tempprocId) {
var array = JSON.parse(objArray);
var str = '<table style="width:100%;">';
str += '<tr>';
for (var index in array[0]) {
str += '<th scope="col">' + index + '</th>';
}
str += '</tr>';
str += '<tbody>';
var flag = false;
var ids;
for (var i = 0; i < array.length; i++) {
str += (i % 2 == 0) ? '<tr>' : '<tr>';
for (var index in array[i]) {
if (flag == false) {
ids = array[i][index];
flag = true;
}
str += '<td><a id="' + ids + '" class="Get' + tempprocId + '" title="' + array[i][index] + '" href="#">' + array[i][index] + '</a></td>';
}
str += '</tr>';
}
str += '</tbody>';
str += '</table>';
return str;
}
});
$(document).click(function (evt) {
var renderpart = "." + '@ViewBag.ControlTxtId';
var theElem = (evt.srcElement) ? evt.srcElement : evt.target;
if (theElem.id == "main" || theElem.id == "sub1") {
$(renderpart).slideUp("fast");
}
});
</script>
5. Now simply call our action with parameter to render a custom auto-complet control.
@{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>
Index</h2>
<h4>
Render Custom action to generate Multiple column Combo.</h4>
<table>
<tr>
<td>
Employees:
</td>
<td>
@{Html.RenderAction("MultiColumnComboBox", "CustomeControls", new { ControlFor = "employee", ControlId = "comboEmp" });}
</td>
</tr>
<tr>
<td>
Projects:
</td>
<td>
@{Html.RenderAction("MultiColumnComboBox", "CustomeControls", new { ControlFor = "project", ControlId = "comboPrj" });}
</td>
</tr>
</table>