注:文字寫作是本人弱項,如描述有問題,請見諒!!!
前言:在開發中,經常使用查詢分頁,為了達到統一與復用,進行的統合實例,本實例將一步一步實現一個統合的查詢分頁的實現。
開發工具:VS2012
1.建立項目:
第一個是MVC4項目,第二個是一個類庫
2.在類庫PageSearchModel中添加引用如下:
3.要進行查詢,我們添加一個查詢方法枚舉:QueryMethod.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace System.Web.Mvc { /// <summary> /// Html表單元素的檢索方式 /// </summary> public enum QueryMethod { /// <summary> /// 等於 /// </summary> //[GlobalCode("=", OnlyAttribute = true)] Equal = 0, /// <summary> /// 小於 /// </summary> //// [GlobalCode("<", OnlyAttribute = true)] LessThan = 1, /// <summary> /// 大於 /// </summary> // [GlobalCode(">", OnlyAttribute = true)] GreaterThan = 2, /// <summary> /// 小於等於 /// </summary> // [GlobalCode("<=", OnlyAttribute = true)] LessThanOrEqual = 3, /// <summary> /// 大於等於 /// </summary> // [GlobalCode(">=", OnlyAttribute = true)] GreaterThanOrEqual = 4, /// <summary> /// Like /// </summary> // [GlobalCode("like", OnlyAttribute = true)] Like = 6, /// <summary> /// In /// </summary> // [GlobalCode("in", OnlyAttribute = true)] In = 7, /// <summary> /// 輸入一個時間獲取當前天的時間塊操作, ToSql未實現,僅實現了IQueryable /// </summary> // [GlobalCode("between", OnlyAttribute = true)] DateBlock = 8, // [GlobalCode("<>", OnlyAttribute = true)] NotEqual = 9, // [GlobalCode("like", OnlyAttribute = true)] StartsWith = 10, // [GlobalCode("like", OnlyAttribute = true)] EndsWith = 11, /// <summary> /// 處理Like的問題 /// </summary> [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] Contains = 12, /// <summary> /// 處理In的問題 /// </summary> [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] StdIn = 13, /// <summary> /// 處理Datetime小於+23h59m59s999f的問題 /// </summary> [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] DateTimeLessThanOrEqual = 14 } }
4.添加一個排序類:QueryOrder.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace System.Web.Mvc { public class QueryOrder { public QueryOrder() { Order = OrderType.ASC; } /// <summary> /// 排序字段 /// </summary> public virtual string Field { get; set; } /// <summary> /// 排序方式 /// </summary> public virtual OrderType Order { get; set; } } public enum OrderType { ASC, DESC } }
5.添加一個組合查詢條件類:ConditionItem.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Web.Mvc; namespace System.Web.Mvc { /// <summary> /// 用於存儲查詢條件的單元 /// </summary> public class ConditionItem { public ConditionItem() { } public ConditionItem(string field, QueryMethod method, object val) { Field = field; Method = method; Value = val; } /// <summary> /// 字段 /// </summary> public string Field { get; set; } /// <summary> /// 查詢方式,用於標記查詢方式HtmlName中使用[]進行標識 /// </summary> public QueryMethod Method { get; set; } /// <summary> /// 值 /// </summary> public object Value { get; set; } /// <summary> /// 前綴,用於標記作用域,HTMLName中使用()進行標識 /// </summary> public string Prefix { get; set; } /// <summary> /// 如果使用Or組合,則此組組合為一個Or序列 /// </summary> public string OrGroup { get; set; } } }
6.添加一個表格的列類:PageColum.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace System.Web.Mvc { /// <summary> /// 列 /// </summary> public class PageColum { public PageColum() { Id = Guid.NewGuid().ToString(); Sort = false; } /// <summary> /// 編號 /// </summary> public string Id { get; set; } /// <summary> /// 字段 /// </summary> public string Field { get; set; } /// <summary> /// 列頭名 /// </summary> public string Header { get; set; } /// <summary> /// 排序 DESC為true /// </summary> public bool Sort { get; set; } /// <summary> /// 列樣式 /// </summary> public string Style { get; set; } } /// <summary> /// 列 /// </summary> public class PageColum<T> : PageColum { public Func<T, object> Format { get; set; } } }
7.添加一個表格的行類:PageRow.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace System.Web.Mvc { /// <summary> /// 行 /// </summary> public class PageRow { public PageRow() { RowData = new List<RowItem>(); } // <summary> /// 行數據 /// </summary> public IList<RowItem> RowData { get; set; } /// <summary> /// 單行數據對象的主鍵字段名 /// </summary> public string SourcePrimaryKey { get; set; } /// <summary> /// 行樣式 /// </summary> public string Style { get; set; } } /// <summary> /// 行中單列數據 /// </summary> public class RowItem { /// <summary> /// 對應列編號 /// </summary> public string ColumId { get; set; } /// <summary> /// 是否是字段列 /// </summary> public bool CheckFieldColum { get; set; } /// <summary> /// 值 /// </summary> public object Vaule { get; set; } } }
8.添加一個查詢分頁類:PageModel.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Web;
using System.Web.WebPages;
namespace System.Web.Mvc
{
/// <summary>
/// 分頁模型
/// </summary>
public class PageModel
{
public PageModel()
{
this.PageIndex = 1;
this.PageSize = 15;
SearchQuery = new List<ConditionItem>();
Id = Guid.NewGuid().ToString().Replace(@"/","").Replace(@"\","").Replace("-", "_");
}
/// <summary>
/// 頁的唯一標識
/// </summary>
public virtual string Id { get; set; }
/// <summary>
/// 頁碼從1開始
/// </summary>
public virtual int PageIndex { get; set; }
/// <summary>
/// 每頁顯示數量
/// </summary>
public virtual int PageSize { get; set; }
/// <summary>
/// 頁總數
/// </summary>
public virtual long PageTotal
{
get
{
#region
if (DataTotal == 0)
{
return 0;
}
else if (DataTotal <= PageSize)
{
return 1;
}
else
{
var z = DataTotal / PageSize;
var y = DataTotal % PageSize;
if (y != 0)
{
return z + 1;
}
else
{
return z;
}
}
#endregion
}
}
/// <summary>
/// 數據總數
/// </summary>
public virtual long DataTotal { get; set; }
/// <summary>
/// 查詢條件
/// </summary>
public virtual List<ConditionItem> SearchQuery { get; set; }
/// <summary>
/// 排序
/// </summary>
public virtual QueryOrder Order { get; set; }
/// <summary>
/// 是否全選
/// </summary>
public bool SelectAll { get; set; }
/// <summary>
/// 選擇的查詢集合
/// </summary>
public IList<string> SelectPrimaryKeys { get; set; }
/// <summary>
/// 判斷查詢字段是存在
/// </summary>
/// <param name="expr"></param>
/// <returns></returns>
public bool CheckSearchName<T>(Expression<Func<T, object>> expr)
{
var field= expr.Body.ToString().Split('.').Last();
if (SearchQuery.Where(m => m.Field == field).Count() > 0)
return true;
else
return false;
}
/// <summary>
/// 查詢字段值
/// </summary>
/// <param name="expr"></param>
/// <returns></returns>
public object SearchValue<T>(Expression<Func<T, object>> expr)
{
var field = expr.Body.ToString().Split('.').Last();
var data = this.SearchQuery.Where(m => m.Field == field);
if (data.Count() > 0)
{
return data.First().Value;
}
return "";
}
/// <summary>
/// 設置當前分頁對象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="data"></param>
/// <param name="dataTotal"></param>
/// <returns></returns>
public PageModel<T> Record<T>(IEnumerable<T> data, long dataTotal = -1) where T : class
{
var model = new PageModel<T>(data, dataTotal);
model.PageIndex = this.PageIndex;
model.PageSize = this.PageSize;
model.Order = this.Order;
model.SearchQuery = this.SearchQuery;
return model;
}
}
/// <summary>
/// 分頁模型
/// </summary>
public class PageModel<T> : PageModel,IHtmlString where T : class//,IHtmlString
{
public PageModel(IEnumerable<T> data, Int64 dataTotal = -1)
: base()
{
#region 設置數據總數
if (data != null)
DataSource = data;
else
DataSource = new List<T>();
if (dataTotal == -1)
{
if (data != null)
{
DataTotal = data.Count();
}
else
{
DataTotal = 0;
}
}
else
{
DataTotal = dataTotal;
}
#endregion
this.TableClassName = "baseui-table";
Colums = new List<PageColum<T>>();
}
/// <summary>
/// 數據源
/// </summary>
public virtual IEnumerable<T> DataSource { get; set; }
/// <summary>
/// 數據列
/// </summary>
private IList<PageColum<T>> Colums { get; set; }
/// <summary>
/// 數據的主鍵字段名
/// </summary>
private string SourcePrimaryKey { get; set; }
/// <summary>
/// 是否顯示選擇框
/// </summary>
private bool ShowCheckBox { get; set; }//顯示選擇框
/// <summary>
/// 列樣式類名
/// </summary>
private string TableClassName { get; set; }
/// <summary>
/// 提交的表單ID
/// </summary>
private string SearchFormId { get; set; }
/// <summary>
/// 要查詢的form表單ID
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public PageModel<T> SetSearchFormId(string id)
{
this.SearchFormId = id;
return this;
}
/// <summary>
/// 是否顯示選擇框
/// </summary>
/// <param name="show"></param>
/// <returns></returns>
public PageModel<T> SetShowCheckBox(bool show = false)
{
this.ShowCheckBox = show;
return this;
}
/// <summary>
/// 查詢字段
/// </summary>
/// <param name="expr"></param>
/// <returns></returns>
public string SearchName(Expression<Func<T, object>> expr)
{
return expr.Body.ToString().Split('.').Last();
}
/// <summary>
/// 查詢字段值
/// </summary>
/// <param name="expr"></param>
/// <returns></returns>
public object SearchValue(Expression<Func<T, object>> expr)
{
var data = this.SearchQuery.Where(m => m.Field == SearchName(expr));
if (data.Count() > 0)
{
return data.First().Value;
}
return "";
}
/// <summary>
/// 設置數據源的每一行的主鍵字段
/// </summary>
/// <param name="expr"></param>
/// <returns></returns>
public PageModel<T> SetSourceKey(Expression<Func<T, object>> expr)
{
this.SourcePrimaryKey = expr.Body.ToString().Split('.').Last();
return this;
}
/// <summary>
/// 設置表的樣式類
/// </summary>
/// <param name="className"></param>
/// <returns></returns>
public PageModel<T> SetClass(string className)
{
this.TableClassName = className;
return this;
}
/// <summary>
/// 設置顯示列
/// </summary>
/// <param name="expr"></param>
/// <param name="header"></param>
/// <param name="sort"></param>
/// <param name="style"></param>
/// <returns></returns>
public PageModel<T> ColumFor(Expression<Func<T, object>> expr, string header = "", bool sort = false, string style = "")
{
var exprBody = expr.Body.ToString();
if (exprBody.Contains("Convert"))
{
exprBody = exprBody.Replace("Convert", "").Replace("(", "").Replace(")", "");
}
var field = exprBody.Split('.').Last();//ExpressionHelper.GetExpressionText(expr);
if (string.IsNullOrEmpty(header))
{
try
{
var metadata = ModelMetadata.FromLambdaExpression<T, object>(expr, new ViewDataDictionary<T>());
string resolvedDisplayName = metadata.DisplayName ?? metadata.PropertyName ?? field.Split('.').Last();
header = HttpUtility.HtmlEncode(resolvedDisplayName);
}
catch//處理比如datetime類型的屬性
{
try
{
//ModelMetadataProvider provider = ModelMetadataProviders.Current;
//ModelMetadata containerMetadata = new ModelMetadata(provider, null, () => null, typeof(T), null);
//var metadata = containerMetadata.Properties.FirstOrDefault(m => m.PropertyName == field);
var metadata = GetModelMetadata<T>(field);
string resolvedDisplayName = metadata.DisplayName ?? metadata.PropertyName ?? field.Split('.').Last();
header = HttpUtility.HtmlEncode(resolvedDisplayName);
}
catch { }
}
}
this.Colums.Add(new PageColum<T>()
{
Field = field,
Header = header,
Style = style,
Sort = sort
});
return this;
}
/// <summary>
/// 列
/// </summary>
/// <param name="header"></param>
/// <param name="func"></param>
/// <param name="style"></param>
/// <returns></returns>
public PageModel<T> Colum(string header, Func<T, object> func, bool sort = false, string style = "")
{
this.Colums.Add(new PageColum<T>()
{
Field = "",
Header = header,
Style = style,
Format = func,
Sort = sort
});
return this;
}
public MvcHtmlString ToMvcHtmlString()
{
var Model = this;
var html = new StringBuilder();
if (Model.Order != null && Model.Order.Field != "")
{
html.Append(string.Format("<input name=\"[PageModel_Order]\" type=\"hidden\" value=\"{0}\">", Model.Order.Field + "|" + Model.Order.Order.ToString()));
}
else
{
html.Append(string.Format("<input name=\"[PageModel_Order]\" type=\"hidden\" value=\"{0}\">", ""));
}
html.Append(string.Format("<input name=\"[PageModel_PageIndex]\" type=\"hidden\" value=\"{0}\">", 1));
html.Append(string.Format("<input name=\"[PageModel_PageSize]\" type=\"hidden\" value=\"{0}\">", Model.PageSize.ToString()));
html.Append(string.Format("<input name=\"[PageModel_CheckSearch]\" type=\"hidden\" value=\"{0}\">", "1"));
html.Append(string.Format("<input name=\"[PageModel_SelectIds]\" type=\"hidden\" value=\"{0}\">", ""));
html.Append(string.Format("<input name=\"[PageModel_PageTotal]\" type=\"hidden\" value=\"{0}\">", Model.PageTotal));
#region 表
var columCount = 0;
html.Append(string.Format("<table class=\"{0}\">",this.TableClassName));
html.Append("<thead>");
html.Append("<tr>");
//html.Append("<th>[]</th>");//列頭
if (Colums != null)
{
columCount = Colums.Count;
if (this.ShowCheckBox)
{
columCount += 1;
html.Append("<th style=\"width: 40px;\" ><input class=\"baseui-checkbox\" onchange=\"PageModelCheck('pageModelCheck_All')\" id=\"pageModelCheck_All\" name=\"pageModelCheck_All\" type=\"checkbox\" value=\"true\">選擇</th>");
}
foreach (var colum in Colums)
{
if (colum.Sort)
{
html.Append(string.Format("<th ><a href=\"javascript:;\" onclick=\"SearchPageModelOrder('{2}','{0}');\">{1}</a></th>"
, colum.Field
, colum.Header
, this.SearchFormId));
}
else
{
html.Append(string.Format("<th ><a href=\"javascript:;\">{0}</a></th>", colum.Header));
}
}
}
html.Append("</tr>");
html.Append("</thead>");
html.Append("<tbody>");
if (Model != null && Model.DataSource.Count() > 0)
{
//html.Append("<td>[]</td>");//列
var rows = this.CreateRows();
foreach (var item in rows)
{
html.Append("<tr>");
if (this.ShowCheckBox)
{
html.Append(string.Format("<td><input class=\"baseui-checkbox\" onchange=\"PageModelCheck('pageModelCheck_{0}')\" id=\"pageModelCheck_{0}\" name=\"pageModelCheck_{0}\" type=\"checkbox\" value=\"true\"></td>", item.SourcePrimaryKey));
}
foreach (var colum in item.RowData)
{
html.Append(string.Format("<td>{0}</td>", colum.Vaule));
}
html.Append("</tr>");
}
html.Append("</tbody>");
html.Append("<tfoot>");
html.Append("<tr>");
html.Append(string.Format("<td colspan=\"{0}\">", columCount));
html.Append("<div class=\"baseui-paging\">");
if (Model.PageIndex == 1)
{
html.Append(" <a href=\"javascript:;\" class=\"baseui-paging-prev\">");
html.Append("<i class=\"iconfont\" ></i> 第一頁");
html.Append("</a>");
}
else
{
html.Append(string.Format(" <a href=\"javascript:;\" onclick=\"SearchPageModelPage('{0}','1');\" class=\"baseui-paging-prev\">", this.SearchFormId));
html.Append("<i class=\"iconfont\" ></i> 第一頁");
html.Append("</a>");
}
var pNumber = 10;
var start = GetStartNumber(Model.PageIndex, Model.PageTotal, pNumber);
for (int i = 0; i < pNumber; i++)
{
if (start + i <= Model.PageTotal)
{
if (start + i == Model.PageIndex)
{
html.Append(string.Format("<a href=\"javascript:;\" class=\"baseui-paging-item baseui-paging-current\">{0}</a>", start + i));
}
else
{
html.Append(string.Format("<a href=\"javascript:;\" onclick=\"SearchPageModelPage('{1}','{0}');\" class=\"baseui-paging-item\">{0}</a>", start + i, this.SearchFormId));
}
}
}
if (Model.PageIndex == Model.PageTotal || Model.PageTotal == 0)
{
html.Append("<a href=\"javascript:;\" class=\"baseui-paging-next\">最后一頁 <i class=\"iconfont\" ></i></a>");
}
else
{
html.Append(string.Format("<a href=\"javascript:;\" onclick=\"SearchPageModelPage('{1}','{0}');\" class=\"baseui-paging-next\">最后一頁 <i class=\"iconfont\"></i></a>", Model.PageTotal, this.SearchFormId));
}
html.Append(string.Format("<span class=\"baseui-paging-info\"><span class=\"baseui-paging-bold\">{0}/{1}</span>頁</span>", Model.PageIndex, Model.PageTotal));
html.Append("<span class=\"baseui-paging-which\">");
html.Append(string.Format("<input name=\"[psome_name]\" value=\"{0}\" type=\"text\">", Model.PageIndex));
html.Append("</span>");
html.Append(string.Format(" <a class=\"baseui-paging-info baseui-paging-goto\" href=\"javascript:;\" onclick=\"SearchPageModelPageJmp('{0}')\">跳轉</a>", this.SearchFormId));
html.Append(" </div>");
html.Append(" </td>");
html.Append("</tr>");
html.Append("</tfoot>");
html.Append("</table>");
}
else
{
html.Append("<tr>");
html.Append(string.Format("<td colspan=\"{0}\">暫無數據</td>", columCount));
html.Append("</tr>");
html.Append("</tbody>");
html.Append("</table>");
}
#endregion
html.Append("<script> function SearchPageModelOrder(searchFormId, value) { var oldValue = $(\"input[name='[PageModel_Order]']\").val(); var newValue = \"\"; if (oldValue == \"\" || oldValue == value + \"|Desc\") $(\"input[name='[PageModel_Order]']\").val(value + \"|Asc\"); else $(\"input[name='[PageModel_Order]']\").val(value + \"|Desc\"); $(\"input[name='[PageModel_CheckSearch]']\").val(\"0\");$(\"#\" + searchFormId).submit();}function SearchPageModelPage(searchFormId, value) {$(\"input[name='[PageModel_PageIndex]']\").val(value);$(\"input[name='[PageModel_CheckSearch]']\").val(\"0\");$(\"#\" + searchFormId).submit();} function SearchPageModelPageJmp(searchFormId) {var pindex = $(\"input[name='[psome_name]']\").val();$(\"input[name='[PageModel_PageIndex]']\").val(pindex);$(\"#\" + searchFormId).submit();}");
string js = "function PageModelCheck(v) {var id = v.split('_')[1]; var oldValue=$(\"input[name='[PageModel_SelectIds]']\").val(); if ($(\"#\" + v).is(\":checked\")) { if (id == \"All\") { $(\"input:checkbox\").each(function (i, ele) { var cid = $(ele).attr(\"id\"); if (cid.indexOf(\"pageModelCheck\") >= 0) { $(ele).attr(\"checked\", true); } }); $(\"input[name='[PageModel_SelectIds]']\").val(id); } else { if (oldValue.indexOf(id) < 0) { var newValue = oldValue + \"|\" + id; $(\"input[name='[PageModel_SelectIds]']\").val(newValue); } } } else { if (id == \"All\") { $(\"input:checkbox\").each(function (i, ele) { var cid = $(ele).attr(\"id\"); if (cid.indexOf(\"pageModelCheck\") >= 0) { $(ele).attr(\"checked\", false); } }); $(\"input[name='[PageModel_SelectIds]']\").val(\"\"); } else { if (oldValue.indexOf(id) >= 0) { var newValue = oldValue.replace(\"|\"+id,\"\"); $(\"input[name='[PageModel_SelectIds]']\").val(newValue); } } } }";
html.Append(js);
html.Append(" function PageModeSelectIds() { var ids = $(\"input[name='[PageModel_SelectIds]']\").val(); return ids;}");
html.Append(" </script>");
return MvcHtmlString.Create(html.ToString());
}
private List<PageRow> CreateRows()
{
var rows = new List<PageRow>();
//ModelMetadataProvider provider = ModelMetadataProviders.Current;
//ModelMetadata containerMetadata = new ModelMetadata(provider, null, () => null, typeof(T), null);
//var properties = containerMetadata.Properties.Select(m => m.PropertyName);
if (this.DataSource != null && this.DataSource.Count() > 0 && this.Colums != null && this.Colums.Count > 0)
{
foreach (var data in this.DataSource)
{
var row = new PageRow();
if (!string.IsNullOrEmpty(this.SourcePrimaryKey))
{
var keyValue = data.GetType().GetProperty(this.SourcePrimaryKey).GetValue(data, null);
row.SourcePrimaryKey = keyValue == null ? Guid.NewGuid().ToString() : keyValue.ToString();
}
else
{
row.SourcePrimaryKey = Guid.NewGuid().ToString();
}
foreach (var colum in this.Colums)
{
if (!string.IsNullOrEmpty(colum.Field))
{
var colValue = data.GetType().GetProperty(colum.Field).GetValue(data, null);
row.RowData.Add(new RowItem() { ColumId = colum.Id, Vaule = colValue, CheckFieldColum = true});
}
else
{
var html = Format(colum.Format, data);
row.RowData.Add(new RowItem() { ColumId = colum.Id, Vaule = HttpUtility.HtmlEncode(html), CheckFieldColum = false });
}
}
rows.Add(row);
}
}
return rows;
}
/// <summary>
/// 執行委托
/// </summary>
/// <param name="format">lambda表達示</param>
/// <param name="arg">委托參數</param>
/// <returns></returns>
private HelperResult Format(Func<T, object> format, dynamic arg)
{
var result = format.Invoke(arg);
return new HelperResult(tw =>
{
var helper = result as HelperResult;
if (helper != null)
{
helper.WriteTo(tw);
return;
}
IHtmlString htmlString = result as IHtmlString;
if (htmlString != null)
{
tw.Write(htmlString);
return;
}
if (result != null)
{
tw.Write(HttpUtility.HtmlEncode(result));
}
});
}
/// <summary>
/// 獲得一個數左右多少個的起始數
/// </summary>
/// <param name="helper"></param>
/// <param name="currentNumber">當前數</param>
/// <param name="maxNumber">最大數</param>
/// <param name="showCount">一共多少個</param>
/// <returns></returns>
private Int64 GetStartNumber(Int64 currentNumber, Int64 maxNumber, int showCount)
{
var arr = new List<Int64>();
var pAvg = showCount / 2;//左右顯示個數
for (int i = 1; i <= pAvg; i++)
{
if (currentNumber - i > 0)
{
arr.Add(currentNumber - i);
}
if (currentNumber + i <= maxNumber)
{
arr.Add(currentNumber + i);
}
}
arr.Add(currentNumber);
if (arr.Count < 10)
{
var le = showCount - arr.Count;
var min = arr.Min();
var max = arr.Max();
for (int i = 1; i <= le; i++)
{
if (min == 1 && max + 1 <= maxNumber)
{
arr.Add(max + 1);
}
if (max == maxNumber && min - 1 >= 1)
{
arr.Add(min - 1);
}
}
}
return arr.Min();
}
private ModelMetadata GetModelMetadata<T>(string PropertyName)
{
ModelMetadataProvider provider = ModelMetadataProviders.Current;
ModelMetadata containerMetadata = new ModelMetadata(provider, null, () => null, typeof(T), null);
var metadata = containerMetadata.Properties.FirstOrDefault(m => m.PropertyName == PropertyName);
return metadata;
}
public string ToHtmlString()
{
return this.ToMvcHtmlString().ToHtmlString();
}
}
}
9.添加一個設置對Html的替換規則類:MvcHtmlWrapper.cs
using System; using System.Collections.Generic; using System.Diagnostics.Contracts; using System.Linq; using System.Text; using System.Web; using System.Web.Mvc; namespace System.Web.Mvc { /// <summary> /// MvcHtmlString包裝器 /// 用於設置對Html的替換規則並在輸出時統一處理顯示Html /// </summary> public class MvcHtmlWrapper : IHtmlString { /// <summary> /// 構建一個MvcHtmlWrapper,如果是MvcHtmlWrapper則直接返回, /// 如果是是其它類型則構造MvcHtmlWrapper后返回 /// </summary> /// <param name="str">IHtmlString類型,實現了ToHtmlString接口的類型</param> /// <returns></returns> public static MvcHtmlWrapper Create(IHtmlString str) { Contract.Requires(str != null); if (str is MvcHtmlWrapper) return str as MvcHtmlWrapper; if (str is MvcHtmlString) return new MvcHtmlWrapper(str); Contract.Assert(false); return null; } IHtmlString HtmlStringInterface { get; set; } private string _htmlString; /// <summary> /// 獲取MvcHtmlString所生成的Html字符串 /// </summary> public string HtmlString { get { return _htmlString ?? (_htmlString = HtmlStringInterface.ToHtmlString()); } } /// <summary> /// 用於替換的Dict /// </summary> public List<Tuple<string, string>> ReplaceDict { get; set; } /// <summary> /// 構造MvcHtmlString包裝器 /// </summary> /// <param name="str">MvcHtmlString的實例,不允許為空</param> MvcHtmlWrapper(IHtmlString str) { Contract.Requires(str != null); HtmlStringInterface = str; ReplaceDict = new List<Tuple<string, string>>(); } /// <summary> /// 對ToHtmlString進行了重寫, 輸出HtmlString的內容,並按替換規則進行了替換 /// </summary> /// <returns></returns> public string ToHtmlString() { return ToString(); } /// <summary> /// 對ToString進行了重寫, 輸出HtmlString的內容,並按替換規則進行了替換 /// </summary> /// <returns></returns> public override string ToString() { var sb = new StringBuilder(HtmlString); foreach (var item in ReplaceDict) { if (!string.IsNullOrEmpty(item.Item1)) { sb.Replace(item.Item1, item.Item2); } } return sb.ToString(); } /// <summary> /// 添加替換原則 /// </summary> /// <param name="item1">被替換的字符串</param> /// <param name="item2">替換為的字符串</param> internal void Add(string item1, string item2) { ReplaceDict.Add(Tuple.Create(item1, item2)); } } }
10.添加一個MVC Html的擴展類:MvcHtmlStringExtension.cs
using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics.Contracts; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Web; using System.Web.Mvc; namespace System.Web.Mvc { [EditorBrowsable(EditorBrowsableState.Never)] public static class MvcHtmlStringExtension { /// <summary> /// 擴展分頁查詢表 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="helper"></param> /// <param name="SearchFormId">要查詢的form表單ID</param> /// <returns></returns> public static PageModel<T> PageTableFor<T>(this HtmlHelper<PageModel<T>> helper, string SearchFormId) where T : class { var model = helper.ViewData.Model; model = model.SetSearchFormId(SearchFormId); return model; } #region ForSearch /// <summary> /// 為當前表單元素添加搜索條件 /// </summary> /// <param name="str"></param> /// <param name="method">搜索方法</param> /// <param name="prefix">前綴</param> /// <param name="hasId">是否顯示Id,默認false</param> /// <param name="orGroup">如果想要支援Or,請設置一個Or分組</param> /// <returns></returns> public static MvcHtmlWrapper ForSearch(this IHtmlString str, QueryMethod? method, string prefix = "", bool hasId = false, string orGroup = "") { var wrapper = MvcHtmlWrapper.Create(str); Contract.Assert(null != wrapper); if (!method.HasValue) return wrapper; var html = wrapper.HtmlString; #region 如果是CheckBox,則去掉hidden if (html.Contains("type=\"checkbox\"")) { var checkMatch = Regex.Match(html, "<input name=\"[^\"]+\" type=\"hidden\" [^>]+ />"); if (checkMatch.Success) { wrapper.Add(checkMatch.Groups[0].Value, string.Empty); } } #endregion #region 替換掉Name var match = Regex.Match(html, "name=\"(?<name>[^\"]+)\""); var strInsert = ""; if (!string.IsNullOrWhiteSpace(prefix)) { strInsert += string.Format("({0})", prefix); } if (!string.IsNullOrWhiteSpace(orGroup)) { strInsert += string.Format("{{{0}}}", orGroup); } if (match.Success) { wrapper.Add(match.Groups[0].Value, string.Format("name=\"[{1}]{2}{0}\"", match.Groups[1].Value, method, strInsert)); } #endregion return wrapper; } #endregion } }
11.添加一個模型映射類:SearchModelBinder.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Web.Mvc; namespace System.Web.Mvc { /// <summary> /// 對SearchModel做為Action參數的綁定 /// </summary> public class SearchModelBinder : IModelBinder { public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { var model = (PageModel)(bindingContext.Model ?? new PageModel()); var dict = controllerContext.HttpContext.Request.Params; var keys = dict.AllKeys.Where(c => c.StartsWith("["));//我們認為只有[開頭的為需要處理的 if (keys.Count() != 0) { foreach (var key in keys) { if (!key.StartsWith("[")) continue; var val = dict[key]; //處理無值的情況 if (string.IsNullOrEmpty(val)) continue; if (key == "[PageModel_Order]")//排序 { var arr = val.Split('|'); if (arr.Length == 2) { model.Order = new QueryOrder() { Field = arr[0], Order = (OrderType)Enum.Parse(typeof(OrderType), arr[1]) }; } continue; } if (key == "[PageModel_PageIndex]")//頁碼 { try { var pindex = int.Parse(val); if (pindex > 1) model.PageIndex = pindex; else model.PageIndex = 1; if (keys.Contains("[PageModel_PageTotal]")) { var pt = int.Parse(dict["[PageModel_PageTotal]"]); if (pindex > pt) { model.PageIndex = 1; } } } catch { model.PageIndex = 1; } continue; } if (key == "[PageModel_PageTotal]") { continue; } if (key == "[PageModel_PageSize]")//每頁顯示數量 { try { var pSize = int.Parse(val); if (pSize > 0) model.PageSize = pSize; else model.PageSize = 20; } catch { model.PageSize = 20; } continue; } if (key == "[PageModel_CheckSearch]") { if (val == "1") { //model.che = 1; } continue; } if (key == "[PageModel_SelectIds]") { if (val == "All") { model.SelectAll = true; } else { model.SelectAll = false; model.SelectPrimaryKeys = val.Split('|').Where(m => m != "").ToList(); } continue; } if (key == "[psome_name]") { continue; } AddSearchItem(model, key, val); } } return model; } /// <summary> /// 將一組key=value添加入PageModel.SearchQuery /// </summary> /// <param name="model">PageModel</param> /// <param name="key">當前項的HtmlName</param> /// <param name="val">當前項的值</param> public static void AddSearchItem(PageModel model, string key, string val) { string field = "", prefix = "", orGroup = "", method = ""; var keywords = key.Split(']', ')', '}'); //將Html中的name分割為我們想要的幾個部分 foreach (var keyword in keywords) { if (Char.IsLetterOrDigit(keyword[0])) field = keyword; var last = keyword.Substring(1); if (keyword[0] == '(') prefix = last; if (keyword[0] == '[') method = last; if (keyword[0] == '{') orGroup = last; } if (string.IsNullOrEmpty(method)) return; if (!string.IsNullOrEmpty(field)) { var item = new ConditionItem { Field = field, Value = val.Trim(), Prefix = prefix, OrGroup = orGroup, Method = (QueryMethod)Enum.Parse(typeof(QueryMethod), method) }; model.SearchQuery.Add(item); } } } }
到此類庫封閉完畢。我們將WEB引用此類庫。
12.在Global.asax中添加:
ModelBinders.Binders.Add(typeof(PageModel), new SearchModelBinder());
13.現在我們WEB的Models中添加一個UserModel.cs進行實例展示:
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Web; namespace MvcApplication.Models { public class UserModel { [Display(Name = "編號")] public virtual string Id { get; set; } [Display(Name = "姓名")] public virtual string Name { get; set; } /// <summary> /// true:男 false:女 /// </summary> [Display(Name = "性別")] public virtual bool IsSex { get; set; } [Display(Name = "生日")] public virtual DateTime Birthday { get; set; } [Display(Name="性別")] public string SexName { get { return this.IsSex ? "男" : "女"; } } } }
14.修改HomeController:
using MvcApplication.Models; using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace MvcApplication.Controllers { public class HomeController : Controller { public ActionResult Index() { return View(); } public ActionResult Table(PageModel model) { var data = CreateData(); var dCount = data.Count; data = data.Skip((model.PageIndex - 1) * model.PageSize).Take(model.PageSize).ToList(); return PartialView(model.Record<UserModel>(data, dCount)); } private IList<UserModel> CreateData() { var list = new List<UserModel>(); for (int i = 0; i < 100; i++) { list.Add(new UserModel() { Id=i.ToString(), Name="姓名"+i.ToString(), IsSex=true, Birthday=DateTime.Now }); } return list; } public ActionResult About() { ViewBag.Message = "你的應用程序說明頁。"; return View(); } public ActionResult Contact() { ViewBag.Message = "你的聯系方式頁。"; return View(); } } }
15.修改Index.cshtml:
@{ ViewBag.Title = "主頁"; } @section featured { } <div id="tb001"> @Html.Action("Table") </div>
16.添加Table視圖:
@model PageModel<MvcApplication.Models.UserModel> @{ Layout = null; var ajaxOption = new AjaxOptions() { HttpMethod = "Post", UpdateTargetId = "tb001", OnBegin = "$('#pageMode_tableConetnt').mask();", OnComplete = "$('#pageMode_tableConetnt').unmask();", InsertionMode = InsertionMode.Replace }; } @using (Ajax.BeginForm("Table", "Home", null, ajaxOption, new { @id = "PageModel_Form" })) { <div> <div class="baseui-box"> <div class="baseui-box-head"> <h3 class="baseui-box-head-title">查詢</h3> <span class="baseui-box-head-text">Search</span> </div> <div class="baseui-box-container"> <div class="baseui-box-content"> 姓名: @Html.TextBox(Model.SearchName(m => m.Name), Model.SearchValue(m => m.Name), new { @class = "baseui-input" }).ForSearch(QueryMethod.Like) <input type="submit" value="查詢" class="baseui-button baseui-button-sorange" /> </div> </div> </div> <br /> <div class="baseui-box"> <div class="baseui-box-head"> <a href="@Url.Action("Add")" data-dialog-title="添加產品類型" data-dialog="true"> <i class="iconfont"></i> 添加 </a> </div> <div class="baseui-box-container"> <div class="baseui-box-content" style="padding: 0px !important;"> <div id="pageMode_tableConetnt"> @(Html.PageTableFor("PageModel_Form") .SetClass("baseui-table") .SetShowCheckBox(false) .SetSourceKey(m => m.Id) .ColumFor(m => m.Name) .ColumFor(m=>m.SexName) .Colum("生日",m=>m.Birthday.ToShortDateString()) .Colum("操作", @<text> @Html.ActionLink("修改", "Edit", new { id = @item.Id } ,new { data_dialog = "true", data_dialog_title = "修改產品類型" }) | @Ajax.ActionLink("刪除", "Delete", new { id = @item.Id }, ajaxOption , new { confirm_show = "true", confirm_tile = "提示", confirm_content = "是否刪除?", confirm_height = 210 }) </text>) ) </div> </div> </div> </div> </div> }
現在,我們看看運行效果:
當我們在姓名查詢框中輸入:張三
現在添加斷點:

這樣處理后,自己再進行處理封裝是不是很方便呢。
有些功能尚未實現,請自行修改
本實例到此結束,如有不懂的地方請留言,如果大家覺得好請支持留言,如果有更好的處理方法請留言告知,不勝感激,在此謝謝了!!!
