[转]Asp.Net MVC 扩展联想控件

[转]Asp.Net MVC 扩展联想控件

本文转自:http://www.cnblogs.com/bright-lin/archive/2013/02/06/MVC_SuggestBox.html

在web中,为改善用户体验,我们常会将一些文本输入框做成智能联想,以让用户更快更准确的输入内容。大概是这样的:当用户开始在文本框输入时,客户端脚本ajax向服务端发起请求,服务端从数据库读取返回数据,客户端解析数据附加在文本框的下拉div中供用户选择参考。

在MVC中我们可以通过扩展HtmlHelper来封装自己写的控件,以便在整个项目中像使用 Html.TextBox(“”) 一样来使用自定义控件。

 

扩展代码如下

[转]Asp.Net MVC 扩展联想控件
[转]Asp.Net MVC 扩展联想控件
View Code

复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.Web.Mvc.Html;
namespace HtmlHelperExt
{
public static class SuggestBoxExtensions
{
#region SuggestBox 联想控件
/// <summary>
/// 联想控件
/// </summary>
/// <param name="htmlHelper"></param>
/// <param name="name">name(id)</param>
/// <param name="value">value</param>
/// <param name="controller">controller</param>
/// <param name="action">action</param>
/// <param name="action">fieldName 要在下拉框显示的DataTable中的字段名</param>
/// <param name="action">callBack 当选择值后的回调脚本函数</param>
/// <param name="htmlAttributes"></param>
/// <returns></returns>
public static string SuggestBox(this HtmlHelper htmlHelper, string name, object value, string controller, string action,string fieldName,string callBack,IDictionary<string, object> htmlAttributes)
{
return htmlHelper.SuggestBox(name, value, controller, action,"", fieldName, fieldName, "", "", "",callBack, htmlAttributes);
}
/// <summary>
/// 联想控件
/// </summary>
/// <param name="htmlHelper"></param>
/// <param name="name">name(id)</param>
/// <param name="value">value</param>
/// <param name="controller">controller</param>
/// <param name="action">action</param>
/// <param name="headerText">下拉选框的头部文字(要显示多列用 ';'隔开)</param>
/// <param name="displayFields">要在下拉框显示的DataTable中的字段名(要显示多列用 ';'隔开)</param>
/// <param name="valueField">要赋文本框的字段(只能是一个,且包含在displayFields中)</param>
/// <param name="action">callBack 当选择值后的回调脚本函数</param>
/// <param name="htmlAttributes"></param>
/// <returns></returns>
public static string SuggestBox(this HtmlHelper htmlHelper, string name, object value, string controller, string action, string headerText, string displayFields, string valueField, string callBack, IDictionary<string, object> htmlAttributes)
{
return htmlHelper.SuggestBox(name, value, controller, action, headerText, displayFields, valueField, "", "", "",callBack, htmlAttributes);
}
/// <summary>
/// 联想控件
/// </summary>
/// <param name="htmlHelper"></param>
/// <param name="name">name(id)</param>
/// <param name="value">value</param>
/// <param name="controller">controller</param>
/// <param name="action">action</param>
/// <param name="headerText">下拉选框的头部文字(要显示多列用 ';'隔开)</param>
/// <param name="displayFields">要在下拉框显示的DataTable中的字段名(要显示多列用 ';'隔开)</param>
/// <param name="valueField">要赋文本框的字段(只能是一个,且包含在displayFields中)</param>
/// <param name="keyField">选择行的主键</param>
/// <param name="keyTextBoxName">将主键值保存在以此命名的隐藏的文本控件中,可供其他地方使用</param>
/// <param name="keyTextBoxValue">初始化时主键文本控件中的值</param>
/// <param name="htmlAttributes"></param>
/// <returns></returns>
public static string SuggestBox(this HtmlHelper htmlHelper, string name, object value, string controller, string action, string headerText, string displayFields, string valueField, string keyField, string keyTextBoxName, string keyTextBoxValue,string callBack,IDictionary<string, object> htmlAttributes)
{
var sb = new StringBuilder();
if (htmlAttributes == null)
htmlAttributes = new Dictionary<string, object>();
string styleStr = "";
if (htmlAttributes.ContainsKey("style"))
styleStr = htmlAttributes["style"].ToString();
string boxId = name.ToUpper() + "_SUGBOX";
if (styleStr.Length > 0)
sb.Append(htmlHelper.TextBox(name, value, new { style = styleStr, autocomplete = "off" }));
else
sb.Append(htmlHelper.TextBox(name, value, new { autocomplete = "off" }));
sb.Append("<script type=\"text/javascript\">");
sb.AppendFormat("$('{0}').suggest({
{boxId:'{1}',controller:'{2}',action:'{3}',headerText:'{4}',displayFields:'{5}',valueField:'{6}',keyField:'{7}',keyTextBoxName:'{8}',callBack:'{9}'}})",
"#" + name, boxId, controller, action, headerText, displayFields, valueField, keyField, keyTextBoxName,callBack);
sb.Append("</script>");
if (keyTextBoxName != "")
{
sb.Append(htmlHelper.Hidden(keyTextBoxName, keyTextBoxValue));
}
return sb.ToString();
}
#endregion
}
}
复制代码

 

