在 ASP.NET MVC 中充分利用 WebGrid (microsoft 官方示例)

时间:2021-12-22 17:30:42

在 ASP.NET MVC 中充分利用 WebGrid

https://msdn.microsoft.com/zh-cn/magazine/hh288075.aspx

今年早些时候,Microsoft 发布了 ASP.NET MVC 版本 3 (asp.net/mvc) 以及一款名为 WebMatrix 的新产品 (asp.net/webmatrix)。 该 WebMatrix 版本中提供了几个工作效率帮助组件,可以简化诸如图表和表格数据呈现等任务。 其中一个帮助组件是 WebGrid,该组件支持通过 AJAX 自定义列的格式、分页、排序和异步更新,使表格呈现变得非常简单。

本文介绍 WebGrid 及其在 ASP.NET MVC 3 中的使用方式,然后讨论如何在 ASP.NET MVC 解决方案中充分利用 WebGrid 的功能。 有关 WebMatrix 的概述以及本文所用 Razor 语法的相关信息,请参见 Clark Sell 在 2011 年 4 月期刊中的文章“WebMatrix 简介”(msdn.microsoft.com/magazine/gg983489)。

本文介绍如何在 ASP.NET MVC 环境中安装 WebGrid 组件,以提高表格数据的呈现效率。 我将从 ASP.NET MVC 角度重点介绍以下与 WebGrid 有关的功能:创建具有完全 IntelliSense 支持的强类型版 WebGrid;利用 WebGrid 支持实现服务器端分页;以及添加可在禁用脚本编写时从容降级的 AJAX 功能。 本文所用示例以一个现成的服务为基础进行构建,该服务通过实体框架提供对 AdventureWorksLT 数据库的访问。 如果您对数据访问代码感兴趣,可在代码下载部分下载这些代码,也可查阅 Julie Lerman 在 2011 年 3 月期刊中的文章“使用实体框架和 ASP.NET MVC 3 实现服务器端分页”(msdn.microsoft.com/magazine/gg650669)。

WebGrid 入门

为了提供一个简单的 WebGrid 示例,我设置了一个 ASP.NET MVC 操作,它执行向视图传递 Ienumerable<Product> 的简单功能。 本文中我大多使用 Razor 视图引擎,但后面我也会讨论如何使用 WebForms 视图引擎。 我的 ProductController 类有如下操作:

public ActionResult List()
{
IEnumerable<Product> model =
_productService.GetProducts(); return View(model);
}

List 视图中包含如下 Razor 代码,用于呈现图 1 所示的网格:

@model IEnumerable<MsdnMvcWebGrid.Domain.Product>
@{
ViewBag.Title = "Basic Web Grid";
}
<h2>Basic Web Grid</h2>
<div>
@{
var grid = new WebGrid(Model, defaultSort:"Name");
}
@grid.GetHtml()
</div>

在 ASP.NET MVC 中充分利用 WebGrid (microsoft 官方示例)
(单击进行缩放)

图 1 呈现的基本 Web 网格

该视图中的第一行指定型号(例如我们在视图中访问的 Model 属性的类型)为 IEnumerable<Product>。然后,我在 div 元素内通过传入型号数据实例化一个 WebGrid,我将代码放入 @{...} 代码块中是要告诉 Razor 不要试图呈现结果。 我还在构造函数中将 defaultSort 参数设置为“Name”,告知 WebGrid 传给它的数据已按 Name 排序。 最后,我用 @grid.GetHtml() 生成网格的 HTML 并在响应中呈现网格。

这段代码虽然不多,却提供了丰富的网格功能。 该网格限制了显示的数据量,并包含翻阅数据所需的分页器链接,而且列标题呈现为链接以支持分页。 如果需要自定义该行为,可在 WebGrid 构造函数和 GetHtml 方法中指定一些选项。 通过这些选项可以禁用分页和排序、更改每页显示的行数、更改分页器链接中的文本等等。 图 2 显示了 WebGrid 构造函数参数,图 3 显示了 GetHtml 参数。

