C#进阶系列——一步一步封装自己的HtmlHelper组件:BootstrapHelper(三:附源码)
前言:之前的两篇封装了一些基础的表单组件,这篇继续来封装几个基于bootstrap的其他组件。和上篇不同的是,这篇的有几个组件需要某些js文件的支持。
本文原创地址:http://www.cnblogs.com/landeanfen/p/5842030.html
BootstrapHelper系列文章目录
- C#进阶系列——一步一步封装自己的HtmlHelper组件:BootstrapHelper
- C#进阶系列——一步一步封装自己的HtmlHelper组件:BootstrapHelper(二)
- C#进阶系列——一步一步封装自己的HtmlHelper组件:BootstrapHelper(三:附源码)
一、NumberBoxExtensions
NumberBoxExtensions是一个基于bootstrap风格的数字文本框,基于之前博主介绍的自增器数字组件spinner去做的封装,不了解spinner组件的园友可以看看http://www.cnblogs.com/landeanfen/p/5461849.html里面介绍的第二个组件。
通过之前的介绍我们知道,自增组件spinner的初始化不需要写任何的js代码,直接通过配置html里面的data属性即可实现它的初始化,这样给我们的封装就带来了很大的方便,我们只需要将常用的初始化参数作为扩展方法的参数传进来,然后在后台变成相应的data属性返回到前端。
废话不多说,先将封装的源码摆上来。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc; namespace BootstrapExtensions
{
public static class NumberBoxExtensions
{
/// <summary>
/// 生成数字文本框
/// </summary>
/// <param name="html">扩展方法实例</param>
/// <param name="id">id</param>
/// <returns>返回数字文本框</returns>
public static MvcHtmlString NumberTextBox(this BootstrapHelper html, string id)
{
return NumberTextBox(html, id, null, null, null, null, null);
} /// <summary>
/// 生成数字文本框
/// </summary>
/// <param name="html">扩展方法实例</param>
/// <param name="id">id</param>
/// <param name="value">文本框的value值</param>
/// <returns>返回数字文本框</returns>
public static MvcHtmlString NumberTextBox(this BootstrapHelper html, string id, object value)
{
return NumberTextBox(html, id, value, null, null, null, null);
} /// <summary>
/// 生成数字文本框
/// </summary>
/// <param name="html">扩展方法实例</param>
/// <param name="value">文本框的value值</param>
/// <param name="min">自增长的最小值</param>
/// <param name="max">自增长的最大值</param>
/// <returns>返回数字文本框</returns>
public static MvcHtmlString NumberTextBox(this BootstrapHelper html, object value, int? min, int? max)
{
return NumberTextBox(html, null, value, min, max, null, null);
} /// <summary>
/// 生成数字文本框
/// </summary>
/// <param name="html">扩展方法实例</param>
/// <param name="id">id</param>
/// <param name="value">文本框的value值</param>
/// <param name="min">自增长的最小值</param>
/// <param name="max">自增长的最大值</param>
/// <returns>返回数字文本框</returns>
public static MvcHtmlString NumberTextBox(this BootstrapHelper html, string id, object value, int? min, int? max)
{
return NumberTextBox(html, id, value, min, max, null, null);
} /// <summary>
/// 生成数字文本框
/// </summary>
/// <param name="html">扩展方法实例</param>
/// <param name="id">id</param>
/// <param name="value">文本框的value值</param>
/// <param name="min">自增长的最小值</param>
/// <param name="max">自增长的最大值</param>
/// <param name="step">每次自增的数字</param>
/// <returns>返回数字文本框</returns>
public static MvcHtmlString NumberTextBox(this BootstrapHelper html, string id, object value, int? min, int? max, int? step)
{
return NumberTextBox(html, id, value, min, max, step, null);
} /// <summary>
/// 生成数字文本框
/// </summary>
/// <param name="html">扩展方法实例</param>
/// <param name="id">id</param>
/// <param name="value">文本框的value值</param>
/// <param name="min">自增长的最小值</param>
/// <param name="max">自增长的最大值</param>
/// <param name="step">每次自增的数字</param>
/// <param name="rule">自增规则</param>
/// <returns>返回数字文本框</returns>
public static MvcHtmlString NumberTextBox(this BootstrapHelper html, string id, object value, int? min, int? max, int? step, SpinningRule? rule)
{
TagBuilder tag = new TagBuilder("div");
tag.MergeAttribute("class", "input-group spinner");
tag.MergeAttribute("data-trigger", "spinner"); System.Text.StringBuilder sb = new System.Text.StringBuilder();
//sb.Append("<input type='text' class='form-control text-center' value='1' data-min='-10' data-max='10' data-step='2' data-rule='quantity'>");
sb.Append("<input type='text' class='form-control text-center' ");
if (!string.IsNullOrEmpty(id))
{
sb.Append("id='").Append(id).Append("' ");
}
if (value != null)
{
sb.Append("value='").Append(value.ToString()).Append("' ");
}
else
{
sb.Append("value='1' ");
}
if (min != null)
{
sb.Append("data-min='").Append(min).Append("' ");
}
if (max != null)
{
sb.Append("data-max='").Append(max).Append("' ");
}
if (step != null)
{
sb.Append("data-step='").Append(step).Append("' ");
}
if (rule != null)
{
sb.Append("data-rule='").Append(rule.ToString()).Append("' ");
}
else
{
sb.Append("data-rule='quantity' ");
}
sb.Append("/>"); sb.Append("<span class='input-group-addon'>");
sb.Append("<a href='javascript;;' class='spin-up' data-spin='up'><i class='fa fa-caret-up'></i></a>");
sb.Append("<a href='javascript:;' class='spin-down' data-spin='down'><i class='fa fa-caret-down'></i></a>");
sb.Append("</span>"); tag.InnerHtml = sb.ToString(); return MvcHtmlString.Create(tag.ToString()); }
} public enum SpinningRule
{
defaults,
currency,
quantity,
percent,
month,
day,
hour,
minute,
second,
}
}
NumberBoxExtensions.cs
除去id、value,我们自增组件初始化需要的参数主要有min、max、step、rule等,分别对应组件的data-min、data-max、data-step、data-rule等参数。
使用相当简单,首先在对应的页面引用相关的js和css文件,然后在cshtml里面这样调用即可:
@Bootstrap.NumberTextBox(null, "1", 1, 10, 2, null)
得到结果:

