分页是Web应用程序中最常用到的功能之一,在ASP.NET中,虽然自带了一些可以分页的数据控件,但其分页功能并不尽如人意。本文对于这些数据控件的假分页暂且不表,如有不明白的同学请百Google度之。

本文中实现的分页控件是在手动分页基础上做的改善,将分页实现的逻辑部分和数据控件的绑定尽可能分开,以克服手工编写分页代码任务繁琐、代码重用率低等问题。

本文依旧是一粒粟子。

一、分页控件素颜

二、分页控件的实现

本文中将介绍两种将分页实现逻辑与数据控件绑定分离的实现方式:

  • 使用反射机制
  • 使用事件机制

1、基于反射机制的分页控件

源码

PagingHelper.ascx:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="PagingHelper.ascx.cs" Inherits="PagingHelper.Controls.PagingHelper" %>
<div style="width:100%">
    <asp:LinkButton ID="lbtnFirstPage" runat="server" CausesValidation="false" onclick="lbtnPage_Click"  >首页</asp:LinkButton>
    <asp:LinkButton ID="lbtnPrevPage" runat="server" CausesValidation="false"  onclick="lbtnPage_Click" >上一页</asp:LinkButton>
    &nbsp;第<asp:Label ID="lbPageIndex" runat="server" Text=""></asp:Label>
    页/共<asp:Label ID="lbTotalPages" runat="server" Text=""></asp:Label>
    页&nbsp;
    <asp:LinkButton ID="lbtnNextPage" runat="server" CausesValidation="false"  onclick="lbtnPage_Click" >下一页</asp:LinkButton>
    <asp:LinkButton ID="lbtnLastPage" runat="server" CausesValidation="false"  onclick="lbtnPage_Click" >尾页</asp:LinkButton>
</div>

PagingHelper.ascx.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Reflection;
 
namespace PagingHelper.Controls
{
    public partial class PagingHelper : System.Web.UI.UserControl
    {
        #region 属性
        private int m_PageSize;
        public int PageSize         //每页显示记录数
        {
            set
            {
                m_PageSize = value;
            }
            get
            {
                if (m_PageSize.Equals(0))
                {
                    m_PageSize = 10;
                }
                return m_PageSize;
            }
        }
 
        private int m_PageIndex;
        public int PageIndex        //当前页页码
        {
            set
            {
                m_PageIndex = value;
            }
            get
            {
                if (m_PageIndex.Equals(0))
                {
                    m_PageIndex = 1;
                }
                return m_PageIndex;
            }
        }
 
        public int TotalItemCount   //记录总数
        {
            set;
            private get;
        }
 
        public string BindDataMethodName    //绑定数据的方法名
        {
            set;
            private get;
        }
        #endregion
 
        #region 受保护的方法
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                BindPagingHelperControl();
            }
        }
        protected void lbtnPage_Click(object sender, EventArgs e)
        {
            LinkButton lbtn = sender as LinkButton;
            ReBindData(lbtn.CommandArgument);
        }
        #endregion
 
        #region 公共方法
 
        #endregion
 
        #region 私有方法
        private void BindPagingHelperControl()
        {
            int totalPages = (TotalItemCount % PageSize) == 0 ? TotalItemCount / PageSize : TotalItemCount / PageSize + 1;
            //显示
            lbPageIndex.Text = PageIndex.ToString();
            lbTotalPages.Text = totalPages.ToString();
            //使能
            lbtnFirstPage.Enabled = PageIndex > 1;
            lbtnPrevPage.Enabled =  PageIndex > 1;
            lbtnLastPage.Enabled = PageIndex < totalPages;
            lbtnNextPage.Enabled = PageIndex < totalPages;
            //命令
            lbtnFirstPage.CommandArgument = "1";
            lbtnPrevPage.CommandArgument = (PageIndex - 1).ToString();
            lbtnNextPage.CommandArgument = (PageIndex + 1).ToString();
            lbtnLastPage.CommandArgument = totalPages.ToString();
        }
        private void ReBindData(string pageIndex)
        {
            PageIndex = int.Parse(pageIndex);
            Object obj = null;  //空间所在的容器
            if (base.Parent is HtmlForm)
            {
                obj = this.Page;
            }
            else if (base.Parent is ContentPlaceHolder)
            {
                obj = this.Page.Master.Page;
            }
            else
            {
                obj = base.Parent;
            }
            MethodInfo methodInfo = obj.GetType().GetMethod(BindDataMethodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
            methodInfo.Invoke(obj, null);
            BindPagingHelperControl();
        }
        #endregion
 
    }
}

Demo:

Default.aspx:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="PagingHelper.Default" %>
 
<%@ Register src="Controls/PagingHelper.ascx" tagname="PagingHelper" tagprefix="uc1" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:GridView ID="gvDemo" runat="server">
        </asp:GridView>
        <br />
        <uc1:PagingHelper ID="PagingHelper1" runat="server" PageSize="2" />
    </div>
    </form>
</body>
</html>

Default.aspx.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
 
namespace PagingHelper
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            GvDemoBind();
        }
 
        protected void GvDemoBind()
        {
            string sql = @"SELECT * FROM tb_user";
            string sqlCount = @"SELECT COUNT(*) FROM tb_user ";
            int itemStart = (PagingHelper1.PageIndex - 1) * PagingHelper1.PageSize;
            sql += string.Format(" LIMIT {0},{1}",itemStart,PagingHelper1.PageSize);
            gvDemo.DataSource = SQLHelper.ExecuteDataTable(sql).DefaultView;
            gvDemo.DataBind();
            PagingHelper1.TotalItemCount = Convert.ToInt32(SQLHelper.ExecuteScalar(sqlCount));
            PagingHelper1.BindDataMethodName = "GvDemoBind";
        }
    }
}

2、基于事件机制的分页控件

源码:

PagingHelper.ascx:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="PagingHelper.ascx.cs" Inherits="PagingHelper_V2.Controls.PagingHelper" %>
<div style="width:100%">
    <asp:LinkButton ID="lbtnFirstPage" runat="server" CausesValidation="false" onclick="lbtnPage_Click"  >首页</asp:LinkButton>
    <asp:LinkButton ID="lbtnPrevPage" runat="server" CausesValidation="false"  onclick="lbtnPage_Click" >上一页</asp:LinkButton>
    &nbsp;第<asp:Label ID="lbPageIndex" runat="server" Text=""></asp:Label>
    页/共<asp:Label ID="lbTotalPages" runat="server" Text=""></asp:Label>
    页&nbsp;
    <asp:LinkButton ID="lbtnNextPage" runat="server" CausesValidation="false"  onclick="lbtnPage_Click" >下一页</asp:LinkButton>
    <asp:LinkButton ID="lbtnLastPage" runat="server" CausesValidation="false"  onclick="lbtnPage_Click" >尾页</asp:LinkButton>
    &nbsp;转到
    <asp:TextBox ID="txtGoto" runat="server" Width="32px"></asp:TextBox>
    页<asp:Button ID="btnGoto" runat="server" Text="确定" onclick="btnGoto_Click" />
</div>

PagingHelper.ascx.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
 
namespace PagingHelper_V2.Controls
{
    public partial class PagingHelper : System.Web.UI.UserControl
    {
        #region 属性
        private int m_PageSize;
        public int PageSize         //每页显示记录数
        {
            set
            {
                m_PageSize = value;
            }
            get
            {
                if (m_PageSize.Equals(0))
                {
                    m_PageSize = 10;
                }
                return m_PageSize;
            }
        }
 
        private int m_PageIndex;
        public int PageIndex        //当前页页码
        {
            set
            {
                m_PageIndex = value;
            }
            get
            {
                if (m_PageIndex.Equals(0))
                {
                    m_PageIndex = 1;
                }
                return m_PageIndex;
            }
        }
 
        public int TotalItemCount   //记录总数
        {
            set;
            private get;
        }
 
        #endregion
 
