[转]9.2.3 .net core 通过TagHelper封装控件
本文转自:https://www.cnblogs.com/BenDan2002/p/6170624.html
.net core 除了继续保留.net framework的HtmlHelper的写法以外,还提供了TagHelper和ViewComponent方式生成控件。
我们本节说的是使用TagHelper来生成控件。不过严格的说起来,TagHelper是对客户端html元素的辅助类,例如渲染、增加服务端特性等。我们可以使用 taghelper 定义自己的标签或更改已知标签。使用TagHelper,VS.net编译环境也可以自动感知,并提供智能提示。因为TagHelper生成的控件,看起来像一个原生的HTML标签一样,也更利于美工进行页面美化。
例如一个lable控件 <label asp-for="Email"></label>,生成的最终html就是这样:<label for="Email">xxx@xx.com</label>
如果要使用TagHelper,除了在页面中using 命名空间之外,还需要使用@addTagHelper来使TagHelper可用。由于我们会编写不止一个TagHelper,且在多个cshtml页面使用,因此我们将如下代码
@using MicroStrutLibrary.Presentation.Web.Controls
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, MicroStrutLibrary.Presentation.Web.Controls
写在视图文件 Views/_ViewImports.cshtml中。写在Views/_ViewImports.cshtml的意思是,默认所有的在 Views 和Views下级目录中的视图文件都可以使用TagHelper,通配符 ("*") 来指定在特定程序集(Microsoft.AspNetCore.Mvc.TagHelpers和MicroStrutLibrary.Presentation.Web.Controls)中的所有的 TagHelpers 在 Views目录和子目录中的视图文件中都是可用的。第一个程序集是mvc自带的,第二个是我们自己的控件程序集。具体的说明大家还是看.net core文档吧。
下面,我们仍旧以上一节介绍的多选控件MultiSelect为例,说明下我们的TagHelper封装过程。
MultiSelect在cshtml中的写法如下,asp-dataSource传入的是数据源,select的所有下拉内容都是通过datasource生成的,而asp-value传入的是选中的项:
1 @model Dictionary<string, string>
2 @{
3 List<string> values = ViewData.Get<List<string>>("Values");
4 }
5
6 <multiSelect id="txtInput0" asp-dataSource="@Model" asp-value="@values"></multiSelect>
Model和values从controller中传过来的,具体如下:
1 public IActionResult MultiSelect()
2 {
3 Dictionary<string, string> data = new Dictionary<string, string>();
4 data.Add("1", "Aaaaa");
5 data.Add("2", "Aaron");
6 data.Add("3", "Abbott");
7 data.Add("4", "Abel");
8 data.Add("5", "Abner");
9 data.Add("6", "Abraham");
10 data.Add("7", "Adair");
11 data.Add("8", "Adam");
12 data.Add("9", "Addison");
13
14 List<string> value = new List<string>();
15 value.Add("2");
16 value.Add("7");
17 ViewData["Values"] = value;
18
19 return View(data);
20 }
这样,最终生成的html代码和页面如下:
1 <div>
2 <select id="txtInput0" name="txtInput0" multiple="multiple">
3 <option value="1" >Aaaaa</option>
4 <option value="2" selected>Aaron</option>
5 <option value="3" >Abbott</option>
6 <option value="4" >Abel</option>
7 <option value="5" >Abner</option>
8 <option value="6" >Abraham</option>
9 <option value="7" selected>Adair</option>
10 <option value="8" >Adam</option>
11 <option value="9" >Addison</option>
12 </select>
13 <script>
14 require(['jquery', 'bootstrap', 'multiselect'], function ($) {
15 $(function(){
16 $("#txtInput0").multiselect({
17 nonSelectedText: '请选择',
18 enableFiltering: true,//是否显示过滤
19 filterPlaceholder: '查找',
20 includeSelectAllOption: true,//是否显示全选
21 selectAllText: '全选',
22 numberDisplayed: 5//显示条数
23 });
24 });
25 });
26 </script>
27 </div>
MultiSelect在页面展示如下图
按照设计,MultiSelect应该能够传入:1、数据源,也就是下拉列表的所有数据;2、已选项,已选择的数据;3、下拉列表的展示条数,以免条数过多,影响页面;4、是否只读等属性,更好的控制控件的展示内容。当然了,还应该包括一个For属性,这个For属性的意思是通过页面的Model绑定,自动生成控件Id和已选择数据项等内容。
由于所有的TagHelper都继承于一个基类TagHelper,我们首先看下TagHelper抽象类:
1 //
2 // 摘要:
3 // Class used to filter matching HTML elements.
4 public abstract class TagHelper : ITagHelper
5 {
6 protected TagHelper();
7
8 //
9 // 备注:
10 // Default order is 0.
11 public virtual int Order { get; }
12
13 //
14 public virtual void Init(TagHelperContext context);
15 //
16 // 摘要:
17 // Synchronously executes the Microsoft.AspNetCore.Razor.TagHelpers.TagHelper with
18 // the given context and output.
19 //
20 // 参数:
21 // context:
22 // Contains information associated with the current HTML tag.
23 //
24 // output:
25 // A stateful HTML element used to generate an HTML tag.
26 public virtual void Process(TagHelperContext context, TagHelperOutput output);
27 //
28 // 摘要:
29 // Asynchronously executes the Microsoft.AspNetCore.Razor.TagHelpers.TagHelper with
30 // the given context and output.
31 //
32 // 参数:
33 // context:
34 // Contains information associated with the current HTML tag.
35 //
36 // output:
37 // A stateful HTML element used to generate an HTML tag.
38 //
39 // 返回结果:
40 // A System.Threading.Tasks.Task that on completion updates the output.
41 //
42 // 备注:
43 // By default this calls into Microsoft.AspNetCore.Razor.TagHelpers.TagHelper.Process(Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContext,Microsoft.AspNetCore.Razor.TagHelpers.TagHelperOutput).
44 public virtual Task ProcessAsync(TagHelperContext context, TagHelperOutput output);
45 }
这里最重要的就是Process方法和ProcessAsync方法。这两个方法,一个是同步,一个是异步,作用都是输出页面html代码。
我们再来看封装后的MultiSelectTagHelper的代码:
1 [HtmlTargetElement("multiSelect", Attributes = ForAttributeName)]
2 [HtmlTargetElement("multiSelect", Attributes = ValueAttributeName)]
3 [HtmlTargetElement("multiSelect", Attributes = ShowItemCountAttributeName)]
4 [HtmlTargetElement("multiSelect", Attributes = DataSourceAttributeName)]
5 [HtmlTargetElement("multiSelect", Attributes = ReadonlyAttributeName)]
6 public class MultiSelectTagHelper : TagHelper
7 {
8 private readonly IHtmlGenerator generator;
9
10 public MultiSelectTagHelper(IHtmlGenerator generator)
11 {
12 this.generator = generator;
13 }
14
15 private const string ForAttributeName = "asp-for";
16 private const string ValueAttributeName = "asp-value";
17 private const string ShowItemCountAttributeName = "asp-showItemCount";
18 private const string DataSourceAttributeName = "asp-dataSource";
19 private const string ReadonlyAttributeName = "asp-readonly";
20
21 [HtmlAttributeNotBound]
22 [ViewContext]
23 public ViewContext ViewContext { get; set; }
24
25 [HtmlAttributeName(ForAttributeName)]
26 public ModelExpression For { get; set; }
27
28 [HtmlAttributeName(ValueAttributeName)]
29 public List<string> Value { get; set; }
30
31 [HtmlAttributeName(ShowItemCountAttributeName)]
32 public int ShowItemCount { get; set; } = 5;
33
34 [HtmlAttributeName(DataSourceAttributeName)]
35 public Dictionary<string, string> DataSource { get; set; }
36
37 [HtmlAttributeName(ReadonlyAttributeName)]
38 public bool Readonly { get; set; }
39
40 public override void Process(TagHelperContext context, TagHelperOutput output)
41 {
42 MicroStrutLibraryExceptionHelper.IsNull(context, this.GetType().FullName, LogLevel.Error, "context参数值为空");
43 MicroStrutLibraryExceptionHelper.IsNull(output, this.GetType().FullName, LogLevel.Error, "output");
44
45 output.TagName = "div";
46 //output.Attributes.Add("class", "multiselect-drop");
47
48 MultiSelectList selectList = new MultiSelectList(this.DataSource, "Key", "Value", this.Value);
49
50 HtmlContentBuilder builder = new HtmlContentBuilder();
51
52 string id;
53 if (For == null)
54 {
55 id = output.Attributes["id"].Value.ToString();
56 output.Attributes.Remove(output.Attributes["id"]);
57
58 string options = string.Empty;
59 foreach (SelectListItem item in selectList)
60 {
61 options += $"<option value=\"{item.Value}\" {(item.Selected ? "selected" : "")}>{item.Text}</option>";
62 }
63
64 builder.AppendHtml($"<select id=\"{id}\" name=\"{id}\" multiple=\"multiple\">{options}</select>");
65 }
66 else
67 {
68 id = For.Name;
69
70 TagBuilder dropDown = generator.GenerateSelect(ViewContext, For.ModelExplorer, For.Name, string.Empty, selectList, true, null);
71 builder.AppendHtml(dropDown);
72 }
73
74 string readOnly = "";
75 if (this.Readonly)
76 {
77 readOnly = $"$('#{id} +div > button').attr('disabled', true);";
78 }
79 string script = string.Format(@"
80 <script>
81 require(['jquery', 'bootstrap', 'multiselect'], function ($) {{
82 $(function(){{
83 $(""#{0}"").multiselect({{
84 nonSelectedText: '请选择',
85 enableFiltering: true,//是否显示过滤
86 filterPlaceholder: '查找',
87 includeSelectAllOption: true,//是否显示全选
88 selectAllText: '全选',
89 numberDisplayed: {1}//显示条数
90 }});
91 {2}
92 }});
93 }});
94 </script>
95 ", id, this.ShowItemCount, readOnly);
96
97 builder.AppendHtml(script);
98
99 output.Content.AppendHtml(builder);
100
101 base.Process(context, output);
102 }
103 }
为了在编写程序时不会出错,我们定义了五个常量ForAttributeName 、ValueAttributeName、ShowItemCountAttributeName、DataSourceAttributeName、ReadonlyAttributeName,分别代表MultiSelect标签的asp-for等Attribute。也就是MultiSelect传入的数据源、已选项、下拉列表的展示条数、是否只读等属性、For属性。
类定义上面[HtmlTargetElement("multiSelect", Attributes = ValueAttributeName)]的作用是在multiSelect标签上生成ValueAttributeName对应值asp-value的Attribute。
属性上面
[HtmlAttributeName(ValueAttributeName)]
public List<string> Value { get; set; }
的作用是告诉multiSelect标签,asp-value传入的应该是个List<string>类型。这里需要注意的是,在各种文档、教程中,大多数情况下,Attribute传入的类型都是一些简单类型,例如字符串、数字等。其实Attribute是可以传入复杂的类型的,例如我们这里传入的List<string>。页面中也就要如下的使用方式:
1 @model Dictionary<string, string>
2 @{
3 List<string> values = ViewData.Get<List<string>>("Values");
4 }
5
6 <multiSelect id="txtInput0" asp-dataSource="@Model" asp-value="@values"></multiSelect>
还有一个属性ViewContext,这个属性不是显式传入的,而是TagHelper创建时,系统自动赋值的,含义是当前的视图执行上下文Microsoft.AspNetCore.Mvc.Rendering.ViewContext。
[HtmlAttributeNotBound]
[ViewContext]
public ViewContext ViewContext { get; set; }
这里还有一个需要重要说明的是For方式public ModelExpression For { get; set; }。普通方式下,multiSelect的Id、Value都是从页面传入的,但是For方式是与Model绑定的,如同HtmlHelper的TextBox、TextBoxFor的区别一样。例如,一个人可能有多个职责,人的职责属性是DutyList,所有职责的数据DutyDictionary,在cshtml页面中就按照如下方式写multiselect:
@model UserInfo
<multiSelect asp-dataSource="@DutyDictionary" asp-for="DutyList"></multiSelect>
MultiSelect构造函数中,传入了一个IHtmlGenerator参数,这个是通过DI容器自动解析出来的,缺省情况下的实现类是DefaultHtmlGenerator。这个类的主要作用是生成各种html标签。我们在For方式用到了自动生成select标签的方法。TagBuilder dropDown = generator.GenerateSelect(ViewContext, For.ModelExplorer, string.Empty, For.Name, selectList, true, null);
最后就是重写Process方法。其实这个方法还是比较简单的,当For方式时,通过For自动生成select;否则就自己写select。我们其中还写了一段脚本,脚本中直接引用了jquery的MultiSelect脚本,
require(['jquery', 'bootstrap', 'multiselect'], function ($) {{…
这里我们使用systemjs这个通用的javascript模块加载器,其中的jquery、bootstrap、multiselect都是在system.config中定义的。System.config.js的代码大体如下,至于为什么这么写,大家还是搜网上帮助吧:
1 System.config({
2 bundles: {
3 },
4 paths: {
5 "external:": externalUrl+"/"
6 },
7 map: {
8 "jquery": "external:lib/jquery/jquery.min.js",
9 "bootstrap": "external:lib/bootstrap/js/bootstrap.min.js",
10
11 //--
12 "jquery-ui": "external:lib/jquery/jquery-ui/jquery-ui.bundle.min.js",
13
14 //--Plugins
15 "multiselect": "external:lib/plugins/multiselect/js/bootstrap-multiselect.min.js"
16 …
17 },
18 meta: {
19 '*.css': {
20 loader: 'external:lib/system/css-loader/css.js'
21 },
22 'jquery': {
23 format: 'global',
24 exports: 'jQuery'
25 },
26 'bootstrap': {
27 format: 'global',
28 deps: ['jquery']
29 },
30 'jquery-ui': {
31 format: 'global',
32 deps: ['jquery','./jquery-ui.min.css']
33 },
34 'multiselect': {
35 format: 'global',
36 deps: ['../css/bootstrap-multiselect.min.css']
37 },
38 …
39 },
40 packages: {
41 '/js': {
42 format: 'cjs',
43 defaultExtension: 'js'
44 },
45
46 //externals
47 'external:js': {
48 format: 'cjs',
49 defaultExtension: 'js'
50 }
51 }
52 });
53
54 //amd require
55 window.require = System.amdRequire;
至此,一个基本的Taghelpr就完成了。
在ASP.NET Core MVC中应该使用 TagHelpers 来替换 HtmlHelpers,因为它们更加的简洁和容易使用。另一个巨大的好处就是依赖注入,在HtmlHelpers中是使用不了的,因为HtmlHelpers 扩展的都是静态内容。 但TagHelpers是一个公共类,我们可以很容易的在它的构造函数中注入服务。
进阶:资源性视图的应用
按照上节的惯例,我们依旧还一个进阶,说明下在TagHelper中如何使用cshtml,以及cshtml作为嵌入的资源该如何写。
我们从上面MultiSelectTagHelper类中将Process方法的页面代码拼接程序提取出来,写成cshtml如下
1 @{
2 string id = ViewData["Id"].ToString();
3 int showItemCount = (int)ViewData["ShowItemCount"];
4 bool isReadonly = (bool)ViewData["Readonly"];
5 }
6
7 <script>
8 require(['jquery', 'bootstrap', 'multiselect'], function ($) {
9 $(function(){
10 $("#@id").multiselect({
11 nonSelectedText: '请选择',
12 enableFiltering: true,//是否显示过滤
13 filterPlaceholder: '查找',
14 includeSelectAllOption: true,//是否显示全选
15 numberDisplayed: @(showItemCount),//显示条数
16 selectAllText: '全选'
17 });
18 @if (isReadonly)
19 {
20 @:$("#@id +div > button").attr("disabled", true);
21 }
22 });
23 });
24 </script>
这样MultiSelectTagHelper类中就简化成如下:
1 [HtmlTargetElement("multiSelect", Attributes = ForAttributeName)]
2 [HtmlTargetElement("multiSelect", Attributes = ValueAttributeName)]
3 [HtmlTargetElement("multiSelect", Attributes = ShowItemCountAttributeName)]
4 [HtmlTargetElement("multiSelect", Attributes = DataSourceAttributeName)]
5 [HtmlTargetElement("multiSelect", Attributes = ReadonlyAttributeName)]
6 public class MultiSelectTagHelper : TagHelper
7 {
8 private readonly IHtmlGenerator generator;
9 private readonly IUrlHelperFactory factory;
10 private readonly IHtmlHelper htmlHelper;
11
12 public MultiSelectTagHelper(IHtmlHelper htmlHelper, IHtmlGenerator generator)
13 {
14 this.generator = generator;
15 this.factory = factory;
16 this.htmlHelper = htmlHelper;
17 }
18
19 private const string ForAttributeName = "asp-for";
20 private const string ValueAttributeName = "asp-value";
21 private const string ShowItemCountAttributeName = "asp-showItemCount";
22 private const string DataSourceAttributeName = "asp-dataSource";
23 private const string ReadonlyAttributeName = "asp-readonly";
24
25 [HtmlAttributeNotBound]
26 [ViewContext]
27 public ViewContext ViewContext { get; set; }
28
29 [HtmlAttributeName(ForAttributeName)]
30 public ModelExpression For { get; set; }
31
32 [HtmlAttributeName(ValueAttributeName)]
33 public List<string> Value { get; set; }
34
35 [HtmlAttributeName(ShowItemCountAttributeName)]
36 public int ShowItemCount { get; set; } = 5;
37
38 [HtmlAttributeName(DataSourceAttributeName)]
39 public Dictionary<string, string> DataSource { get; set; }
40
41 [HtmlAttributeName(ReadonlyAttributeName)]
42 public bool Readonly { get; set; }
43
44 public override void Process(TagHelperContext context, TagHelperOutput output)
45 {
46 MicroStrutLibraryExceptionHelper.IsNull(context, this.GetType().FullName, LogLevel.Error, "context参数值为空");
47 MicroStrutLibraryExceptionHelper.IsNull(output, this.GetType().FullName, LogLevel.Error, "output");
48
49 output.TagName = "div";
50 //output.Attributes.Add("class", "multiselect-drop");
51
52 MultiSelectList selectList = new MultiSelectList(this.DataSource, "Key", "Value", this.Value);
53
54 HtmlContentBuilder builder = new HtmlContentBuilder();
55
56 string id;
57 if (For == null)
58 {
59 id = output.Attributes["id"].Value.ToString();
60 output.Attributes.Remove(output.Attributes["id"]);
61
62 string options = string.Empty;
63 foreach (SelectListItem item in selectList)
64 {
65 options += $"<option value=\"{item.Value}\" {(item.Selected ? "selected" : "")}>{item.Text}</option>";
66 }
67
68 builder.AppendHtml($"<select id=\"{id}\" name=\"{id}\" multiple=\"multiple\">{options}</select>");
69 }
70 else
71 {
72 id = For.Name;
73
74 TagBuilder dropDown = generator.GenerateSelect(ViewContext, For.ModelExplorer, null, For.Name, selectList, true, null);
75 builder.AppendHtml(dropDown);
76 }
77
78 output.Content.AppendHtml(builder);
79
80 //Contextualize the html helper
81 (htmlHelper as IViewContextAware).Contextualize(ViewContext);
82
83 ViewDataDictionary data = new ViewDataDictionary(this.ViewContext.ViewData);
84 data["Id"] = id;
85 data["ShowItemCount"] = this.ShowItemCount;
86 data["Readonly"] = this.Readonly;
87
88 var content = htmlHelper.Partial("TagHelpers/MultiSelect/MultiSelect", data);
89 output.Content.AppendHtml(content);
90
91 base.Process(context, output);
92 }
93 }
94 }
大家可能注意到构造函数中我们增加了个参数IHtmlHelper htmlHelper。这个参数是之前MVC的HtmlHelper,我们通过DI方式直接获取到htmlhelper。然而,此时DI获取的htmlhelper还无法使用,必须通过(htmlHelper as IViewContextAware).Contextualize(ViewContext);将上下文信息传入HtmlHelper。var content = htmlHelper.Partial("TagHelpers/MultiSelect/MultiSelect", data); output.Content.AppendHtml(content);这两句话执行cshtml页面,将最终页面的内容呈现在TagHelper中。
这里还有一个问题,就是我们将所有的控件都存放到一个应用程序集中,控件的cshtml页面也会以资源方式打包进应用程序集中。我们控件的项目结构如下:
MultiSelect的内容如下,有2个文件,一个cshtml,一个是taghelper程序。其他目录的结构也是类似的。
新的.net core的嵌入资源方式需要在project.json中按照如下方式编写:
"buildOptions": {
"embed": [ "Components/**/*.cshtml", "TagHelpers/**/*.cshtml" ]
}
这里的意思是我们将所有components和taghelpers目录下的第二级子目录下的所有cshtml文件以嵌入方式打包进应用程序集中。在.net core中使用应用程序集中嵌入的文件,还算是比较方便。因为.net core已经把许多可扩展的内容开放出来了。
我们这里写了一个扩展方法,在RazorViewEngineOptions(RazorViewEngine程序方式的配置)中增加一个Razor视图文件的定位器EmbeddedFileProvider。EmbeddedFileProvider就可以获取应用程序集中嵌入的cshtml文件,构造函数第一个参数是包含嵌入cshtml文件的应用程序集,第二个参数是命名空间。
1 public static class EmbeddedViewServiceCollectionExtensions
2 {
3 public static IServiceCollection AddEmbeddComponentView(this IServiceCollection services)
4 {
5 if (services == null)
6 {
7 throw new ArgumentNullException(nameof(services));
8 }
9
10 EmbeddedFileProvider fileProvider = new EmbeddedFileProvider(typeof(EmbeddedViewServiceCollectionExtensions).GetTypeInfo().Assembly, "MicroStrutLibrary.Presentation.Web.Controls");
11
12 services.Configure<RazorViewEngineOptions>(options => {
13 options.FileProviders.Add(fileProvider);
14 });
15
16 return services;
17 }
18 }
接下来就是在Startup.cs中使用这个扩展方法:
1 public void ConfigureServices(IServiceCollection services)
2 {
3 services.AddMvc(options =>
4 {
5 …
6 });
7
8 services.AddEmbeddComponentView();
9 }
现在才发现,其实生成select标签部分也是应该放到csthml中的,而不是在taghelper中生成,就不改了啊:)。
这里主要有几个小技巧再提示下:
1、cshtml页面中,Taghelper的Attribute可以传入各种复杂对象,而不是string\int\bool等简单类型
2、TagHelper如果使用cshtml,则应该使用IHtmlHelper
3、嵌入资源方式的cshtml,需要使用embeddedfileprovider。
[转]9.2.3 .net core 通过TagHelper封装控件的更多相关文章
- 9.2.3 .net core 通过TagHelper封装控件
.net core 除了继续保留.net framework的HtmlHelper的写法以外,还提供了TagHelper和ViewComponent方式生成控件. 我们本节说的是使用TagHelper ...
- 9.2.4 .net core 通过ViewComponent封装控件
我们在.net core中还使用了ViewComponent方式生成控件.ViewComponent也是asp.net core的新特性,是对页面部分的渲染,以前PartialView的功能,可以使用 ...
- [转].net core 通过ViewComponent封装控件 左侧菜单
本文转自:http://www.cnblogs.com/BenDan2002/p/6224816.html 我们在.net core中还使用了ViewComponent方式生成控件.ViewCompo ...
- ASP.NET Core MVC TagHelper实践HighchartsNET快速图表控件-开源
ASP.NET Core MVC TagHelper最佳实践HighchartsNET快速图表控件支持ASP.NET Core. 曾经在WebForms上写过 HighchartsNET快速图表控件- ...
- ASP.NET MVC Core的TagHelper (高级特性)
这篇博文ASP.NET MVC Core的TagHelper(基础篇)介绍了TagHelper的基本概念和创建自定义TagHelper的方式,接着继续介绍一些新的看起来比较高级的特性.(示例代码紧接着 ...
- .NET CORE的TagHelper智能提示
VisualStudio2017下ASP.NET CORE的TagHelper智能提示不能使用的解决办法 之前在VS2017RC中就发现该问题,安装了依赖,但是前段一直点不出来asp-for,后来 ...
- .net core 学习笔记(1)-分页控件的使用
最近有个小项目,用.net core开发练练手,碰到的第一个问题就是分页控件的问题,自己写太费时间,上网查了下,发现有人已经封装好了的,就拿过来用了,分页控件github:https://github ...
- FineUIPro/Mvc/Core/JS v4.2.0 发布了(老牌ASP.NET控件库,WebForms,ASP.NET MVC,Core,JavaScript)!
还记得 10 年前那个稍微青涩的 ExtAspNet 吗,如今她已脱胎换骨,变成了如下 4 款产品: FineUIPro:基于jQuery的经典款ASP.NET WebForms控件,之前的FineU ...
- .Net Core使用视图组件(ViewComponent)封装表单文本框控件
实例程序的界面效果如下图所示: 在表单中的搜索条件有姓名,学号,成绩.他们在一行中按照水平三等分排列. 在cshtml中用html实现上述表单效果的的代码如下: <form class=&quo ...
随机推荐
- kylin的clube合并后清理hbase中产生的相关历史表
kylin的clube合并后清理hbase中产生的相关历史表 kylin 的clube 历史的每次构建,都会产生一个hbase的表:虽然可以设置按照一定策略合并,但是合并后hbase 历史表不会被自动 ...
- NLayerAppV3-Infrastructure(基础结构层)的Data部分和Application(应用层)
回顾:NLayerAppV3是一个使用.net 2.1实现的经典DDD的分层架构的项目. NLayerAppV3是在NLayerAppV2的基础上,使用.net core2.1进行重新构建的:它包含了 ...
- Asp.NetCore初步探究
1, 新建一个空的AspNetCore项目,默认Program下的代码如下: public static void Main(string[] args) { BuildWebHost(args ...
- C# OleDbConnection对特定部分Excel的数据读取
最近在写winform程序,先来一个简单的. 读取特定部分Excel的数据读取,读取Excel第30行开始到H列的数据 using System;using System.Collections.Ge ...
- javascript实现快排
<script> var a = [7,4,5,3,2,1,4,5,6,6,2,21,4,53,12,0,-5,31,535,64,11,1,1,1,1]; function swap(a ...
- 三个分段的.tar.gz文件,合并并解压
1.合并使用spilt分割的文件 # cat sxrt5.0.dvd1.tar.gzaa sxrt5.0.dvd1.tar.gzab sxrt5.0.dvd1.tar.gzac >>sxr ...
- Socket编程概念
一.网路套接字 在通信过程中,套接字是成对存在的,该套接字内部借助两个缓冲区实现 二.网络字序 1.存储方式 大端法(网络):高位存低位,低位存高位 小端法(本地):高位存高位,低位存低位 2.网络字 ...
- 3.jquery在js文件中获取选择器对象
一.常用的选择器有一下几种: 1.标签选择器 2.类选择器 3.id选择器 4.并集选择器 5.层级选择器 二.如何获取选择器对象: <!DOCTYPE html> <html la ...
- Python面向对象(特殊成员)
day25 __init__ 类()自动执行 __del__ __call__ 对象() 类()() 自动执行 __int__ int(对象) ...
- tomcat安装配置常见问题详解
历经波折,终于把tomcat装好了.记录下过程供自己和后来的初学者参考吧! 本文先后介绍了tomcat的下载安装方法.安装和启动不成功的常见原因 以及启动tomcat后如何配置上下文. 一.下载安装 ...