通过Controller读取、解析、返回数据。将从数据库(或XML)读取的数据存入DataTable,然后转换为Json字符串再返回给客户端。本Demo中模拟数据在XML文件中。

Controller代码如下:

[转]Asp.Net MVC 扩展联想控件
[转]Asp.Net MVC 扩展联想控件
View Code

复制代码
 public class SuggestBoxController : Controller
{
public ActionResult Demo()
{
return View();
}
public string Suggest()
{
string searchText = "";
if (Request["param"] == null)
{
return "";
}
searchText = Request["param"].ToString();
DataSet ds = new DataSet();
ds.ReadXml(Server.MapPath("~/KeyWords.xml"));
DataRow[] drs = ds.Tables[0].Select("name like '%" + searchText + "%'");
DataTable dt = new DataTable();
dt.Columns.AddRange(new DataColumn[] { new DataColumn("id"), new DataColumn("name") });
int len = drs.Length;
for (int i = 0; i < len; i++)
{
DataRow dr = dt.NewRow();
dr[0] = drs[i][0];
dr[1] = drs[i][1];
dt.Rows.Add(dr);                
}
return CreateJsonStr(dt);
}
#region CreateJsonStr
/// <summary>
/// 将DataTable数据转换为Json字符串
/// </summary>
/// <param name="dt"></param>
/// <returns></returns>
public  string CreateJsonStr(DataTable dt)
{
StringBuilder JsonString = new StringBuilder();
JsonString.Append("{ ");
JsonString.Append("\"Data\":[ ");
if (dt != null && dt.Rows.Count > 0)
{
for (int i = 0; i < dt.Rows.Count; i++)
{
JsonString.Append("{ ");
for (int j = 0; j < dt.Columns.Count; j++)
{
if (j < dt.Columns.Count - 1)
{
JsonString.Append("\"" + dt.Columns[j].ColumnName.ToString() + "\":" + "\"" + dt.Rows[i][j].ToString() + "\",");
}
else if (j == dt.Columns.Count - 1)
{
JsonString.Append("\"" + dt.Columns[j].ColumnName.ToString() + "\":" + "\"" + dt.Rows[i][j].ToString() + "\"");
}
}
if (i == dt.Rows.Count - 1)
{
JsonString.Append("} ");
}
else
{
JsonString.Append("}, ");
}
}
}
JsonString.Append("]}");
return JsonString.ToString();
}
#endregion
}
复制代码

 

主要核心还是在客户端的脚本中,脚本通过ajax访问服务端,并加载绑定返回数据,响应反馈用户的操作。

[转]Asp.Net MVC 扩展联想控件
[转]Asp.Net MVC 扩展联想控件
View Code