这样比我们每次都去copy一大段html代码要方便多了吧,你有没有一丝心动呢~~
二、DateTimeBoxExtensions
有了上面的数字组件作为基础,接下来就是封装时间组件了。博主同样打算使用data属性去做初始化,可是找了半天文档,datatimepicker里面没有自带data属性初始化的方式,没办法,只有博主自己去做data属性的初始化了。
1、初始方案
我们新建一个文件:bootstrap-datetimepicker-helper.js。里面的代码如下
$(function () {
var datetimedefault = {
locale: 'zh-CN', //中文化
};
$.each($(".date"), function (index, item) {
var data = $(item).data();
var param = $.extend({}, datetimedefault, data || {});
$(item).datetimepicker(param);
});
});
然后html代码这样写
<div class='input-group date' data-format="YYYY-MM-DD" data-maxDate="2017-01-10" data-minDate="2010-01-10">
<input type='text' class="form-control" />
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
貌似都没有问题,起初博主也以为没有任何问题。可是事与愿违!这里有一点博主没有考虑到,那就是Jquery里面的data()方法取到的属性名会全部转小写,也就是说,我们html里面写的data-maxDate,可是通过data()方法得到的结果却变成了maxdate,如下图:

然后在初始化datetimepicker的时候就报了js异常。此法行不通。
2、改进方案
既然上面的方法行不通,那我们就要改进啊,data()方法是否存在什么参数可以让它不转小写的?找了一圈,没找到啥答案。最后没办法,博主打算自行改造,于是js代码变成了这样:
$(function () {
var datetimedefault = {
format: 'YYYY-MM-DD',//日期格式化,只显示日期
locale: 'zh-CN', //中文化
maxDate: '2017-01-01',//最大日期
minDate: '2010-01-01', //最小日期
viewMode: 'days',
defaultDate: false,
disabledDates: false,
enabledDates: false,
};
$.each($(".date"), function (index, item) {
var data = $(item).data();
$.each(data, function (key, value) {
for (i in datetimedefault) {
if (key == i.toLowerCase()) {
datetimedefault[i] = value;
break;
}
}
});
//var param = $.extend({}, datetimedefault, data || {});
$(item).datetimepicker(datetimedefault);
});
});
原理就是比较data()方法得到的结果和datetimedefault的属性名转小写后进行对比,如果相同,则将html里面的data属性覆盖默认的属性。调试了几遍,基本没发现什么问题。
代码写成这样,确实可以解决我们上面的问题,但是需要我们的 datetimedefault 变量里面包含足够多的默认参数,这样才能达到覆盖的目的,当然项目中一般修改的就那么几个参数,这里只需要加上一些我们经常需要变化的默认属性即可。
好了,有上面的作为理论基础,我们的DataTimeBox也就好封装了。直接上代码吧。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc; namespace BootstrapExtensions
{
public static class DateTimeBoxExtensions
{
/// <summary>
/// 生成日期控件
/// </summary>
/// <param name="html">扩展方法实例</param>
/// <param name="id">文本框标签的id</param>
/// <returns>返回呈现日期控件的html标签</returns>
public static MvcHtmlString DateTimeBox(this BootstrapHelper html, string id)
{
return DateTimeBox(html, id, null, null, null, null, null, null);
} /// <summary>
/// 生成日期控件
/// </summary>
/// <param name="html">扩展方法实例</param>
/// <param name="id">文本框标签的id</param>
/// <param name="value">文本框标签的默认值</param>
/// <returns>返回呈现日期控件的html标签</returns>
public static MvcHtmlString DateTimeBox(this BootstrapHelper html, string id, object value)
{
return DateTimeBox(html, id, value, null, null, null, null, null);
} /// <summary>
/// 生成日期控件
/// </summary>
/// <param name="html">扩展方法实例</param>
/// <param name="id">文本框标签的id</param>
/// <param name="value">文本框标签的默认值</param>
/// <param name="format">显示日期的格式</param>
/// <param name="maxDate">日期的最小值</param>
/// <param name="minDate">日期的最大值</param>
/// <returns>返回呈现日期控件的html标签</returns>
public static MvcHtmlString DateTimeBox(this BootstrapHelper html, string id, object value, string format, string maxDate, string minDate)
{
return DateTimeBox(html, id, value, format, maxDate, minDate, null, null);
} /// <summary>
/// 生成日期控件
/// </summary>
/// <param name="html">扩展方法实例</param>
/// <param name="id">文本框标签的id</param>
/// <param name="value">文本框标签的默认值</param>
/// <param name="format">显示日期的格式</param>
/// <param name="maxDate">日期的最小值</param>
/// <param name="minDate">日期的最大值</param>
/// <param name="viewMode">日期控件的浏览模式</param>
/// <param name="showClear">是否显示清空按钮</param>
/// <returns>返回呈现日期控件的html标签</returns>
public static MvcHtmlString DateTimeBox(this BootstrapHelper html, string id, object value, string format, string maxDate, string minDate, string viewMode, bool? showClear)
{
TagBuilder tag = new TagBuilder("div");
tag.MergeAttribute("class", "input-group date");
if (!string.IsNullOrEmpty(format))
{
tag.MergeAttribute("data-format", format);
}
if (!string.IsNullOrEmpty(maxDate))
{
tag.MergeAttribute("data-maxDate", maxDate);
}
if (!string.IsNullOrEmpty(minDate))
{
tag.MergeAttribute("data-minDate", minDate);
}
if (!string.IsNullOrEmpty(viewMode))
{
tag.MergeAttribute("data-viewMode", viewMode);
}
if (showClear!=null)
{
tag.MergeAttribute("data-showClear", showClear.ToString());
} System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append("<input type='text' class='form-control'");
if(!string.IsNullOrEmpty(id))
{
sb.Append("id='").Append(id).Append("' ");
}
if (value != null)
{
sb.Append("value='").Append(value.ToString()).Append("' ");
} sb.Append("/>").Append("<span class='input-group-addon'>")
.Append("<span class='glyphicon glyphicon-calendar'></span>")
.Append("</span>"); tag.InnerHtml = sb.ToString(); return MvcHtmlString.Create(tag.ToString());
}
}
}
DateTimeBoxExtensions.cs
然后我们的cshtml页面只需要引用我们的js和css
<link href="~/Content/bootstrap-datetimepicker/css/bootstrap-datetimepicker.css" rel="stylesheet" />
<script src="~/Content/bootstrap-datetimepicker/js/moment-with-locales.js"></script>
<script src="~/Content/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js"></script>
<script src="~/Content/bootstrap-datetimepicker/js/bootstrap-datetimepicker-helper.js"></script>
然后直接使用
<div class="col-xs-3">
@Bootstrap.DateTimeBox("starttime", null, null, null, null, null, null)
</div>
<div class="col-xs-3">
@Bootstrap.DateTimeBox("endtime", null, null, null, null, null, null)
</div>
得到结果

