سلام.
چیزی که شما دنبالش میگردید، در سی شارپ اصطلاحا بهش Paging (صفحه بندی کردن) گفته میشه. مثلا زمانیکه تعداد رکوردهای جدولمون زیاد هست هم بخاطر اینکه سرعت Load کردن اطلاعات زیاد بشه و هم اینکه واقعا تعداد رکوردهای زیاد در یک لحظه به درد کاربر نمی خوره، از این paging استفاده می کنن که البته بسیار پر کاربرد هم هست.
من مراحل کار رو به همراه کدهای مورد نظر قدم به قدم توضیح میدم تا کامل متوجه موضوع بشید.
اصول کار اینه که شما یه عدد بعنوان تعداد رکوردهای هر صفحه باید مشخص کنید. مثلا هر صفحه (هر نمایش گرید) شامل 10 رکورد باشه.
برای بار اول (page = 1) بایستی 10 رکورد اول (رکوردهای 1 تا 10) ، برای بار دوم (page = 2) بایستی 10 رکورد دوم (رکوردهای 11 تا 20) و ...
پس نیاز داریم که علاوه بر مشخص شدن تعداد رکوردهای هر نمایش، بدونیم هر بار که درخواست میدیم، چندین نمایش (چندمین page) رو درخواست دادیم.
مطلب بعدی در زمان انتخاب رکوردهای هر page اینه که باید محدوده این رکوردها مشخص باشه که از چه شماره ای تا چه شماره ای رو برگردونه. مثلا برای page = 2 باید از رکودهای 11 تا 20 رو برامون برگردونه.
حالا می خوام این توضیحات رو در قالب کد sql مورد نظر بیارم. در ادامه من از یک stored procedure برای این کار استفاده میکنم.
برای این کار در سمت sql، ابتدا یک جدول موقت ایجاد می کنم که فیلدهای این جدول دقیقا مثل فیلدهای جدول اصلیتون هست و تمام رکوردهای جدول مورد نظرم رو داخل این جدول موقت می ریزم و یک فیلد ID هم خودم به این جدول بصورت Identity اضافه می کنم. این فیلد بخاطر این هست که می خوام رکوردهای جدول، شماره پشت سر هم داشته باشند. اکیدا" توصیه می کنم حتی اگر جدولتون فیلد Identity داره باز هم این فیلدی رو که در sp پایین هست بهش دست نزنید. چون ممکنه با اینکه جدول شما فیلد identity داشته باشه ولی ازش رکوردهایی رو حذف کرده باشید و ترتیب شماره های فیلد identity بهم خورده باشه.
در کد زیر همونطور که در بالا هم اشاره کردم، نیاز دارید که تعداد رکوردهای درخواستی و شماره page درخواستی و همچنین محدوده رکوردهایی که باید واکشی بشن رو داشته باشیم(متغیرهای FirstRecord@ و LastRecord@ دقیقا برای همین منظور تعریف شدن).
نحوه محاسبه FirstRecord@ و LastRecord@ هم با یک عدد گذاری ساده می تونید کاملا متوجهش بشید.
با این توضیحات کد stored procedure زیر رو ملاحظه بفرمایید :
Create PROCEDURE [dbo].[sp_PagedItem]
(
@Page int,
@RecordsPerPage int
)
AS
CREATE
TABLE #TempItems
(
ID int IDENTITY,Order_Id int ,OrderNumber int,Person_Id int
)
INSERT
INTO #TempItems(O_Id,OrderNo,P_Id)
SELECT * FROM Orders
DECLARE
@FirstRecord int, @LastRecord int
SELECT
@FirstRecord =(@Page - 1)* @RecordsPerPage
SELECT
@LastRecord =((@Page * @RecordsPerPage) + 1)
SELECT
*
FROM
#TempItems
WHERE
ID > @FirstRecord AND ID < @LastRecord
حالا در سمت برنامه، یک گرید داشته باشید و دو دکمه Next و Previous برای نمایش رکوردهای بعدی و قبلی.
زمانی می تونید رکوردهای بعدی رو نمایش بدید که واقعا رکوردی باقی مونده باشه (تعداد page های کل جدول شما بزرگتر از page جاری شما باشه. مثلا کل جدول شما 5 صفحه هست و شما الان در صفحه 4 هستید) و همچنین زمانی می تونید رکوردهای قبلی رو نمایش بدید که page جاری شما بزرگتر از 1 باشه (مثلا در page = 2 هستید و می خواید page قبلی یعنی page = 1 رو نمایش بدید).
در لحظه Load با استفاده از همین sp تعداد رکورد مد نظرتون (مثلا 10 رکورد برای هر بار نمایش) رو واکشی کنید و درون گرید نمایش بدید.همونطور که در بالا هم توضیح دادم شما در هر بار فراخوانی sp باید شماره page جاری (بار اول در رویداد load میشه page = 1) و تعداد رکوردهای مد نظرتون رو برای sp بفرستید.
برای شماره page جاری یه متغیر سراسری از نوع int تعریف کنید مثلا CurrentPage و در رویداد Load بعد از واکشی رکوردها و نمایش اونها در گرید، مقدارش رو 1 قرار بدید. از این به بعد هر وقت روی دکمه بعدی کلیک می کنید باید در انتهای کدهای دکمه (تاکید میکنم در انتهای کدهای دکمه) به این متغیر CurrentPage یک واحد اضافه کنید و هر بار روی دکمه قبلی کلیک می کنید باید در انتهای کدهای دکمه (تاکید میکنم در انتهای کدهای دکمه) از این متغیر CurrentPage یک واحد کم کنید.
تمام این صحبت ها در کدهای زیر به روشنی قابل دیدن هستن (در سازنده فرم که قبل از رویداد Load اجرا میشه، تعداد کل صفحات جدول محاسبه شده که در شرط if از این مقدار استفاده کردیم) :
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;
namespace test
{
public partial class frmpaging : Form
{
SqlConnection con = new SqlConnection("Server = .\\md2012;DataBase = testsql;Integrated Security = true");
int TotalPages;
int currentpage = 0;
public frmpaging()
{
InitializeComponent();
// بدست آوردن تعداد کل صفحات موجود در جدول در سازنده. تابع سازنده قبل از رویداد لود اجرا میشه
SqlDataAdapter da = new SqlDataAdapter("select count(*) from orders", con);
DataTable dt = new DataTable();
da.Fill(dt);
TotalPages = Convert.ToInt32(dt.Rows[0][0].ToString()) / 10;
}
//
private void BtnNext_Click(object sender, EventArgs e)
{
// اگر صفحه جاری کوچکتر از تعداد کل صفحات باشه، صفحه بعدی وجود خواهد داشت
if(currentpage < TotalPages)
{
SqlDataAdapter da = new SqlDataAdapter("sp_pagedItem", con);
da.SelectCommand.CommandType = CommandType.StoredProcedure;
da.SelectCommand.Parameters.AddWithValue("@page", currentpage + 1);
da.SelectCommand.Parameters.AddWithValue("@RecordsPerPage", 10);
DataTable dt = new DataTable();
da.Fill(dt);
dataGridView1.DataSource = dt;
currentpage++;
}
}
//
private void BtnPrevious_Click(object sender, EventArgs e)
{
// اگر صفحه جاری بزرگتر از 1 باشه، صفحه قبلی وجود خواهد داشت
if (currentpage > 1)
{
SqlDataAdapter da = new SqlDataAdapter("sp_pagedItem", con);
da.SelectCommand.CommandType = CommandType.StoredProcedure;
da.SelectCommand.Parameters.AddWithValue("@page", currentpage - 1);
da.SelectCommand.Parameters.AddWithValue("@RecordsPerPage", 10);
DataTable dt = new DataTable();
da.Fill(dt);
dataGridView1.DataSource = dt;
currentpage--;
}
}
//
private void frmpaging_Load(object sender, EventArgs e)
{
// اولین بار در اجرای فرم برنامه، رکوردهای مورد نظر رو از جدول واکشی میکنه و به کاربر نمایش میده
SqlDataAdapter da = new SqlDataAdapter("sp_pagedItem", con);
da.SelectCommand.CommandType = CommandType.StoredProcedure;
da.SelectCommand.Parameters.AddWithValue("@page", 1);
da.SelectCommand.Parameters.AddWithValue("@RecordsPerPage", 10);
DataTable dt = new DataTable();
da.Fill(dt);
dataGridView1.DataSource = dt;
currentpage = 1;
}
}
}
موفق باشید.