图 2 WebGrid 构造函数参数

名称 类型 备注
source IEnumerable<dynamic> 要呈现的数据。
columnNames IEnumerable<string> 筛选呈现的列。
defaultSort string 指定作为排序依据的默认列。
rowsPerPage int 控制每页显示的行数(默认值为 10)。
canPage bool 启用或禁用数据分页。
canSort bool 启用或禁用数据排序。
ajaxUpdateContainerId string 网格中包含元素的 ID,用来启用 AJAX 支持。
ajaxUpdateCallback string 完成 AJAX 更新后调用的客户端函数。
fieldNamePrefix string 支持多个网格时查询字符串字段使用的前缀。
pageFieldName string 页码的查询字符串字段名称。
selectionFieldName string 所选行号的查询字符串字段名称。
sortFieldName string 排序列的查询字符串字段名称。
sortDirectionFieldName string 排序方向的查询字符串字段名称。

图 3 WebGrid.GetHtml 参数

名称 类型 备注
tableStyle string 样式使用的表类。
headerStyle string 样式使用的标题行类。
footerStyle string 样式使用的页脚行类。
rowStyle string 样式使用的行类(仅限奇数行)。
alternatingRowStyle string 样式使用的行类(仅限偶数行)。
selectedRowStyle string 所选的样式行类。
caption string 显示为表标题的字符串。
displayHeader bool 指示是否应显示标题行。
fillEmptyRows bool 指示表中是否可以通过添加空行来保证 rowsPerPage 的行数。
emptyRowCellValue string 空行内填充的值,仅在设置了 fillEmptyRows 时使用。
columns IEnumerable<WebGridColumn> 用于自定义列呈现的列模型。
exclusions IEnumerable<string> 自动填充列时要排除的列。
mode WebGridPagerModes 分页器呈现模式(默认值为 NextPrevious 和 Numeric)。
firstText string 第一页链接的文本。
previousText string 上一页链接的文本。
nextText string 下一页链接的文本。
lastText string 最后一页链接的文本。
numericLinksCount int 要显示的数字链接的数量(默认值为 5)。
htmlAttributes object 包含为元素设置的 HTML 属性。

前一段 Razor 代码将呈现每一行的所有属性,但您也可能希望对显示哪些列作出限制。 有多种方法可以实现这一目的。 第一种方法(也是最简单的方法)是将这一组列传递到 WebGrid 构造函数。 例如,以下代码只呈现 Name 和 ListPrice 属性:

var grid = new WebGrid(Model, columnNames: new[] {"Name", "ListPrice"});

也可在 GetHtml 调用而不是在构造函数中指定这些列。 这种方法虽然要编写稍多的代码,但好处是可以指定更多关于如何呈现列的信息。 在下面的示例中,我指定了 header 属性,以使 ListPrice 列更便于阅读:

@grid.GetHtml(columns: grid.Columns(
grid.Column("Name"),
grid.Column("ListPrice", header:"List Price")
)
)

在呈现一组项目时,我们通常希望让用户通过点击一个项目来导航到详细信息视图。 通过 Column 方法的 format 参数可以自定义数据项的呈现。 以下代码演示如何更改名称的呈现方式,以输出指向某个项目详细信息视图的链接。这段代码输出带两位小数的“List Price”(货币值惯用的小数位数),得到的输出如图 4 所示。

@grid.GetHtml(columns: grid.Columns(
grid.Column("Name", format: @<text>@Html.ActionLink((string)item.Name,
"Details", "Product", new {id=item.ProductId}, null)</text>),
grid.Column("ListPrice", header:"List Price",
format: @<text>@item.ListPrice.ToString("0.00")</text>)
)
)

在 ASP.NET MVC 中充分利用 WebGrid (microsoft 官方示例)

图 4 采用自定义列的基本网格