三、TextareExtensions
关于textarea文本域的封装相对来说是比较简单的,因为本身它的结构和TextBox就差不多,我们直接给出封装的源码吧。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc; namespace BootstrapExtensions
{
public static class TextareExtensions
{
/// <summary>
/// textarea文本域
/// </summary>
/// <param name="html">扩展方法实例</param>
/// <param name="id">id</param>
/// <returns>html标签</returns>
public static MvcHtmlString TextAreaBox(this BootstrapHelper html, string id)
{
return TextAreaBox(html, id, null, null, null, null);
} /// <summary>
/// textarea文本域
/// </summary>
/// <param name="html">扩展方法实例</param>
/// <param name="id">id</param>
/// <param name="value">value</param>
/// <param name="cssClass">样式</param>
/// <returns>html标签</returns>
public static MvcHtmlString TextAreaBox(this BootstrapHelper html, string id, object value, string cssClass)
{
return TextAreaBox(html, id, value, cssClass, null, null);
} /// <summary>
/// textarea文本域
/// </summary>
/// <param name="html">扩展方法实例</param>
/// <param name="id">id</param>
/// <param name="value">value</param>
/// <param name="cssClass">样式</param>
/// <param name="rows">行数</param>
/// <returns>html标签</returns>
public static MvcHtmlString TextAreaBox(this BootstrapHelper html, string id, object value, string cssClass, int? rows)
{
return TextAreaBox(html, id, value, cssClass, rows, null);
} /// <summary>
/// textarea文本域
/// </summary>
/// <param name="html">扩展方法实例</param>
/// <param name="id">id</param>
/// <param name="value">value</param>
/// <param name="cssClass">样式</param>
/// <param name="rows">行数</param>
/// <param name="cols">列数</param>
/// <returns>html标签</returns>
public static MvcHtmlString TextAreaBox(this BootstrapHelper html, string id, object value, string cssClass, int? rows, int? cols)
{
TagBuilder tag = new TagBuilder("textarea");
tag.AddCssClass("form-control");
if (!string.IsNullOrEmpty(id))
{
tag.MergeAttribute("id", id);
}
if (value != null)
{
tag.MergeAttribute("value", value.ToString());
}
if (!string.IsNullOrEmpty(cssClass))
{
tag.AddCssClass(cssClass);
}
if (rows != null)
{
tag.MergeAttribute("rows", rows.ToString());
}
if (cols != null)
{
tag.MergeAttribute("cols", cols.ToString());
} return MvcHtmlString.Create(tag.ToString());
}
}
}
TextAreaExtensions.cs
只支持几个最简单的参数rows和cols,如果你的项目有一些特殊的需求,比如需要初始化成富文本编辑框,你也可以自己去改进。
使用方法
<div>
@Bootstrap.TextAreaBox("id", "", "", 3, 5)
</div>
这里有一个问题要提一下,就是我们直接这样写,得到的结果却是:

貌似我们的cols属性没有起作用,原来,只要你的标签加了class='form-control'样式,那它就会在满撑整个div,解决的方法也很简单,比如我们可以在div上面做些处理:
<div class="col-xs-3">
@Bootstrap.TextAreaBox("", "", "", 3, 5)
</div>

既然cols属性没有起作用,其实参数里面的cols可以考虑去掉。
四、SelectExtensions
又到了纠结的select下拉框。为什么说它纠结呢,因为封装它的时候要考虑很多问题,比如:
- <optgroup>和<option>如何处理
- 静态的option值如何传到后台
- 是封装原始的select还是封装成基于某些组件(比如select2)的select
- 方法和事件该如何处理等等
后来转念一想,封装的目的是为了什么?不就是为了使用起来更加方便吗,如果封得太死,使用起来能够方便吗?后来所幸直接封装成最简单的select算了。博主打算这样做:
如果是静态的option,直接写原生的select标签;如果是动态的option,则传递对应的url到后台,取到数据后生成option。封装的代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc; namespace BootstrapExtensions
{
public static class SelectExtensions
{
/// <summary>
/// 返回select标签
/// </summary>
/// <param name="html">扩展方法实例</param>
/// <param name="id">标签id</param>
/// <returns>select标签</returns>
public static MvcHtmlString SelectBox(this BootstrapHelper html, string id)
{
return SelectBox(html, id, null, null, null, null, null, null);
} /// <summary>
/// 返回select标签
/// </summary>
/// <param name="html">扩展方法实例</param>
/// <param name="id">标签id</param>
/// <param name="value">标签选中值</param>
/// <returns>select标签</returns>
public static MvcHtmlString SelectBox(this BootstrapHelper html, string id, object value)
{
return SelectBox(html, id, value, null, null, null, null, null);
} /// <summary>
/// 返回select标签
/// </summary>
/// <param name="html">扩展方法实例</param>
/// <param name="id">标签id</param>
/// <param name="value">标签选中值</param>
/// <param name="cssClass">标签样式</param>
/// <returns>select标签</returns>
public static MvcHtmlString SelectBox(this BootstrapHelper html, string id, object value, string cssClass)
{
return SelectBox(html, id, value, cssClass, null, null, null, null);
} /// <summary>
/// 返回select标签
/// </summary>
/// <param name="html">扩展方法实例</param>
/// <param name="id">标签id</param>
/// <param name="value">标签选中值</param>
/// <param name="cssClass">标签样式</param>
/// <param name="url">请求数据的url</param>
/// <param name="textField">显示字段</param>
/// <param name="valueField">值字段</param>
/// <returns>select标签</returns>
public static MvcHtmlString SelectBox(this BootstrapHelper html, string id, object value, string cssClass, string url, string textField, string valueField)
{
return SelectBox(html, id, value, cssClass, url, null, textField, valueField);
} /// <summary>
/// 返回select标签
/// </summary>
/// <param name="html">扩展方法实例</param>
/// <param name="id">标签id</param>
/// <param name="value">标签选中值</param>
/// <param name="cssClass">标签样式</param>
/// <param name="url">请求数据的url</param>
/// <param name="param">请求的参数</param>
/// <param name="textField">显示字段</param>
/// <param name="valueField">值字段</param>
/// <param name="multiple">是否多选</param>
/// <returns>select标签</returns>
public static MvcHtmlString SelectBox(this BootstrapHelper html, string id, object value, string cssClass, string url, string param, string textField, string valueField, bool multiple = false)
{
TagBuilder tag = new TagBuilder("select");
tag.AddCssClass("form-control");
if (!string.IsNullOrEmpty(id))
{
tag.MergeAttribute("id", id);
}
if (value != null)
{
tag.MergeAttribute("value", value.ToString());
}
if (!string.IsNullOrEmpty(cssClass))
{
tag.AddCssClass(cssClass);
}
if (!string.IsNullOrEmpty(url))
{
tag.MergeAttribute("data-url", url);
}
if (!string.IsNullOrEmpty(param))
{
tag.MergeAttribute("data-param", param);
}
if (!string.IsNullOrEmpty(valueField))
{
tag.MergeAttribute("data-value-field", valueField);
}
if (!string.IsNullOrEmpty(textField))
{
tag.MergeAttribute("data-text-field", textField);
}
if (multiple)
{
tag.MergeAttribute("multiple", "multiple");
} return MvcHtmlString.Create(tag.ToString());
}
}
}
SelectExtensions.cs
然后前端使用js去初始化,需要有一个js文件utility.combobox.js:
(function ($) {
//1.定义jquery的扩展方法combobox
$.fn.combobox = function (options, param) {
if (typeof options == 'string') {
return $.fn.combobox.methods[options](this, param);
}
//2.将调用时候传过来的参数和default参数合并
options = $.extend({}, $.fn.combobox.defaults, options || {});
//3.添加默认值
var target = $(this);
target.attr('valuefield', options.valueField);
target.attr('textfield', options.textField);
target.empty();
var option = $('<option></option>');
option.attr('value', '');
option.text(options.placeholder);
target.append(option);
//4.判断用户传过来的参数列表里面是否包含数据data数据集,如果包含,不用发ajax从后台取,否则否送ajax从后台取数据
if (options.data) {
init(target, options.data);
}
else {
//var param = {};
options.onBeforeLoad.call(target, options.param);
if (!options.url) return;
if (typeof options.param == "string") {
options.param = JSON.parse(options.param);
}
$.getJSON(options.url, options.param, function (data) {
init(target, data);
});
}
function init(target, data) {
$.each(data, function (i, item) {
var option = $('<option></option>');
option.attr('value', item[options.valueField]);
option.text(item[options.textField]);
target.append(option);
});
options.onLoadSuccess.call(target);
}
target.unbind("change");
target.on("change", function (e) {
if (options.onChange)
return options.onChange(target.val());
});
}
//5.如果传过来的是字符串,代表调用方法。
$.fn.combobox.methods = {
getValue: function (jq) {
return jq.val();
},
setValue: function (jq, param) {
jq.val(param);
},
load: function (jq, url) {
$.getJSON(url, function (data) {
jq.empty();
var option = $('<option></option>');
option.attr('value', '');
option.text('请选择');
jq.append(option);
$.each(data, function (i, item) {
var option = $('<option></option>');
option.attr('value', item[jq.attr('valuefield')]);
option.text(item[jq.attr('textfield')]);
jq.append(option);
});
});
}
};
//6.默认参数列表
$.fn.combobox.defaults = {
url: null,
param: null,
data: null,
valueField: 'value',
textField: 'text',
placeholder: '请选择',
onBeforeLoad: function (param) { },
onLoadSuccess: function () { },
onChange: function (value) { }
};
//这一段是新加的,在页面初始化完成之后调用初始化方法
$(document).ready(function () {
$('select').each(function () {
var $combobox = $(this);
$.fn.combobox.call($combobox, $combobox.data());
})
});
})(jQuery);
这个js文件来源于博主之前的一篇文章http://www.cnblogs.com/landeanfen/p/5159911.html
然后前端调用
<div class="col-xs-2">
@Bootstrap.SelectBox("sel", null, null, "/Home/GetDept", null, "Name", "Id")
</div>
五、总结
至此,我们BootstrapHelper第一个版本的封装基本算是完成了,主要封装的组件有如下几个:

当然还有大家最喜欢源码分享了。源码地址
如果你觉得本文能够帮到你,请帮忙推荐吧。
本文原创出处:http://www.cnblogs.com/landeanfen/
欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利
C#进阶系列——一步一步封装自己的HtmlHelper组件:BootstrapHelper(三:附源码)的更多相关文章
- 循序渐进做项目系列(4)迷你QQ篇(2)——视频聊天!(附源码)
一·效果展示 源码派送:MiniQQ1.1 文字聊天的实现参见:循序渐进做项目系列(3):迷你QQ篇(1)——实现客户端互相聊天 二·服务端设计 对于实现视频聊天而言,服务端最核心的工作就是要构造多媒 ...
- openlayers4 入门开发系列之前端动态渲染克里金插值 kriging 篇(附源码下载)
前言 openlayers4 官网的 api 文档介绍地址 openlayers4 api,里面详细的介绍 openlayers4 各个类的介绍,还有就是在线例子:openlayers4 官网在线例子 ...
- SSM 三大框架系列:Spring 5 + Spring MVC 5 + MyBatis 3.5 整合(附源码)
之前整理了一下新版本的 SSM 三大框架,这篇文章是关于它的整合过程和项目源码,版本号分别为:Spring 5.2.2.RELEASE.SpringMVC 5.2.2.RELEASE.MyBatis ...
- C#进阶系列——一步一步封装自己的HtmlHelper组件:BootstrapHelper
前言:之前学习过很多的Bootstrap组件,博主就在脑海里构思:是否可以封装一套自己Bootstrap组件库呢.再加上看到MVC的Razor语法里面直接通过后台方法输出前端控件的方式,于是打算仿照H ...
- MVC系列——MVC源码学习:打造自己的MVC框架(二:附源码)
前言:上篇介绍了下 MVC5 的核心原理,整篇文章比较偏理论,所以相对比较枯燥.今天就来根据上篇的理论一步一步进行实践,通过自己写的一个简易MVC框架逐步理解,相信通过这一篇的实践,你会对MVC有一个 ...
- 【转】.NET(C#):浅谈程序集清单资源和RESX资源 关于单元测试的思考--Asp.Net Core单元测试最佳实践 封装自己的dapper lambda扩展-设计篇 编写自己的dapper lambda扩展-使用篇 正确理解CAP定理 Quartz.NET的使用(附源码) 整理自己的.net工具库 GC的前世与今生 Visual Studio Package 插件开发之自动生
[转].NET(C#):浅谈程序集清单资源和RESX资源 目录 程序集清单资源 RESX资源文件 使用ResourceReader和ResourceSet解析二进制资源文件 使用ResourceM ...
- 基于Python接口自动化测试框架+数据与代码分离(进阶篇)附源码
引言 在上一篇<基于Python接口自动化测试框架(初级篇)附源码>讲过了接口自动化测试框架的搭建,最核心的模块功能就是测试数据库初始化,再来看看之前的框架结构: 可以看出testcase ...
- arcgis api 3.x for js 入门开发系列批量叠加 zip 压缩 SHP 图层优化篇(附源码下载)
前言 关于本篇功能实现用到的 api 涉及类看不懂的,请参照 esri 官网的 arcgis api 3.x for js:esri 官网 api,里面详细的介绍 arcgis api 3.x 各个类 ...
- openlayers4 入门开发系列之地图导航控件篇(附源码下载)
前言 openlayers4 官网的 api 文档介绍地址 openlayers4 api,里面详细的介绍 openlayers4 各个类的介绍,还有就是在线例子:openlayers4 官网在线例子 ...
随机推荐
- 利用Python进行数据分析(15) pandas基础: 字符串操作
字符串对象方法 split()方法拆分字符串: strip()方法去掉空白符和换行符: split()结合strip()使用: "+"符号可以将多个字符串连接起来: join( ...
- linux iptables常用命令之配置生产环境iptables及优化
在了解iptables的详细原理之前,我们先来看下如何使用iptables,以终为始,有可能会让你对iptables了解更深 所以接下来我们以配置一个生产环境下的iptables为例来讲讲它的常用命令 ...
- Oracle 中的操作符
1.union:对两个结果集进行并集操作,不包括重复行,同时进行默认规则的排序: SELECT * FROM emp WHERE sal < UNION SELECT * FROM emp WH ...
- Windows下删除.svn文件夹的最简易方法
建立一个文本文件,取名为kill-svn-folders.reg(扩展名由txt改为reg),内容如下: Windows Registry Editor Version 5.00 [HKEY_LOCA ...
- 配置rsync服务,数据同步。
这部分设计服务器端和客户端. [服务器端] 如果服务器没有安装rsync服务则使用yum安装rsync服务. yum install rsync 然后 vim /etc/xinetd.d/rsync ...
- jQuery 中bind(),live(),delegate(),on() 区别(转)
当我们试图绑定一些事件到DOM元素上的时候,我相信上面这4个方法是最常用的.而它们之间到底有什么不同呢?在什么场合下用什么方法是最有效的呢? 准备知识: 当我们在开始的时候,有些知识是必须具备的: D ...
- arcgis engine 中出现的内存堆栈溢出问题。
两种解决方案: 1.循环加载mxd文档的时候出现的堆栈溢出,解决办法是每次循环结束时清空FeatureLayer,感觉并不好,但是确实可以实现功能. 2.循环调取featureclass的search ...
- Android Weekly Notes Issue #223
Android Weekly Issue #223 September 18th, 2016 Android Weekly Issue #223 本期内容包括: Offline时间戳处理; Acces ...
- iOS 下拉刷新-上拉加载原理
前言 讲下拉刷新及上拉加载之前先给大家解释UIScrollView的几个属性 contentSize是UIScrollView可以滚动的区域. contentOfinset 苹果官方文档的解释是&qu ...
- 15-static和extern关键字1-对函数的作用
一.extern与函数 如果一个程序中有多个源文件(.c),编译成功会生成对应的多个目标文件(.obj),这些目标文件还不能单独运行,因为这些目标文件之间可能会有关联,比如a.obj可能会调用c.ob ...