(function($) { var itemIndex = 0; $.fn.suggest = function(options) { var params = { boxId: "suggestBox", boxWidth: 250, boxHeight: 200, controller: "", action: "", headerText: "", displayFields: "", valueField: "", keyField: "", keyTextBoxName: "", callBack: "" }; var ops = $.extend(params, options); var headerTextArr = new Array(); var displayFieldsArr = new Array(); headerTextArr = ops.headerText.split(';'); displayFieldsArr = ops.displayFields.split(';'); var headerStr = ""; var headerLen = headerTextArr.length; if (headerLen == 1 || headerLen == 0) { var textBox = $(this); ops.boxWidth = textBox.css("width"); } var box = ''; if (ops.headerText.length == 0) { box = '<div id="' + ops.boxId + '" style="display:none;width:' + ops.boxWidth + ';height:' + ops.boxHeight + '"><ul class="suggestBoxItems"></ul></div>'; } else { for (var i = 0; i < headerLen; i++) { if (i == headerLen - 1) { headerStr += '<span class="headerTextShort">' + headerTextArr[i] + '</span>' } else { headerStr += '<span class="headerTextLong">' + headerTextArr[i] + '</span>' } } box = '<div id="' + ops.boxId + '" style="display:none;width:' + ops.boxWidth + ';height:' + ops.boxHeight + '"><div class = "headerText">' + headerStr + '</div><ul class="suggestBoxItems"></ul></div>'; } $(this).after(box); var itemCount = 0; $(this).bind('keyup', function(e) { var value = $.trim($(this).val()); if (value.length >= 1) { var position = $(this).position(); $('#' + ops.boxId).css({ 'display': 'block', 'background': 'white', 'color': 'black', 'position': 'absolute', 'border': "1px solid #D5D5D5", 'left': position.left, 'top': position.top + 22 }); var pVal = $(this).val() + ""; if (pVal.search('&') >= 0) { pVal = pVal.replace('&', '%26'); } if (e.keyCode != 38 && e.keyCode != 40 && e.keyCode != 13 && e.keyCode != 9) { var sugTextBox = $(this); var dataUrl = "/" + ops.controller + "/" + ops.action; if (pVal != "") { $.ajax({ type: "post", async: true, url: dataUrl, data: "param=" + pVal, dataType: "json", cache: false, timeout: 5000, beforeSend: loading(ops.boxId), error: function(XMLHttpRequest, textStatus, errorThrown) { alert(textStatus); $('#' + ops.boxId).slideUp("slow"); $('#' + ops.boxId + ' ul').html(''); }, success: function(data) { initBox(ops.boxId, sugTextBox, data, displayFieldsArr, ops.valueField, ops.keyField, ops.keyTextBoxName); } }); } itemIndex = 0; } var itemCount = $('#' + ops.boxId + ' ul li').length; switch (e.keyCode) { case 38: if (itemIndex == 0) { itemIndex = itemCount + 1; } if (itemIndex > 1) { $('#' + ops.boxId + ' ul li:nth-child(' + itemIndex + ')').css({ 'background': 'white', 'color': 'black' }); itemIndex--; } $('#' + ops.boxId + ' ul li:nth-child(' + itemIndex + ')').css({ 'background': '#7AADEB', 'color': 'white' }); $(this).val($('#' + ops.boxId + ' ul li:nth-child(' + itemIndex + ')').find('font').text()); if (ops.keyTextBoxName != "") { $('#' + ops.keyTextBoxName).val($('#' + ops.boxId + ' ul li:nth-child(' + itemIndex + ')').find('div').text()); } break; case 40: if (itemIndex < itemCount) { $('#' + ops.boxId + ' ul li:nth-child(' + itemIndex + ')').css({ 'background': 'white', 'color': 'black' }); itemIndex++; } $('#' + ops.boxId + ' ul li:nth-child(' + itemIndex + ')').css({ 'background': '#7AADEB', 'color': 'white' }); $(this).val($('#' + ops.boxId + ' ul li:nth-child(' + itemIndex + ')').find('font').text()); if (ops.keyTextBoxName != "") { $('#' + ops.keyTextBoxName).val($('#' + ops.boxId + ' ul li:nth-child(' + itemIndex + ')').find('div').text()); } break; case 13: if (itemIndex > 0 && itemIndex <= itemCount) { $(this).val($('#' + ops.boxId + ' ul li:nth-child(' + itemIndex + ')').find('font').text()); if (ops.keyTextBoxName != "") { $('#' + ops.keyTextBoxName).val($('#' + ops.boxId + ' ul li:nth-child(' + itemIndex + ')').find('div').text()); } $('#' + ops.boxId).slideUp("fast"); $('#' + ops.boxId + ' ul').html(''); eval(ops.callBack); } break; default: break; } } else { $('#' + ops.boxId).slideUp("fast"); $('#' + ops.boxId + ' ul').html(''); } }); $(this).blur(function() { var tempLi = $('#' + ops.boxId + ' ul li:nth-child(1)'); if (itemIndex == 0 && tempLi != undefined) { $(this).val(tempLi.find('font').text()); if (ops.keyTextBoxName != "") { $('#' + ops.keyTextBoxName).val(tempLi.find('div').text()); } itemIndex = 1; } if ($('#' + ops.boxId + ' ul').html() != '') { eval(ops.callBack); } $('#' + ops.boxId).slideUp("fast"); $('#' + ops.boxId + ' ul').html(''); }); }; function loading(boxId) { $('#' + boxId + ' ul').html('<img alt="loading" src="/Scripts/SuggestBox/loading.gif"/>'); } function initBox(boxId, obj, data, displayFieldsArr, valueField, keyField, keyTextBoxName) { var str = ""; if (data == undefined || data.Data == undefined || data.Data.length == 0) { $('#' + boxId + ' ul').html('<div class="noRecordsTip">No records found<div>'); } else { for (var i = 0; i < data.Data.length; i++) { var fieldStr = ""; for (var j = 0; j < displayFieldsArr.length; j++) { if (displayFieldsArr[j] == valueField) { if (j == 0 || j != displayFieldsArr.length - 1) { fieldStr += "<font class='singleField'>" + data.Data[i][displayFieldsArr[j]] + "</font>"; } else { fieldStr += "<font>" + data.Data[i][displayFieldsArr[j]] + "</font>"; } } else { var tempValue = data.Data[i][displayFieldsArr[j]]; if (tempValue.length > 16) { tempValue = tempValue.substr(0, 16) + "..."; } fieldStr += "<span class='commonFields'>" + tempValue + "</span>"; } } if (keyField != "") { fieldStr += "<div style = 'display:none;'>" + data.Data[i][keyField] + "</div>"; } str += "<li>" + fieldStr + "</li>"; } $('#' + boxId + ' ul').html(str); } if (data != undefined && data.Data != undefined && data.Data.length == 1) { var tempLi = $('#' + boxId + ' ul li'); obj.val(tempLi.find('font').text()); if (keyTextBoxName != "") { $('#' + keyTextBoxName).val(tempLi.find('div').text()); } itemIndex = 1; } $('#' + boxId + ' ul li').each(function() { $(this).bind('click', function() { obj.val($(this).find('font').text()); if (keyTextBoxName != "") { $('#' + keyTextBoxName).val($(this).find('div').text()); } eval(ops.callBack); $('#' + boxId).slideUp("fast"); }); }); $('#' + boxId + ' ul li').each(function() { $(this).hover( function() { $('#' + boxId + ' ul li:nth-child(' + itemIndex + ')').css({ 'background': 'white', 'color': 'black' }); itemIndex = $('#' + boxId + ' ul li').index($(this)[0]) + 1; $(this).css({ 'background': '#7AADEB', 'color': 'white' }); obj.val($(this).find('font').text()); if (keyTextBoxName != "") { $('#' + keyTextBoxName).val($(this).find('div').text()); } }, function() { $(this).css({ 'background': 'white', 'color': 'black' }); } ); }); }; })(jQuery);