虽然我指定格式时发生的情况看似有些神秘,但 format 参数实际就是一个 Func<dynamic,object>,即一个利用动态参数返回对象的委托函数。 Razor 引擎采用为 format 参数指定的代码段,并将其转变为一个委托。该委托采用一个名为 item 的动态参数,format 代码段中正是使用了这个 item 变量。 有关这些委托的工作方式的更多信息,请参见 Phil Haack 在以下地址发表的博客文章:bit.ly/h0Q0Oz

由于 item 参数属于动态类型,所以在编写代码时无法获得 IntelliSense 支持和编译器检查(请参见 Alexandra Rusina 在 2011 年 2 月期刊中发表的关于动态类型的文章msdn.microsoft.com/magazine/gg598922)。 而且,也不支持用动态参数调用扩展方法。 也就是说,当调用扩展方法时,一定要使用静态类型。正因为如此,我在前面的代码中调用 Html.ActionLink 扩展方法时,item.Name 转换成了 string。 由于 ASP.NET MVC 中对扩展方法的使用较为普遍,动态和扩展方法之间的这种冲突可能会让人疲于应付(在使用 T4MVC 等其他组件时情况甚至更糟:bit.ly/9GMoup)。

添加强类型化

虽然动态类型化可能很适合 WebMatrix,但强类型化视图也有其优点。 实现强类型化的一种办法是创建一个派生类型 WebGrid<T>,如图 5 所示。 如您所见,这是个非常轻型的包装!

图 5 创建派生 WebGrid

public class WebGrid<T> : WebGrid
{
public WebGrid(
IEnumerable<T> source = null,
...
parameter list omitted for brevity)
: base(
source.SafeCast<object>(),
...
parameter list omitted for brevity)
{ }
public WebGridColumn Column(
string columnName = null,
string header = null,
Func<T, object> format = null,
string style = null,
bool canSort = true)
{
Func<dynamic, object> wrappedFormat = null;
if (format != null)
{
wrappedFormat = o => format((T)o.Value);
}
WebGridColumn column = base.Column(
columnName, header,
wrappedFormat, style, canSort);
return column;
}
public WebGrid<T> Bind(
IEnumerable<T> source,
IEnumerable<string> columnNames = null,
bool autoSortAndPage = true,
int rowCount = -1)
{
base.Bind(
source.SafeCast<object>(),
columnNames,
autoSortAndPage,
rowCount);
return this;
}
} public static class WebGridExtensions
{
public static WebGrid<T> Grid<T>(
this HtmlHelper htmlHelper,
...
parameter list omitted for brevity)
{
return new WebGrid<T>(
source,
...
parameter list omitted for brevity);
}
}

这样做有什么好处呢? 通过实现这个新的 WebGrid<T>,我添加了一个新的 Column 方法,该方法以 Func<T, object> 作为 format 参数,这意味着在调用扩展方法时不必再进行转换。 不仅如此,现在还能够获得 IntelliSense 支持和编译器检查(假定项目文件中已经打开 MvcBuildViews,它默认处于关闭状态)。

通过这种 Grid 扩展方法,您能够利用编译器针对范型参数的类型推断功能。 因此,本例中我们只需要编写 Html.Grid(Model),而不必编写新的 WebGrid<Product>(Model)。 无论采用哪种方式,返回的类型都是 WebGrid<Product>。

添加分页和排序

如您所见,WebGrid 能让我们毫不费力的获得分页和排序功能。 您还了解到如何通过 rowsPerPage 参数(位于构造函数中,或通过 Html.Grid 帮助程序实现)配置页面大小,使网格自动显示单页数据并呈现页面导航所使用的分页控件。 但是,这种默认行为可能满足不了您的需求。 为了说明这一点,我添加了一行代码,用于在呈现网格后显示数据源中包含的项数,如图 6 所示。

在 ASP.NET MVC 中充分利用 WebGrid (microsoft 官方示例)

图 6 数据源中的项数