        #region 受保护的方法
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                BindPagingHelperControl();
            }
        }
        protected void lbtnPage_Click(object sender, EventArgs e)
        {
            LinkButton lbtn = sender as LinkButton;
            ReBindData(int.Parse(lbtn.CommandArgument));
        }
        protected void btnGoto_Click(object sender, EventArgs e)
        {
            int gotoPageIndex = PageIndex;
            if (int.TryParse(txtGoto.Text, out gotoPageIndex))
            {
                if (gotoPageIndex < 1 || gotoPageIndex > int.Parse(lbTotalPages.Text))
                {
                    Response.Write("<script>alert('此页面不存在!')</script>");
                }
                else
                {
                    if (!gotoPageIndex.Equals(int.Parse(lbPageIndex.Text)))
                    {
                        ReBindData(gotoPageIndex);
                    }
                }
            }
            else
            {
                Response.Write("<script>alert('请输入正确的页码!')</script>");
            }
 
        }
        #endregion
 
        #region 公共方法
 
        #endregion
 
        #region 私有方法
        private void BindPagingHelperControl()
        {
            int totalPages = (TotalItemCount % PageSize) == 0 ? TotalItemCount / PageSize : TotalItemCount / PageSize + 1;
            //显示
            lbPageIndex.Text = PageIndex.ToString();
            lbTotalPages.Text = totalPages.ToString();
            txtGoto.Text = PageIndex.ToString();
            //使能
            lbtnFirstPage.Enabled = PageIndex > 1;
            lbtnPrevPage.Enabled = PageIndex > 1;
            lbtnLastPage.Enabled = PageIndex < totalPages;
            lbtnNextPage.Enabled = PageIndex < totalPages;
            //命令
            lbtnFirstPage.CommandArgument = "1";
            lbtnPrevPage.CommandArgument = (PageIndex - 1).ToString();
            lbtnNextPage.CommandArgument = (PageIndex + 1).ToString();
            lbtnLastPage.CommandArgument = totalPages.ToString();
        }
        private void ReBindData(int pageIndex)
        {
            PageIndex = pageIndex;
            OnPageIndexChanged(new EventArgs());
            BindPagingHelperControl();
        }
        #endregion
 
        #region 事件
        public delegate void PageIndexChangedEventHandler(object sender, EventArgs e);
        public event PageIndexChangedEventHandler PageIndexChanged;
        protected virtual void OnPageIndexChanged(EventArgs e)
        {
            PageIndexChangedEventHandler handler = PageIndexChanged;
            if (handler != null)
            {
                handler(this, e);
            }
        }
        #endregion
 
        
    }
}

Demo:

Default.aspx:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="PagingHelper_V2.Default" %>
 
<%@ Register src="Controls/PagingHelper.ascx" tagname="PagingHelper" tagprefix="uc1" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:GridView ID="gvDemo" runat="server">
        </asp:GridView>
        &nbsp;
        <uc1:PagingHelper ID="PagingHelper1" runat="server" PageSize="2" OnPageIndexChanged="PagingHelper1_OnPageIndexChanged" />
    </div>
    </form>
</body>
</html>

Default.aspx.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
 
namespace PagingHelper_V2
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            GvDemoBind();
        }
 
        protected void GvDemoBind()
        {
            string sql = @"SELECT * FROM tb_user";
            string sqlCount = @"SELECT COUNT(*) FROM tb_user ";
            int itemStart = (PagingHelper1.PageIndex - 1) * PagingHelper1.PageSize;
            sql += string.Format(" LIMIT {0},{1}", itemStart, PagingHelper1.PageSize);
            gvDemo.DataSource = SQLHelper.ExecuteDataTable(sql).DefaultView;
            gvDemo.DataBind();
            PagingHelper1.TotalItemCount = Convert.ToInt32(SQLHelper.ExecuteScalar(sqlCount));
            
        }
 
        protected void PagingHelper1_OnPageIndexChanged(object sender, EventArgs e)
        {
            GvDemoBind();
        }
    }
}

三、总结

比较两种实现方式,基于事件机制的实现更符合ASP.NET服务器控件的style。

好!那就参照园子里的分页使用基于事件机制的方式再做一个控件作为总结。

源码:

PagingHelper.ascx:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="PagingHelper.ascx.cs" Inherits="PagingHelper_V3.Controls.PagingHelper" %>
<style type="text/css">
    a.LinkButtonDefault{text-align:center;text-decoration:none;margin-right:1px;padding:2px 4px;}
    a.LinkButtonBlue{background: #ebebeb;text-align:center;text-decoration:none;margin-right:1px;padding:2px 4px;}
    a.LinkButtonYellow { background-color:#ccc; color:#000fff; font-weight:bold;text-align:center;text-decoration:none;margin-right:1px;padding:2px 4px;}
</style>
<div style="width:100%">
    共<asp:Label ID="lbTotalPages" runat="server" ForeColor="#fff"></asp:Label>页:
    <asp:LinkButton ID="lbtnFirstPage" runat="server" CausesValidation="false" CssClass="LinkButtonDefault" onclick="lbtnPage_Click" >首页</asp:LinkButton>
    <asp:LinkButton ID="lbtnPrevPage" runat="server" CausesValidation="false" CssClass="LinkButtonDefault" onclick="lbtnPage_Click" >上一页</asp:LinkButton>
    <asp:Repeater ID="rptPageNumber" runat="server">
        <ItemTemplate>
            <asp:LinkButton ID="lbtnPageNumber" runat="server" CausesValidation="false" Width="16px" onclick="lbtnPage_Click"
                 CssClass='<%# Convert.ToInt32(Container.DataItem)==PageIndex?"LinkButtonYellow":"LinkButtonBlue"%>' CommandArgument='<%# Container.DataItem %>'>
<%
   1: #Container.DataItem 
%>
            </asp:LinkButton>
        </ItemTemplate>
    </asp:Repeater>
    <asp:LinkButton ID="lbtnNextPage" runat="server" CausesValidation="false" CssClass="LinkButtonDefault"  onclick="lbtnPage_Click" >下一页</asp:LinkButton>
    <asp:LinkButton ID="lbtnLastPage" runat="server" CausesValidation="false" CssClass="LinkButtonDefault"  onclick="lbtnPage_Click" >尾页</asp:LinkButton>
</div>

PagingHelper.ascx.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
 
namespace PagingHelper_V3.Controls
{
    public partial class PagingHelper : System.Web.UI.UserControl
    {
        #region 属性
        private int m_PageSize;
        public int PageSize         //每页显示记录数
        {
            set
            {
                m_PageSize = value;
            }
            get
            {
                if (m_PageSize.Equals(0))
                {
                    m_PageSize = 10;
                }
                return m_PageSize;
            }
        }
 
        private int m_PageIndex;
        public int PageIndex        //当前页页码
        {
            set
            {
                m_PageIndex = value;
            }
            get
            {
                if (m_PageIndex.Equals(0))
                {
                    m_PageIndex = 1;
                }
                return m_PageIndex;
            }
        }
 
        public int TotalItemCount   //记录总数
        {
            set;
            private get;
        }
 
        #endregion
 
        #region 受保护的方法
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                BindPagingHelperControl();
            }
        }
        protected void lbtnPage_Click(object sender, EventArgs e)
        {
            LinkButton lbtn = sender as LinkButton;
            ReBindData(int.Parse(lbtn.CommandArgument));
        }
        #endregion
 
        #region 公共方法
 
        #endregion
 
        #region 私有方法
        private void BindPageNum(int totalPages)
        {
            int startPageIndex = 1, endPageIndex = 10;
            if (totalPages < endPageIndex)
            {
                endPageIndex = totalPages;
            }
            else
            {
                startPageIndex = (PageIndex > 5) ? PageIndex - 5 : startPageIndex;
                int result = (startPageIndex + 9) - totalPages;
                if (result > 0)
                {
                    endPageIndex = totalPages;
                    startPageIndex -= result;
                }
                else
                {
                    endPageIndex = startPageIndex + 9;
                }
            }
            BindPageNum(startPageIndex, endPageIndex);
        }
        private void BindPageNum(int startPageIndex, int endPageIndex)
        {
            int[] pages = new int[endPageIndex - startPageIndex + 1];
            int index = 0;
            for (int i = startPageIndex; i <= endPageIndex; i++)
            {
                pages[index] = i;
                index++;
            }
            rptPageNumber.DataSource = pages;
            rptPageNumber.DataBind();
        }
        private void BindPagingHelperControl()
        {
            int totalPages = (TotalItemCount % PageSize) == 0 ? TotalItemCount / PageSize : TotalItemCount / PageSize + 1;
            //显示
            lbTotalPages.Text = totalPages.ToString();
            BindPageNum(totalPages);
            //使能
            lbtnFirstPage.Enabled = PageIndex > 1;
            lbtnPrevPage.Enabled = PageIndex > 1;
            lbtnLastPage.Enabled = PageIndex < totalPages;
            lbtnNextPage.Enabled = PageIndex < totalPages;
            //命令
            lbtnFirstPage.CommandArgument = "1";
            lbtnPrevPage.CommandArgument = (PageIndex - 1).ToString();
            lbtnNextPage.CommandArgument = (PageIndex + 1).ToString();
            lbtnLastPage.CommandArgument = totalPages.ToString();
        }
        private void ReBindData(int pageIndex)
        {
            PageIndex = pageIndex;
            OnPageIndexChanged(new EventArgs());
            BindPagingHelperControl();
        }
        #endregion
 
        #region 事件
        public delegate void PageIndexChangedEventHandler(object sender, EventArgs e);
        public event PageIndexChangedEventHandler PageIndexChanged;
        protected virtual void OnPageIndexChanged(EventArgs e)
        {
            PageIndexChangedEventHandler handler = PageIndexChanged;
            if (handler != null)
            {
                handler(this, e);
            }
        }
        #endregion
    }
}

作者:韩兆新
出处:http://hanzhaoxin.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

分类: [06]ASP.NET相关
标签: ASP.NET
本文转自韩兆新博客博客园博客,原文链接:http://www.cnblogs.com/hanzhaoxin/p/3871703.html,如需转载请自行联系原作者