在View里面需要Import我们写的扩展类所在的命名空间,<%@ Import Namespace=”HtmlHelperExt” %>

以及引入相关的js、css(extension.suggestbox.js 和 jquery-1.4.1.js 和 SugBoxStyle.css)

[转]Asp.Net MVC 扩展联想控件
[转]Asp.Net MVC 扩展联想控件
View Code

复制代码
<div>
<% IDictionary<string, object> htmlAttributes = new Dictionary<string, object>(); htmlAttributes.Add("style", "width:198px"); %>
简单单列 <%=Html.SuggestBox("MySuggestBox01", "", "SuggestBox", "Suggest","name","", htmlAttributes)%>
<br /><br /><br /><br />
带表头单列  <%=Html.SuggestBox("MySuggestBox02", "", "SuggestBox", "Suggest","关键字","name","name","", htmlAttributes)%>
<br /><br /><br /><br />
带表头双列 <%=Html.SuggestBox("MySuggestBox03", "", "SuggestBox", "Suggest","编号;关键字","id;name","name","", htmlAttributes)%>
<br /><br /><br /><br />
带表头双列+回调函数  <%=Html.SuggestBox("MySuggestBox04", "", "SuggestBox", "Suggest", "编号;关键字", "id;name", "name", "id", "MySuggestBox04_ID", "0", "afterSelect()", htmlAttributes)%>
<span id="tip"></span>
<script type="text/javascript">
var id = document.getElementById("MySuggestBox04_ID").value;
document.getElementById("tip").innerHTML = "当前选择的编号是: <font color='red'>" + id + "</font>";
function afterSelect() {
var id = document.getElementById("MySuggestBox04_ID").value;
document.getElementById("tip").innerHTML = "当前选择的编号是: <font color='red'>"+id+"</font>";
}
</script>
</div>
复制代码