可以看到,我们传递的数据中包含完整的产品列表(本例中为 295 个产品,但检索更多数据的情形想来并不少见)。 随着返回数据量的增加,虽然依旧是呈现单页数据,但服务和数据库所承受的负荷会越来越大。 但是有一种更好的办法:服务器端分页。 采用这种方式,只需要取回需要在当前页面中显示的数据(例如只显示五行数据)。

实现 WebGrid 服务器端分页的第一步是限制从数据源检索的数据量。 为此,需要知道请求的是哪一页数据,以便检索正确的数据页。 WebGrid 在呈现分页链接时,会重复使用页面的 URL,并在页码中附加一个查询字符串参数,例如 http://localhost:27617/Product/DefaultPagingAndSorting?page=3(该查询字符串参数的名称可通过帮助程序参数进行配置,这在支持同一页面中多个网格的分页时非常有用)。 也就是说,您可以在自己的操作方法中采用一个名为 page 的参数,然后使用查询字符串值填充该参数。

如果只是通过修改现有代码向 WebGrid 传递单页数据,则 WebGrid 只会看到单页数据。 由于它不知道还有别的页面,因而不再呈现分页器控件。 幸运的是,WebGrid 还有一种名为 Bind 的方法,可用来指定数据。Bind 不仅能够接受数据,而且有一个表示总行数的参数,从而据此计算页数。 为了使用此方法,需要更新 List 操作以检索更多信息并将其传入视图,如图 7 所示。

图 7 更新 List 操作

public ActionResult List(int page = 1)
{
const int pageSize = 5; int totalRecords;
IEnumerable<Product> products = productService.GetProducts(
out totalRecords, pageSize:pageSize, pageIndex:page-1); PagedProductsModel model = new PagedProductsModel
{
PageSize= pageSize,
PageNumber = page,
Products = products,
TotalRows = totalRecords
};
return View(model);
}

利用这些附加信息,即可更新视图以使用 WebGrid 的 Bind 方法。 通过调用 Bind 可提供要呈现的数据和总行数,并将 autoSortAndPage 参数设置为 false。 autoSortAndPage 参数告知 WebGrid 不需要应用分页,因为这由 List 方法负责。 对此可用下面代码说明:

<div>
@{
var grid = new WebGrid<Product>(null, rowsPerPage: Model.PageSize,
defaultSort:"Name");
grid.Bind(Model.Products, rowCount: Model.TotalRows, autoSortAndPage: false);
}
@grid.GetHtml(columns: grid.Columns(
grid.Column("Name", format: @<text>@Html.ActionLink(item.Name,
"Details", "Product", new { id = item.ProductId }, null)</text>),
grid.Column("ListPrice", header: "List Price",
format: @<text>@item.ListPrice.ToString("0.00")</text>)
)
) </div>

经过如此改造,WebGrid 又恢复了生机,重新呈现分页控件,但分页发生在服务中而不是视图中! 但是,由于关闭了 autoSortAndPage,排序功能遭到破坏。 WebGrid 利用查询字符串参数来传递排序列和方向,但我们已命令它不执行排序。 解决办法是在操作方法中添加 sort 和 sortDir 参数,然后将它们传入服务,让服务执行必要的排序,如图 8 所示。

图 8 在操作方法中添加排序参数

public ActionResult List(
int page = 1,
string sort = "Name",
string sortDir = "Ascending" )
{
const int pageSize = 5; int totalRecords;
IEnumerable<Product> products =
_productService.GetProducts(out totalRecords,
pageSize: pageSize,
pageIndex: page - 1,
sort:sort,
sortOrder:GetSortDirection(sortDir)
); PagedProductsModel model = new PagedProductsModel
{
PageSize = pageSize,
PageNumber = page,
Products = products,
TotalRows = totalRecords
};
return View(model);
}

AJAX:客户端改动

