我在一个WebForms项目中,有必要对从存储过程中接收到的数据进行分页,我正在使用VS 2010 Framework 3.5,ASP.NET WebForms和SQL Server 2008。
这是存储过程:
@CantPagina INT, --Amount of registries per each page
@Pagina INT, --Amount of pages
@AsuntoVariable VARCHAR(100), --Search variable
@IdComercio VARCHAR(100), --Search variable
@FechaEnvioDesde DATE, --Search variable
@FechaEnvioHasta DATE, --Search variable
@DescripcionLarga VARCHAR(100), ---Search variable
@Destinatario VARCHAR(100) --Search variable
AS
BEGIN
SET NOCOUNT ON;
DECLARE
@FechaMin DATE = (SELECT CAST(-53690 AS DATETIME)), --Search variable
@FechaMax DATE = GETDATE() --Search variable
--If number of pages is 0 or null, return all data
IF (@CantPagina = 0 OR @CantPagina IS NULL)
BEGIN
SET @CantPagina = 2147483646
END;
IF (@Pagina = 0 OR @Pagina IS NULL)
BEGIN
SET @Pagina = 1
END;
IF(@IdComercio = '-1')
BEGIN
SET @IdComercio = ''
END;
WITH PageNumbers AS
(
SELECT TOP 100 PERCENT
mda.IdComercio, mda.FechaEnvio, tda.DescripcionLarga, mda.Destinatario, mda.AsuntoVariable,
ROW_NUMBER() OVER(ORDER BY mda.FechaEnvio DESC) AS NumFila --Creo columna n + 1
FROM
tm_mda_mail_de_alerta_wcom AS mda
INNER JOIN
tm_tda_tipos_de_alerta_wcom AS tda ON mda.IdTipo = tda.IdTipo
WHERE
mda.AsuntoVariable LIKE '%' + @AsuntoVariable + '%'
AND tda.DescripcionLarga LIKE '%' + @DescripcionLarga + '%'
AND mda.Destinatario LIKE '%' + @Destinatario + '%'
AND mda.FechaEnvio BETWEEN ISNULL(@FechaEnvioDesde, @FechaMin) AND ISNULL(DATEADD(DAY, 1, @FechaEnvioHasta), @FechaMax)
AND CAST(mda.IdComercio AS VARCHAR(20)) LIKE '%' + @IdComercio + '%'
ORDER BY
mda.FechaEnvio DESC)
SELECT *
FROM PageNumbers
WHERE NumFila BETWEEN ((@Pagina - 1) * @CantPagina + 1)
AND (@Pagina * @CantPagina)
END
后端就像这样:
在Page_Load
内的(!IsPostBack)
中:
TraerAlertaCargarGrilla(new WC.Paginacion() { Pagina = PAGINA, RegistrosPorPagina = CANTPAGINA });
然后我调用此方法:
private void TraerAlertaCargarGrilla(WC.Paginacion paginacion)
{
try
{
List<Alerta> alertas = CargarLogEnvioMails(paginacion);
CargarGrillaEnvioMails(alertas);
}
catch (Exception ex)
{
MensajeFront.Mostrar(Page.Title, Resources.Facturacion.Error_Generico_Usuario, Controles_Comunes_wucMensaje.TipoMensaje.Info);
log.Error(String.Format(Resources.Facturacion.LogError, Helper.TraerNombreDelMetodo()), ex);
throw ex;
}
}
然后我将此方法称为:
private List<Alerta> CargarLogEnvioMails(WC.Paginacion paginacion)
{
List<Alerta> logAlertas = new List<Alerta>();
int noFiltrarPorComercio = -1;
try
{
WC.AlertaDTOResp alertaDTOResp = new WC.AlertaDTOResp() { ListaDeAlertas = new WC.ListaDeAlertas() };
WC.AlertaDTOReq alertaDTOReq = new WC.AlertaDTOReq()
{
TipoOperacion = WC.Accion.Consultar,
Operacion = Constantes.Consultas.Alertas.CONSULTA_LOG_ALERTAS,
Paginacion = paginacion,
ListaDeAlertas = new WC.ListaDeAlertas()
{
new WC.AlertaDTO()
{
AsuntoVariable = txtRazon.Text,
IdComercio = txtComercio.Text == String.Empty ? noFiltrarPorComercio : Convert.ToInt32(txtComercio.Text),
FechaDesde = txtFechaDesde.Text == String.Empty ? DateTime.MinValue : Convert.ToDateTime(txtFechaDesde.Text),
FechaHasta = txtFechaHasta.Text == String.Empty ? DateTime.Now : Convert.ToDateTime(txtFechaHasta.Text),
Destinatario = txtDestinatario.Text,
TipoAlerta = new List<WC.TipoAlertaDTO>()
{
new WC.TipoAlertaDTO()
{
DescripcionLarga = txtDescripcion.Text
}
}
}
}
};
using (WC.FacturaClient fc = new WC.FacturaClient())
{
alertaDTOResp = fc.AlertasEjecutar(alertaDTOReq);
}
foreach (var item in alertaDTOResp.ListaDeAlertas)
{
logAlertas.Add(new Alerta()
{
AsuntoVariable = item.AsuntoVariable,
DescripcionLarga = item.TipoAlerta.FirstOrDefault().DescripcionLarga,
Destinatario = item.Destinatario,
FechaEnvio = item.FechaEnvio,
IdComercio = item.IdComercio,
});
}
PopularPager(alertaDTOResp.TotalRegistros, paginacion.Pagina);
return logAlertas;
}
catch (Exception ex)
{
MensajeFront.Mostrar(Page.Title, Resources.Facturacion.Error_Generico_Usuario, Controles_Comunes_wucMensaje.TipoMensaje.Info);
log.Error(String.Format(Resources.Facturacion.LogError, Helper.TraerNombreDelMetodo()), ex);
throw ex;
}
}
然后我叫PopularPager(PopulatePager):
private void PopularPager(int conteoRegistros, int paginaActual)
{
try
{
string primero = "First";
string ultimo = "last";
string primerPagina = "1";
double cantPag = (double)((decimal)conteoRegistros / decimal.Parse(ddlTamañoPagina.SelectedValue));
int paginas = (int)Math.Ceiling(cantPag);
List<ListItem> paginasListItem = new List<ListItem>();
if (paginas > 0)
{
paginasListItem.Add(new ListItem(primero, primerPagina, paginaActual > 1));
for (int i = 1; i <= paginas; i++)
{
paginasListItem.Add(new ListItem(i.ToString(), i.ToString(), i != paginaActual));
}
paginasListItem.Add(new ListItem(ultimo, paginas.ToString(), paginaActual < paginas));
}
rptPager.DataSource = paginasListItem;
rptPager.DataBind();
}
catch (Exception ex)
{
MensajeFront.Mostrar(Page.Title, Resources.Facturacion.Error_Generico_Usuario, Controles_Comunes_wucMensaje.TipoMensaje.Info);
log.Error(String.Format(Resources.Facturacion.LogError, Helper.TraerNombreDelMetodo()), ex);
throw ex;
}
}
我将我从SP接收的页面数量和每页注册表数量绑定到此repeater
,repeater
将在寻呼机上创建每个号码,因此,如果我有1000个注册表按10个注册表,我将拥有100页。
我想做的事,我认为PopularPager
方法是我必须修改的一种方法,是将人们可以看到的页面数量限制为20,当按下20时又转到20注册表。如果按下第一个按钮,也是如此。
我该如何实现?
编辑:
通过浏览不同的网站,我发现了一种有趣的方法来解决此来源:https://www.aspforums.net/Threads/106478/Numeric-paging-in-ASPNet-Repeater-with-Next-and-Previous-Button-using-C-and-VBNet/,因此我像下面这样替换了初始方法PopularPager
(PopulatePager):
private void PopularPager(int conteoRegistros, int paginaActual)
{
double dblPageCount = (double)((decimal)conteoRegistros / decimal.Parse(ddlTamañoPagina.SelectedValue));
int pageCount = (int)Math.Ceiling(dblPageCount);
List<ListItem> pages = new List<ListItem>();
int cantMaxPaginas = 20;
if (pageCount > 0)
{
pages.Add(new ListItem("Primero", "1", paginaActual > 1));
if (paginaActual != 1)
{
pages.Add(new ListItem("Atras", (paginaActual - 1).ToString()));
}
if (pageCount < cantMaxPaginas)
{
for (int i = 1; i <= pageCount; i++)
{
pages.Add(new ListItem(i.ToString(), i.ToString(), i != paginaActual));
}
}
else if (paginaActual < cantMaxPaginas)
{
for (int i = 1; i <= cantMaxPaginas; i++)
{
pages.Add(new ListItem(i.ToString(), i.ToString(), i != paginaActual));
}
pages.Add(new ListItem("...", (paginaActual).ToString(), false));
}
else if (paginaActual > pageCount - cantMaxPaginas)
{
pages.Add(new ListItem("...", (paginaActual).ToString(), false));
for (int i = paginaActual - 1; i <= pageCount; i++)
{
pages.Add(new ListItem(i.ToString(), i.ToString(), i != paginaActual));
}
}
else
{
pages.Add(new ListItem("...", (paginaActual).ToString(), false));
for (int i = paginaActual - 2; i <= paginaActual + 2; i++)
{
pages.Add(new ListItem(i.ToString(), i.ToString(), i != paginaActual));
}
pages.Add(new ListItem("...", (paginaActual).ToString(), false));
}
if (paginaActual != pageCount)
{
pages.Add(new ListItem("Siguiente", (paginaActual + 1).ToString()));
}
pages.Add(new ListItem("Ultimo", pageCount.ToString(), paginaActual < pageCount));
}
rptPager.DataSource = pages;
rptPager.DataBind();
}
问题是,当我浏览这些页面时,它显示的是该页面的n-1,而不是其中的5,例如: 如果我有... 10 11 12 13 14 15 ...如果我单击10,它至少应向我显示... 5 6 7 8 9 10 ...并选择10作为ListItem(并且启用了CSS类) ),但仅显示3,我认为问题出在方法的这一部分:
else if (paginaActual > pageCount - cantMaxPaginas)
{
pages.Add(new ListItem("...", (paginaActual).ToString(), false));
for (int i = paginaActual - 1; i <= pageCount; i++)
{
pages.Add(new ListItem(i.ToString(), i.ToString(), i != paginaActual));
}
}
paginaActual
和pageCount
之间的差异很小(Aprox 3或4),这就是为什么要迭代这么小的金额。
也许减去恒定数量的也许另外2个可以解决问题?