结果演示一:简单单列

[转]Asp.Net MVC 扩展联想控件

结果演示二:带表头单列

[转]Asp.Net MVC 扩展联想控件

结果演示三:带表头双列

[转]Asp.Net MVC 扩展联想控件

结果演示四:带表头双列+回调函数(选择一值时将key值赋给指定的Hidden中)

[转]Asp.Net MVC 扩展联想控件

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/110080.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • TCP Flow Control

    TCP Flow Control这里写自定义目录标题TCPFlowControlTCP简述TCP传输机制滑动窗口FlowControl计时器总结TCPFlowControl最近在学习《计算机网络》在TCP的FlowControl部分理解不太清楚,查阅了资料后有一些粗浅的理解,如有不准确的地方,请大佬指正。参考资料1.计算机网络2.TCPFlowControlTCP简述TCP(Transmissi…

  • app加固_360加固保手机版

    app加固_360加固保手机版为什么要加固APP?答:因为黑客通过反编译APK得到源码后,会在应用中插入代码,获取利益,比如添加广告,盗取用户账号、密码,后台定制活动等。反编译的方法?反编译是指apk文件通过反编译工具(例如

  • 一般人到底要不要学Python_Python值得学吗

    一般人到底要不要学Python_Python值得学吗前言本人纯屌丝一枚,在学python之前对电脑的认知也就只限于上个网,玩个办公软件。这里不能跑题,我为啥说自学python,一般人我还是劝你算了吧。因为我就是那个一般人。基础真的很简单,是个人稍微认点真都能懂,这就是好多人说的python简单、易懂、好学,然后就是一顿浮夸的言论,误导那些小白,再然后那些小白也就跟着浮夸。这里我就给那些轻浮的人泼一桶冷水,懂跟学会是一码事吗?先来说哈python这个就业哈,我现在生活在祖国的肚皮上–成都,(嗯,有想了解川西迷你小环线的在下面留言哦),下面亲身经历,我喃,

  • telnet发电子邮件

    telnet发电子邮件

  • MySQL——事务(Transaction)详解

    MySQL——事务(Transaction)详解该博客详解MySQL中的事务一、事务定义Transaction事务:一个最小的不可再分的工作单元;通常一个事务对应一个完整的业务(例如银行账户转账业务,该业务就是一个最小的工作单元)一个完整的业务需要批量的DML(insert、update、delete)语句共同联合完成事务只和DML语句有关,或者说DML语句才有事务。这个和业务逻辑有关,业务逻辑不同,DML语句的个数不同…

  • PLC编程入门基础技术知识

    PLC编程入门基础技术知识PLC编程入门基础技术知识第一章可编程控制器简介可编程序控制器,英文称ProgrammableController,简称PC。但由于PC容易和个人计算机(PersonalComputer)混淆,故人们仍习惯地用PLC作为可编程序控制器的缩写。它是一个以微处理器为核心的数字运算操作的电子系统装置,专为在工业现场应用而设计,它采用可编程序的存储器,用以在其内部存储执行逻辑运算、顺序控制、定时/计数和算术运算等操作指令,并通过数字式或模拟式的输入、输出接口,控制各种类型的机械或生产过程。PLC是微机技术与

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号