WebGrid 支持通过 AJAX 异步更新网格内容。 为了利用此功能,应确保包含网格的 div 有一个 id,然后通过 ajaxUpdateContainerId 参数将该 id 传入网格的构造函数。 还需要对 jQuery 的引用,但这已经包括在布局视图中。 指定 ajaxUpdateContainerId 以后,WebGrid 会修改自己的行为,使分页和排序链接能够利用 AJAX 进行更新:

<div id="grid">

@{
var grid = new WebGrid<Product>(null, rowsPerPage: Model.PageSize,
defaultSort: "Name", ajaxUpdateContainerId: "grid");
grid.Bind(Model.Products, autoSortAndPage: false, rowCount: Model.TotalRows);
}
@grid.GetHtml(columns: grid.Columns(
grid.Column("Name", format: @<text>@Html.ActionLink(item.Name,
"Details", "Product", new { id = item.ProductId }, null)</text>),
grid.Column("ListPrice", header: "List Price",
format: @<text>@item.ListPrice.ToString("0.00")</text>)
)
) </div>

尽管内置的使用 AJAX 的功能很不错,但如果脚本编写被禁用,生成的输出将不起作用。 其原因在于,在 AJAX 模式下,WebGrid 在呈现定位标记时将 href 设置为“#”,并通过 onclick 处理程序注入 AJAX 行为。

我一直热衷于创建能在禁用脚本编写时从容降级的页面,最后往往发现做到这一点最好的办法是渐进式增强(基本原理是提供一个无需脚本即可正常工作的页面,然后通过脚本对该页面加以丰富)。 为达到此目的,可恢复为非 AJAX 的 WebGrid,然后创建图 9 所示的脚本以重新应用 AJAX 行为:

图 9 重新应用 AJAX 行为

$(document).ready(function () {

  function updateGrid(e) {
e.preventDefault();
var url = $(this).attr('href');
var grid = $(this).parents('.ajaxGrid');
var id = grid.attr('id');
grid.load(url + ' #' + id);
};
$('.ajaxGrid table thead tr a').live('click', updateGrid);
$('.ajaxGrid table tfoot tr a').live('click', updateGrid);
});

为使脚本只应用到一个 WebGrid 中,它利用 jQuery 选择器标识出设置了 ajaxGrid 类的元素。 脚本通过 jQuery live 方法 (api.jquery.com/live) 建立排序和分页链接的 click 处理程序(通过网格容器内的表标题和页脚进行标识)。 这将为符合选择器要求的现有和未来元素设置事件处理程序,由于脚本将取代内容,因此这样做非常方便。

updateGrid 方法被设置为事件处理程序,它首先要做的是调用 preventDefault 以抑制默认行为。 在此之后,该方法获取要使用的 URL(通过定位标记的 href 属性获取),然后通过调用 AJAX 将更新的内容加载到容器元素之中。 为了采用这种做法,一定要禁用默认的 WebGrid AJAX 行为,将 ajaxGrid 类添加到容器 div,然后加入图 9 所示的脚本。

AJAX:服务器端改动