Web用户控件开发--分页控件相关推荐

  1. 用C#编写ActiveX控件,开发浏览器控件,注册ActiveX 控件

    用C#编写ActiveX控件,开发浏览器控件,注册ActiveX 控件 用C#编写ActiveX控件 开发浏览器控件这是本控件开发完成后的一个简单应用.我们可以利用它以本地文件夹为单位来批量更新服务器 ...

  2. Winform分页控件之纯分页显示处理

    在之前介绍的Winform分页控件中,都以分页控件+显示表格控件作为一个整体性的控件,不可分开,这样做的目的是可以实现更多的操作,集成更多丰富的特性,减少我们开发的工作量,这种情况虽然适用于大多数的情 ...

  3. QuickPager asp.net 分页控件 转

    QuickPager asp.net 分页控件.表单控件等自定义控件下载 和介绍 最新下载地址: 自然框架的源代码.Demo.数据库.配置信息管理程序下载(2010.01.25更新) QuickCon ...

  4. 分页控件 实战 Post篇

    2019独角兽企业重金招聘Python工程师标准>>> 前言: 分页,大伙并不陌生 也许你正用着:DataGrid/GridView自带的分页 也许你正用着:网上流传较广的Aspne ...

  5. 开发和使用Web用户控件

    在 ASP.NET 的开发中 Web 用户控件的开发和使用是一项必不可少的技术,在对这项技术的一番研究后写下了这篇随笔,不过确实担心这么初级的东东放到原创首页上会被拍砖头. 1.简介 2.创建 Web ...

  6. C#自定义用户控件之分页

    形形色色的分页控件很多,有些可满足我们的要求,但有些却不一定,下面是我在工作当中遇到的问题而随手写了个能满足某些功能的自定义分页控件: 控件源代码: <%@ Control Language=& ...

  7. Web用户控件的一个毛病

    前几天发现的,今天好好审查的 的确是.net 2.0的问题,也不知道是微软.net小组特意的,就是我在自定义的web 用户控件中,自定义的一些字段后,在页面中的对它的字段赋值,但是在web用户自定义控 ...

  8. 读书笔记:《Aspx开发200问》——如何实现Repeater控件的分页

    由于Repeater控件没有分页相关的属性,要使用System.Web.UI.WebControl中的PageDataSource类. PageDataSource封装了DataGrid控件的分页属性 ...

  9. web developer tips (8):创建web用户控件并包含在web页面里

    原文地址: How to create an ASP.NET Web User Control and include it in your web page 使用Visual Web Develop ...

  10. VS2008 Tips #008 如何创建ASP.NET Web 用户控件并包含在Web 页面中

    在 Visual Web Developer 中创建 ASP.NET Web 用户控件就像 ASP.NET Page 页面一样简单. 以下是创建步骤: 1.打开您想添加用户控件的站点. 2.右键点击站 ...

最新文章

  1. 【全网最短】实现倒计时:时分秒的功能
  2. 深入理解javascript选择器API系列第二篇——getElementsByClassName
  3. java 中的路径问题总结(绝对路径与相对路径) .
  4. micropython按键控制流水灯_【micro:bit Micropython】The LED Display(1)控制像素点
  5. js中如何删除json对象的某一个选项
  6. Doxygen从零学起———安装和配置
  7. 前端学习(1603):脚手架组件使用
  8. spring学习(33):id和name
  9. 通过JS原型定义字符串格式化方法
  10. Midi 乐器set
  11. 修理计算机英语,英语口语对话:修理电脑
  12. logstash grok切分nginx日志
  13. hadoop错误:Does not contain a valid host:port authority
  14. iphone主屏幕动态壁纸_苹果11怎么设置动态壁纸?这个简单!只需这样操作
  15. 浅析帧、帧数、帧率、FPS区别
  16. Android ELF文件编译之符号隐藏
  17. 前端使用UtoVR Player全景视频播放器实现360°C全景VR视频
  18. 怎么删除计算机管理员用户密码,解除计算机管理员密码的方法
  19. php guzzle 上传文件,Guzzle 使用文档
  20. 解决vue+element 时间控件时间差,区域时差8小时

热门文章

  1. 菜鸟修行之路--Echarts数据可视化知识总结完整版
  2. 任泉自曝在Star VC年薪100万 今年重点投资互联网金融
  3. 华夏出入口车牌识别摄像机
  4. 大黄,不懂 HTTP 行嘛?
  5. MAC OS搭建pyhton+selenium+pycharm实现web自动化测试
  6. 两阶段目标检测详解--FastRCNN
  7. 面试时,如何正确介绍自己的项目经验?
  8. 80psi等于多少kpa_kpa与psi的换算(kpa与psi对照表)
  9. Django用户认证系统
  10. 未来物联网的一些问题