还有一点需要指出,就是脚本使用 jQuery load 方法中的功能从返回的文档中分离出一个片段。 只需调用 load(‘http://example.com/someurl’) 就能加载 URL 的内容。 但是,load(‘http://example.com/someurl #someId’) 将从指定 URL 加载内容,然后返回 id 为“someId”的片段。这反映了 WebGrid 的默认 AJAX 行为,意味着不必通过更新服务器代码添加部分呈现行为。WebGrid 首先加载整个页面,然后从中剥离出新的网格。

尽管这样在快速获得 AJAX 功能方面非常有效,但也意味着需要通过网络发送不必要的数据,而且可能在服务器中也要查询不必要的数据。 幸运的是,ASP.NET MVC 能够轻松解决这个问题。 基本做法是将要在 AJAX 及非 AJAX 请求*享的呈现内容提取到一个部分视图中。 随后,控制器中的 List 操作既可以为 AJAX 调用仅呈现部分视图,也可以为非 AJAX 调用呈现完整视图(该完整视图又使用该部分视图)。

这种做法非常简单,只需在操作方法内部测试 Request.IsAjaxRequest 扩展方法的结果即可。 当 AJAX 与非 AJAX 代码途径之间的差别非常小时,这种方法十分适用。 然而,两者之间的差别往往比较大(例如,完全呈现需要的数据比部分呈现多)。 在这种情况下,可能需要编写一个 AjaxAttribute,以便单独编写相应的方法,然后让 MVC 框架根据请求是否为 AJAX 请求来选择合适的方法(与 HttpGet 和 HttpPost 属性的工作方式相同)。 关于这方面的例子,请参阅我在bit.ly/eMlIxU 的博客文章。

WebGrid 和 WebForms 视图引擎

到目前为止,所有举例都使用了 Razor 视图引擎。 在最简单的情况下,我们不必执行任何修改即可将 WebGrid 用于 WebForms 视图(暂不论视图引擎的语法差别)。 在前面的示例中,我演示了如何使用 format 参数自定义行数据的呈现:

grid.Column("Name",
format: @<text>@Html.ActionLink((string)item.Name,
"Details", "Product", new { id = item.ProductId }, null)</text>),

format 参数实际上是一个 Func,但 Razor 视图引擎对我们隐藏了这一点。 不过,您还是可以传递 Func,例如用 lambda 表达式:

grid.Column("Name",
format: item => Html.ActionLink((string)item.Name,
"Details", "Product", new { id = item.ProductId }, null)),

借助于这种简单的转换,现在我们可以轻松地在 WebForms 视图引擎中使用 WebGrid!

总结

本文介绍了如何通过几项简单的调整,在不牺牲强类型化、IntelliSense 和高效服务器端分页的情况下利用 WebGrid 为我们提供的功能。 WebGrid 有一些非常棒的功能,可帮助我们提高表格数据的呈现效率。 希望本文能为您在 ASP.NET MVC 应用程序中充分利用 WebGrid 提供有益的提示。

Stuart Leeks 是英国高级开发支持团队的应用程序开发经理,他对于键盘快捷方式有着超乎寻常的热爱。他的博客站点在 blogs.msdn.com/b/stuartleeks,他在那里讨论自己感兴趣的技术主题(包括但不限于 ASP.NET MVC、实体框架和 LINQ)。

衷心感谢以下技术专家对本文的审阅:Simon Ince 和 Carl Nolan

在 ASP.NET MVC 中充分利用 WebGrid (microsoft 官方示例)的更多相关文章

  1. ASP&period;NET MVC中使用Ninject

    ASP.NET MVC中使用Ninject 在[ASP.NET MVC 小牛之路]系列上一篇文章(依赖注入(DI)和Ninject)的末尾提到了在ASP.NET MVC中使用Ninject要做的两件事 ...

  2. 在 ASP&period;NET MVC 中使用异步控制器

    线程池 一直想把项目改写成异步,但是ASP.NETMVC3下写的过于繁琐,.NET 4.5与ASP.NET MVC下代码写起来就比较简单了, MS好像也一直喜欢这样搞,每一个成熟的东西,都要演变好几个 ...

  3. 在Asp&period;Net MVC 中配置 Serilog

    Serilog 是一种非常简便记录log 的处理方式,使用Serilog可以生成本地的text文件, 也可以通过 Seq 来在Web界面中查看具体的log内容. 接下来就简单的介绍一下在Asp.Net ...

  4. 如何在 ASP&period;NET MVC 中集成 AngularJS(3)

    今天来为大家介绍如何在 ASP.NET MVC 中集成 AngularJS 的最后一部分内容. 调试路由表 - HTML 缓存清除 就在我以为示例应用程序完成之后,我意识到,我必须提供两个版本的路由表 ...

  5. 如何在 ASP&period;NET MVC 中集成 AngularJS(1)

    介绍 当涉及到计算机软件的开发时,我想运用所有的最新技术.例如,前端使用最新的 JavaScript 技术,服务器端使用最新的基于 REST 的 Web API 服务.另外,还有最新的数据库技术.最新 ...

  6. ASP&period;NET MVC 中应用Windows服务以及Webservice服务开发分布式定时器

    ASP.NET MVC 中应用Windows服务以及Webservice服务开发分布式定时器一:闲谈一下:1.现在任务跟踪管理系统已经开发快要结束了,抽一点时间来写一下,想一想自己就有成就感啊!!  ...

  7. ASP&period;NET MVC中使用ASP&period;NET AJAX异步访问WebService

    使用过ASP.NET AJAX的朋友都知道,怎么通过ASP.NET AJAX在客户端访问WebService,其实在ASP.NET MVC中使用ASP.NET AJAX异步访问WebService 也 ...

  8. NPOI以及在ASP&period;NET MVC中的使用

    NPOI以及在ASP.NET MVC中的使用 1.前言 相信大家在工作中经常要遇到一些导入导出Execl操作.学习贵在分享,分享使人快乐,园子里的前辈已经有很多好的文章,鄙人也是能力有限,在这里把这些 ...

  9. Ninject 在 Winform、 Asp&period;net MVC中连络EntityFramework的应用

    Ninject 在 Winform. Asp.net MVC中连络EntityFramework的应用( 注入同一个DbContext的应用名人名言:科学是老老实实的东西,它要靠许许多多人民的劳动和智 ...

随机推荐

  1. ELF Format 笔记(十三)—— 段权限

    ilocker:关注 Android 安全(新手) QQ: 2597294287 一个可被系统加载的程序至少拥有一个可加载段.当系统创建可加载段的内存映像时,会根据 p_flags 赋予一定的访问权限 ...

  2. CentOS 7 配置静态IP

    1.查看MAC地址 2.修改/etc/sysconfig/network-scripts/ifcfg-[第一步中红框内的文字] 3.添加和修改内容如下: 4.修改/etc/resolv.conf 5. ...

  3. 32位计时器极端情况下产生的bug

    用每毫秒更新的32位变量用来计时, 使用这个变量计算离上次操作是否间隔10秒.两种写法: f - lastF <10, 和 f

  4. Android成长日记-ProgressBar的设计

    ProgressBar的关键属性 Android:max=”100” - ---最大显示进度 Android:progress=”50”----第一显示进度 Android:secondaryProg ...

  5. c&num; tcp备忘及networkstream&period;length此流不支持查找解决

    服务端 bool isRunning = true;  MouseKeyBoard mk = new MouseKeyBoard(); void InitTcpServer(int port) { T ...

  6. 非常有用!eclipse与myeclipse恢复已删除的文件和代码

     eclipse与myeclipse恢复已删除的文件和代码 今天写了1300多行代码,被不小心删除了顿时感觉手足无措,后来用myeclipse的历史文件恢复功能,找回来了,虚惊一场!!!MyEclip ...

  7. 【转】shell脚本处理字符串的常用方法

    转自:http://blog.csdn.net/linfeng999/article/details/6661233 1. 构造字符串 直接构造 STR_ZERO=hello #shell中等号左右的 ...

  8. 大数据测试之hadoop系统生态

    poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标,也是国内最早探索大数据测试培训的机构,开发了独有的课程体系.如果对课程感兴趣,请大 ...

  9. ES6字符串扩展

    前面的话 字符串是编程中重要的数据类型,只有熟练掌握字符串操作才能更高效地开发程序.JS字符串的特性总是落后于其它语言,例如,直到 ES5 中字符串才获得了 trim() 方法.而 ES6 则继续添加 ...

  10. 洛谷P4363 一双木棋chess &lbrack;九省联考2018&rsqb; 搜索&plus;hash

    正解:记搜+hash 解题报告: 传送门! 因为看到nm范围特别小,,,所以直接考虑爆搜(bushi 先考虑爆搜之后再想优化什么的嘛QwQ 首先对这种都要最优的,就可以直接把答案设为针对某一方,然后题 ...