# برنامه نویسی با محصولات مایکروسافت > برنامه نویسی مبتنی بر Microsoft .Net Framework > ASP.NET Web Forms > مقاله: آموزش پیاده سازی Custom Paging در GridView با تکنولوژی Ajax

## alonemm

باسلام:
موضوع:
چندی هست که توی این تالار سوالات متعددی در ضمینه پیجینگ و پیاده سازی اون در GridView مطرح میشه و پاسخ های متعددی هم داده میشه و یک تاپیک در این مورد که به نتیجه برسه نبوده.
هدف از این مقاله:
پیاده سازی پیجینگ دستی به کمک تکنولوژی Ajax. 
مقدمه:
همونطور که میدونید در بحث برنامه نویسی سمت وب یکی از مهمترین مسائل سرعت لود صفحه میباشد.
خب شما در نظر داشته باشید که یک جدول با 10000 رکورد دارید و میخواید این اطلاعات رو به کاربر نمایش بدید.
در دید اول که شما نمیتونید تمامی این رکورد ها رو در یک صفحه به نمایش در بیارید چون یک صفحه با این مقدار رکورد هم کلی پیمایش لازم داره هم لود صفحه طول میکشه.
معمولا کاربران از خاصیت Paging گرید برای نمایش تعداد خاصی از رکورد ها در صفحه جاری استفاده میکنند.
اما مشکل این قسمت این هست که عملیات پیجینگ در این قسمت به صورت مجازی شکل میگیره.
یعنی کل رکورد ها در فضای حافظه شما لود میشه و فقط چندتا رکورد جاری نمایش پیدا میکنه که به این معنا هست که تمامی رکوردها از سمت پایگاه داده واکشی شده و این زمان لود در حافظه سرعت صفحه رو پایین میاره و اگه بخواید این کار رو بدون بازسازی صفحه یعنی با استفاده از Ajax انجام بدید که خیلی کندتر عمل میکنه.

خب در این مقاله میخوایم با هم یک پیجینگ دستی درست کنیم که در هر صفحه فقط به تعداد لازم از پایگاه داده عملیات واکشی انجام بشه بدون بازسازی صفحه با Ajax.


فایل پروژه رو هم میتونید از لینک زیر دریافت کنید:
http://www.mediafire.com/?v86e97m858693bi

پاورقی:
دوستان خواهش میکنم از پست های اضافه و فاقد محتوی فنی خوداری کنید تا تاپیک تمیز تر بمونه.
باتشکر.

----------


## alonemm

بریم برای طراحی در قالب یک پروژه کاربردی:
اول یک عکس از کل کار ببینیم:

----------


## alonemm

طراحی سمت پایگاه داده:
یک جدول داریم با 2 ستون.
1- شناسه - ID
2- نام شهر- display_name

CREATE TABLE [dbo].[city](
	[id] [smallint] NOT NULL,
	[display_name] [nvarchar](50) NOT NULL,


پس تا اینجا جدول شهر در پایگاه داده مورد نظر رو ساختید.

----------


## alonemm

در این مرحله به سراغ ساخت یک Stored Procedures یا همان رویه های ذخیره شده در SQL Server میریم.
این رویه ذخیره شده عملیات واکشی داده به تعداد دلخواه رو انجام میده.
خب اول کد ساختشو ببینیم:

USE [DBName]
GO

/****** Object:  StoredProcedure [dbo].[CastumPaging]    Script Date: 02/24/2012 02:31:44 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

Create PROCEDURE  [dbo].[CastumPaging]
(
   @SqlTableName nvarchar(100),
   @PageIndex int,
   @PageSize int
)
AS
BEGIN
declare @SQLText nvarchar(500)
--set @SqlTableName = 'City'
--set @PageIndex = 0
--set @PageSize = 21
set @SQLText = 'SELECT * FROM (SELECT * , ROW_NUMBER() OVER(ORDER BY id) as RowNum FROM '+@SqlTableName+'  ) as DerivedTableName WHERE RowNum BETWEEN '+ str(@PageIndex) +' AND'+ str((@PageIndex+ @PageSize) - 1)  
exec(@SQLText)
END
GO

همونطور که مشخصه این رویه ذخیره شده دارای 3 پارامتر هست:
1- نام جدول--SqlTableName
2-شماره شروع--PageIndex
3-تعداد--PageSize

که در کد بالا این پارامتر ها رو مقدار دادم که به صورت کامنت هست و میتونید از کامنت در بیارید و نتیجه اجرا رو ببینید.
درباره کارکرد این رویه هم باید بگم که نام جدول مربوطه رو و بازه رکوردهایی که میخواید واکشی بشند رو به عنوان پارامتر به این رویه ذخیره شده ارسال میکنید و مهمترین کار این رویه این هست که با دستور :

 ROW_NUMBER() OVER(ORDER BY id) as RowNum

یک ستون میسازه به نام RowNum که به ازاء هر ردیف یک شماره تعلق میگیره که از 1 شروع میشه.
بعد بازه بین دو عدد پارامتر ورودی که ما دادیم انتخاب شده و عملیات واکشی انجام میشه.
این پروسیجر رو به شکل زیر اجرا کنید:( در محیط SQLServer)

exec CastumPaging '[city]',0,10

میبینید که به تعداد مورد نظر عملیات واکشی رکورد ها انجام شده.

----------


## alonemm

خب کار ما سمت پایگاه داده به پایان رسید کم کم به سراغ پیاده سازی وب فرم هامون میریم.

یک پروژه وب سایت باز کنید.
یک صفحه وب به نام دلخواه بسازید.
یک کنترل گرید به صفحه اضافه کنید.
مثل :

            <asp:GridView ID="GridView1" runat="server" 
             AutoGenerateColumns="False" ondatabound="GridView1_DataBound" 
             BackColor="White" 
             BorderColor="#E7E7FF" BorderStyle="None" BorderWidth="1px" CellPadding="3" 
             GridLines="Horizontal" EmptyDataText="جدول خالی میباشد" Font-Bold="False" 
             Font-Names="Tahoma" Font-Size="Small" Width="70%" 
            >
            <AlternatingRowStyle BackColor="#F7F7F7" />
            <Columns>
                    <asp:BoundField DataField="display_name" HeaderText='نام شهر'  ItemStyle-Width="50px" >
                        <ItemStyle Width="50px" HorizontalAlign="Center" VerticalAlign="Middle"></ItemStyle>
                    </asp:BoundField>
                    <asp:BoundField DataField="id" HeaderText='شناسه' ItemStyle-Width="50px" >
                        <ItemStyle Width="50px">
                        </ItemStyle>
                    </asp:BoundField>
                    <asp:TemplateField HeaderText='ردیف' HeaderStyle-Width="40px">
                    <ItemTemplate>
                       <asp:Label  runat="server" ID='lbl' Width="25px" Height="25px" Text='<%# Eval("RowNum") %>'/>
                    </ItemTemplate>
                  <HeaderStyle Width="40px"></HeaderStyle>
                  </asp:TemplateField>
            </Columns> 
                <FooterStyle BackColor="#B5C7DE" ForeColor="#4A3C8C" />
                <HeaderStyle BackColor="#4A3C8C" Font-Bold="True" ForeColor="#F7F7F7" 
                    HorizontalAlign="Center" VerticalAlign="Middle" />
                <PagerStyle BackColor="#E7E7FF" ForeColor="#4A3C8C" HorizontalAlign="Right" />
                <RowStyle BackColor="#E7E7FF" ForeColor="#4A3C8C" HorizontalAlign="Center" 
                    VerticalAlign="Middle" />
                <SelectedRowStyle BackColor="#738A9C" Font-Bold="True" ForeColor="#F7F7F7" />
                <SortedAscendingCellStyle BackColor="#F4F4FD" />
                <SortedAscendingHeaderStyle BackColor="#5A4C9D" />
                <SortedDescendingCellStyle BackColor="#D8D8F0" />
                <SortedDescendingHeaderStyle BackColor="#3E3277" />
        </asp:GridView>


با کد بالا ما یک گرید ساختیم همانند عکسی که در پست شماره 2 هستش.

----------


## alonemm

در این فاز کاری میخوایم مراحل انعقاد و بایند کردن گرید رو انجام بدیدم.
یعنی با پایگاه داده ارتباط برقرار کنیم و سپس با ارسال پارامترها رکوردهای مورد نظر رو از جدول واکشی کنیم.
برای این کار چون در یک پروژه شما تعداد جدول ها و صفحات متفاوتی دارید ما این متدها رو در قالب یک کلاس تعریف میکنیم که در همجا قابل استفاده باشند:
در پوشه App_Code یک کلاس به نام Code میسازیم همانند کد زیر:

using System.Configuration;
using System.Data;
using System.Data.SqlClient;

/// <summary>
/// Majid Maghsoudipour
/// Class Connect To SP CastumPaging
/// </summary>
///

[System.ComponentModel.DataObject]
public class Cod
{
    public Cod()
    {

    }

    public string ConnectionString
    {
        get
        {
            return ConfigurationManager.ConnectionStrings["ConnectionString"].ToString();
        }
    }

    public DataSet ExecuteDataset(string SQLTableName,int PageIndex, int PageSize)
    {
        using (SqlConnection con = new SqlConnection(ConnectionString))
        {
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = con;
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.CommandText = "[CastumPaging]";
            cmd.Parameters.AddWithValue("@SqlTableName", SQLTableName);
            cmd.Parameters.AddWithValue("@PageIndex", PageIndex);
            cmd.Parameters.AddWithValue("@PageSize", PageSize);
            DataSet ds = new DataSet();
            SqlDataAdapter da = new SqlDataAdapter(cmd);
            con.Open();
            da.Fill(ds);
            con.Close();
            return ds;
        }
    }

    public int countall(string SQLTableName)
    {
        using (SqlConnection con = new SqlConnection(ConnectionString))
        {
            con.Open();
            string commandText55 = "select  count(id)as mm from " + SQLTableName + " ";
            SqlCommand cmdObj55 = new SqlCommand(commandText55, con);
            SqlDataReader ddr = cmdObj55.ExecuteReader();
            ddr.Read();
            int code22;
            if (ddr.HasRows == true)
            {
                code22 = int.Parse(ddr["mm"].ToString());
                con.Close();
                return code22;
            }
            else
                con.Close();
            return 0;
        }
    }
}

----------


## alonemm

خب حالا که کلاس مورد نظر رو ساختید کمی در مورد اجزاء این کلاس میگم:
دیاگرام این کلاس ضمیمه شده.
1 پراپرتی به نام ConnectionString از جنس رشته هست که فقط خواندنی هست که عملیات خواندن رشته اتصال به پایگاه داده رو از فایل WebConfig به عهده داره.
متد countall:
نام جدول رو به عنوان پارامتر دریافت میکنه و تعداد کل رکورد هاشو برمیگردونه از جنس عدد.
متد ExecuteDataset:
نام جدول و شناسه شروع (شماره صفحه) و تعداد رکورد نمایشی رو به عنوان پارامتر دریافت میکنه و بارقراری ارتباط با پایگاه داده و ارسال این پارامتر ها به رویه ذخیره شده که در پست های قبل ساختیم این رویه رو اجرا کرده و رکوردهای مورد نظر رو واکشی میکنه و توسط یک شی دیتاسورس به نام Dataset برمیگردونه که قابل بایند شدن به گرید هستش.

----------


## alonemm

باسلام:
خب در این قسمت میخوایم دکمه هایی که زیر گرید هست و برای پیمایش بین صفحات هستن و یک تکس باکس که شماره صفحه رو میگیره رو طراحی کنیم:
کد:

<asp:Table ID="Table1" runat="server" Font-Names="Tahoma" Font-Size="Small">
                <asp:TableRow ID="TableRow1" runat="server">
                    <asp:TableCell ID="TableCell1" runat="server"><asp:ImageButton ID="btnStart" runat="server" 
                ImageUrl="~/Images/1322728593_control_start_blue.png" 
                onclick="btnStart_Click" /></asp:TableCell>
                    <asp:TableCell ID="TableCell2" runat="server">
                        <asp:ImageButton ID="btnPrevious0" runat="server" 
                ImageUrl="~/Images/1322728647_Play1Pressed - Copy.png" 
                onclick="btnPrevious0_Click" /></asp:TableCell>
                    <asp:TableCell ID="TableCell3" runat="server"></asp:TableCell>
                    <asp:TableCell ID="TableCell4" runat="server"><asp:TextBox ID="txtPageNumber" runat="server" Text="1" ontextchanged="txtPageNumber_TextChanged" 
                Width="25" AutoPostBack="True" onkeyup="FilterEnterNumber(this,10000)"></asp:TextBox> </asp:TableCell>
                    <asp:TableCell ID="TableCell5" runat="server">
                       <asp:ImageButton ID="btnNext" runat="server" 
                ImageUrl="~/Images/1322728647_Play1Pressed.png" onclick="btnNext_Click" />
                       </asp:TableCell>
                    <asp:TableCell ID="TableCell6" runat="server"><asp:ImageButton ID="btnEnd" runat="server" 
                ImageUrl="~/Images/1322728537_control_end_blue.png" onclick="btnEnd_Click" /></asp:TableCell>
                </asp:TableRow>
            </asp:Table>

----------


## alonemm

پس از طراحی قسمت پیمایشی وارد قسمت کد نویسی صفحه میشیم:
از کلاسی که قبلا ساختیم یک نمونه سازی انجام میدیم تا در هر متدی ازش در صفحه استفاده کنیم:

Cod ADO = new Cod();


ما برای نگه داری داده هایی که در صفحه داریم از ViewState استفاده میکنیم.

 #region Property
    protected int PageIndex
    {
        get
        {
            object value = this.ViewState["PageIndex"];
            if (value != null)
                return System.Convert.ToInt32(value);
            else
                return 1;
        }
        set
        {
            this.ViewState["PageIndex"] = value;
        }
    }

    protected int PageCount
    {
        get
        {
            object value = this.ViewState["PageCount"];
            if (value != null)
                return System.Convert.ToInt32(value);
            else
                return 1;
        }
        set
        {
            this.ViewState["PageCount"] = value;
        }
    }

    protected int PageSize
    {
        get
        {
            object value = this.ViewState["PageSize"];
            if (value != null)
                return System.Convert.ToInt32(value);
            else
                return 1;
        }
        set
        {
            this.ViewState["PageSize"] = value;
        }
    }

    public string SQLTableName 
    {
        get
        {
            object value = this.ViewState["SQLTableName"];
            if (value != null)
                return value.ToString();
            else
                return null;
        }
        set
        {
            this.ViewState["SQLTableName"] = value;
        }
    }
    #endregion

----------


## alonemm

پس از ساخت این 4 خواص متدهای زیر رو قرار میدیم:

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            SQLTableName = "[city]";
            PageSize = 10;
            PageIndex = 1;
            PageCount = Convert.ToInt32(Math.Ceiling((double)ADO.countall(  SQLTableName) / (double)PageSize));
            DataBindGrid(); 
        }
    }


    private void DataBindGrid()
    {
        GridView1.DataSource = ADO.ExecuteDataset(SQLTableName, PageIndex , PageSize);
        GridView1.DataBind();
    }

----------


## alonemm

همونطور که دیدید مقادیر 4 خواص که از نام هاشون مشخص هستند مقدار دهی شد.
و یک متد داریم(DataBindGrid) که عملیات انعقاد داده رو به عهده داره و به کلاس Cod و متد ExecuteDataset متصل میشه و پارامترها رو ست میکنه و دیتا سورس مورد نظر رو برمیگردونه.

----------


## alonemm

خب در این قسمت به تعریف متدهای دکمه هایی که در پست 8 تعریف کردیم میریم:

 protected void btnStart_Click(object sender, ImageClickEventArgs e)
    {
        PageIndex = 1;
        DataBindGrid();
    }
    protected void btnPrevious0_Click(object sender, ImageClickEventArgs e)
    {
        if ((PageIndex - PageSize) > 1)
            PageIndex -= PageSize;
        else
            PageIndex = 1;
        DataBindGrid();
    }
    protected void btnNext_Click(object sender, ImageClickEventArgs e)
    {
        if ((PageIndex + PageSize) < (PageSize * PageCount))
            PageIndex += PageSize;
        else
            PageIndex = (PageSize * PageCount) - PageSize;
        DataBindGrid();
    }
    protected void btnEnd_Click(object sender, ImageClickEventArgs e)
    {
        PageIndex = (PageSize * PageCount) - PageSize;
        DataBindGrid();
    }
    protected void txtPageNumber_TextChanged(object sender, EventArgs e)
    {
        if (!string.IsNullOrEmpty(txtPageNumber.Text))
        {
            PageIndex = (int.Parse(txtPageNumber.Text)-1) * PageSize ;
            DataBindGrid();
        }
    }

----------


## alonemm

همونطور که در عکس پست 2 دید در پایین دکمه ها یک جدول هست که گزارشی از پیمایش شما در گرید میده:
کد طراحی:

<asp:Table ID="Table2" runat="server" Font-Names="Tahoma" Font-Size="Small">
                <asp:TableRow ID="TableRow2" runat="server">
                <asp:TableCell ID="TableCell7" runat="server">رکورد</asp:TableCell>
                <asp:TableCell ID="TableCell8" runat="server">
                    <asp:Label ID="Label8" runat="server" Text="Label" BackColor="BlanchedAlmond"></asp:Label></asp:TableCell>
                <asp:TableCell ID="TableCell9" runat="server">از</asp:TableCell>
                <asp:TableCell ID="TableCell10" runat="server">
                    <asp:Label ID="Label7" runat="server" Text="Label" BackColor="BlanchedAlmond"></asp:Label></asp:TableCell>
                    <asp:TableCell ID="TableCell11" runat="server">تا</asp:TableCell>
                    <asp:TableCell ID="TableCell12" runat="server">
                        <asp:Label ID="Label6" runat="server" Text="Label" BackColor="BlanchedAlmond"></asp:Label></asp:TableCell>
                    <asp:TableCell ID="TableCell13" runat="server">پیمایش رکودهای</asp:TableCell>
                    <asp:TableCell ID="TableCell14" runat="server">-------</asp:TableCell>
                    <asp:TableCell ID="TableCell15" runat="server">
                        <asp:Label ID="Label5" runat="server" Text="Label" BackColor="BlanchedAlmond"></asp:Label></asp:TableCell>
                    <asp:TableCell ID="TableCell16" runat="server">از</asp:TableCell>
                    <asp:TableCell ID="TableCell17" runat="server">
                        <asp:Label ID="Label4" runat="server" Text="Label" BackColor="BlanchedAlmond"></asp:Label></asp:TableCell>
                    <asp:TableCell ID="TableCell18" runat="server">نمایش صفحه</asp:TableCell>
                </asp:TableRow>
            </asp:Table>

----------


## alonemm

و در متد زیر مقدار دهی میکنیم:

 protected void GridView1_DataBound(object sender, EventArgs e)
    {
        Label1.Text = "PageIndex: " + PageIndex.ToString();
        Label2.Text = "PageSize: " + PageSize.ToString();
        Label3.Text = "PageCount: " + PageCount.ToString();
        if (PageIndex != 1)
            Label4.Text = ((PageIndex / PageSize)+1).ToString();
        else
            Label4.Text = PageIndex.ToString();
        Label5.Text = PageCount.ToString();

        Label6.Text = PageIndex.ToString();
        
        if(PageIndex == ((PageSize * PageCount) - PageSize) )
            Label7.Text = ADO.countall(SQLTableName).ToString();
        else
            Label7.Text = ((PageIndex + PageSize) - 1).ToString();
        
         Label8.Text = ADO.countall(SQLTableName).ToString();
         txtPageNumber.Text = ((PageIndex / PageSize)+1).ToString();
    }

----------


## alonemm

برای اینکه این عملیات بدون بازسازی صفحه انجام بشه از کنترل های Ajax خود دات نت استفاده کردم:
کد کل صفحه:

<%@ Page Language="C#‎" AutoEventWireup="true" CodeFile="Default2.aspx.cs" Inherits="Default2"   %>
<!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> 
    <script language="javascript" type="text/javascript">
                function FilterEnterNumber(e, maxValue)
                {
                    var keyCode = e.value.charCodeAt(e.value.length - 1);
                    if(keyCode < 48 || keyCode > 57)
                    {
                        e.value = e.value.substring(0, e.value.length - 1);
                        e.focus();
                        return false;
                    }
                    if(maxValue != null && maxValue != undefined)
                    {
                        if(parseInt(e.value) > maxValue)
                        {
                            e.value = maxValue;
                        }
                    }
                }
               </script>
</head>
<body>

 <form id="form1" runat="server">
    <div align="center">

<asp:ScriptManager ID="ScriptManager1" runat="server">
    </asp:ScriptManager>
   <asp:UpdateProgress ID="UpdateProgress1" runat="server">
        <ProgressTemplate>
        <asp:Label ID="Label9" runat="server" Text="چند لحظه صبر کنید"></asp:Label>
        </ProgressTemplate>
    </asp:UpdateProgress>
    <asp:UpdatePanel ID="UpdatePanel1" runat="server" RenderMode="Inline" UpdateMode="Always">
    <ContentTemplate>
       
            <asp:GridView ID="GridView1" runat="server" 
             AutoGenerateColumns="False" ondatabound="GridView1_DataBound" 
             BackColor="White" 
             BorderColor="#E7E7FF" BorderStyle="None" BorderWidth="1px" CellPadding="3" 
             GridLines="Horizontal" EmptyDataText="جدول خالی میباشد" Font-Bold="False" 
             Font-Names="Tahoma" Font-Size="Small" Width="70%" 
            >
            <AlternatingRowStyle BackColor="#F7F7F7" />
            <Columns>
                    <asp:BoundField DataField="display_name" HeaderText='نام شهر'  ItemStyle-Width="50px" >
                        <ItemStyle Width="50px" HorizontalAlign="Center" VerticalAlign="Middle"></ItemStyle>
                    </asp:BoundField>
                    <asp:BoundField DataField="id" HeaderText='شناسه' ItemStyle-Width="50px" >
                        <ItemStyle Width="50px">
                        </ItemStyle>
                    </asp:BoundField>
                    <asp:TemplateField HeaderText='ردیف' HeaderStyle-Width="40px">
                    <ItemTemplate>
                       <asp:Label  runat="server" ID='lbl' Width="25px" Height="25px" Text='<%# Eval("RowNum") %>'/>
                    </ItemTemplate>
                  <HeaderStyle Width="40px"></HeaderStyle>
                  </asp:TemplateField>
            </Columns> 
                <FooterStyle BackColor="#B5C7DE" ForeColor="#4A3C8C" />
                <HeaderStyle BackColor="#4A3C8C" Font-Bold="True" ForeColor="#F7F7F7" 
                    HorizontalAlign="Center" VerticalAlign="Middle" />
                <PagerStyle BackColor="#E7E7FF" ForeColor="#4A3C8C" HorizontalAlign="Right" />
                <RowStyle BackColor="#E7E7FF" ForeColor="#4A3C8C" HorizontalAlign="Center" 
                    VerticalAlign="Middle" />
                <SelectedRowStyle BackColor="#738A9C" Font-Bold="True" ForeColor="#F7F7F7" />
                <SortedAscendingCellStyle BackColor="#F4F4FD" />
                <SortedAscendingHeaderStyle BackColor="#5A4C9D" />
                <SortedDescendingCellStyle BackColor="#D8D8F0" />
                <SortedDescendingHeaderStyle BackColor="#3E3277" />
        </asp:GridView>
            
            <br />
            <asp:Table ID="Table1" runat="server" Font-Names="Tahoma" Font-Size="Small">
                <asp:TableRow ID="TableRow1" runat="server">
                    <asp:TableCell ID="TableCell1" runat="server"><asp:ImageButton ID="btnStart" runat="server" 
                ImageUrl="~/Images/1322728593_control_start_blue.png" 
                onclick="btnStart_Click" /></asp:TableCell>
                    <asp:TableCell ID="TableCell2" runat="server">
                        <asp:ImageButton ID="btnPrevious0" runat="server" 
                ImageUrl="~/Images/1322728647_Play1Pressed - Copy.png" 
                onclick="btnPrevious0_Click" /></asp:TableCell>
                    <asp:TableCell ID="TableCell3" runat="server"></asp:TableCell>
                    <asp:TableCell ID="TableCell4" runat="server"><asp:TextBox ID="txtPageNumber" runat="server" Text="1" ontextchanged="txtPageNumber_TextChanged" 
                Width="25" AutoPostBack="True" onkeyup="FilterEnterNumber(this,10000)"></asp:TextBox> </asp:TableCell>
                    <asp:TableCell ID="TableCell5" runat="server">
                       <asp:ImageButton ID="btnNext" runat="server" 
                ImageUrl="~/Images/1322728647_Play1Pressed.png" onclick="btnNext_Click" />
                       </asp:TableCell>
                    <asp:TableCell ID="TableCell6" runat="server"><asp:ImageButton ID="btnEnd" runat="server" 
                ImageUrl="~/Images/1322728537_control_end_blue.png" onclick="btnEnd_Click" /></asp:TableCell>
                </asp:TableRow>
            </asp:Table>
            <asp:Table ID="Table2" runat="server" Font-Names="Tahoma" Font-Size="Small">
                <asp:TableRow ID="TableRow2" runat="server">
                <asp:TableCell ID="TableCell7" runat="server">رکورد</asp:TableCell>
                <asp:TableCell ID="TableCell8" runat="server">
                    <asp:Label ID="Label8" runat="server" Text="Label" BackColor="BlanchedAlmond"></asp:Label></asp:TableCell>
                <asp:TableCell ID="TableCell9" runat="server">از</asp:TableCell>
                <asp:TableCell ID="TableCell10" runat="server">
                    <asp:Label ID="Label7" runat="server" Text="Label" BackColor="BlanchedAlmond"></asp:Label></asp:TableCell>
                    <asp:TableCell ID="TableCell11" runat="server">تا</asp:TableCell>
                    <asp:TableCell ID="TableCell12" runat="server">
                        <asp:Label ID="Label6" runat="server" Text="Label" BackColor="BlanchedAlmond"></asp:Label></asp:TableCell>
                    <asp:TableCell ID="TableCell13" runat="server">پیمایش رکودهای</asp:TableCell>
                    <asp:TableCell ID="TableCell14" runat="server">-------</asp:TableCell>
                    <asp:TableCell ID="TableCell15" runat="server">
                        <asp:Label ID="Label5" runat="server" Text="Label" BackColor="BlanchedAlmond"></asp:Label></asp:TableCell>
                    <asp:TableCell ID="TableCell16" runat="server">از</asp:TableCell>
                    <asp:TableCell ID="TableCell17" runat="server">
                        <asp:Label ID="Label4" runat="server" Text="Label" BackColor="BlanchedAlmond"></asp:Label></asp:TableCell>
                    <asp:TableCell ID="TableCell18" runat="server">نمایش صفحه</asp:TableCell>
                </asp:TableRow>
            </asp:Table>
            <br />
            <br />
        <asp:Label ID="Label1" runat="server" Text="Label" Visible="False"></asp:Label>
        <br />
        <asp:Label ID="Label2" runat="server" Text="Label" Visible="False"></asp:Label>
        <br />
        <asp:Label ID="Label3" runat="server" Text="Label" Visible="False"></asp:Label>
    
    </ContentTemplate>
    </asp:UpdatePanel>
 </div>
    </form>  
</body>
</html>

----------


## alonemm

کلام آخر:
پیاده سازی پروژه به پایان رسید.
امیدوارم از این مقاله بهره ببرید و سوالات در این بحث هم به پایان برسه.
از این روش در 2 پروژه برای شهرداری و سپاه پاسداران انقلاب اسلامی استفاده کردم و به طور کامل تست شده و از نظر سرعت کاملا عالی کار میکنه.

منتظر بقیه مقالات باشید.

روش های بهینه سازی و بالا رفتن سرعت لود صفحه :
https://barnamenevis.org/showthread.p...B1-UpdatePanel


از کدنویسی لذت ببرید.

MaidMaghsoudipour-AloneMM

----------


## alonemm

باسلام:
با درخواست چندنفر از دوستان فایل پروژه رو در پست شماره 1 ضمیمه کردم.


موفق باشید.

----------


## fakhravari

با سلام خدمت alon  :بوس: 
چنتا نکنه که بتونی داینامیکتر کنی این قسمت.
    string ConnectionString = DAL.ConnectionString;

    public DataTable ExecuteDataset(string SQLTableName, int PageIndex, int PageSize, string Sort,string asc_dsc)
    {
       SqlConnection con = new SqlConnection(ConnectionString);
       SqlCommand cmd = new SqlCommand("SELECT * FROM (SELECT * , ROW_NUMBER() OVER(ORDER BY " + Sort + ") as RowNum FROM " + SQLTableName + ") as DerivedTableName WHERE RowNum BETWEEN (" + PageIndex + ")  AND  ((" + PageIndex + " + " + PageSize + ") - 1) Order by " + Sort + " " + asc_dsc + " ", con);
       cmd.CommandType = CommandType.Text;
.
.
.
    }
برای قسمت جمع تداد رکور ها هم بهتر از COUNT(*) استفاده کنی.

    private void DataBindGrid()
    {
        GridView1.DataSource = pg.ExecuteDataset(SQLTableName, PageIndex, PageSize,"TopicID","Desc");
        GridView1.DataBind();
    }
سمپل کار 
http://fakhravary.somee.com/test/Default3.aspx

----------


## fa_karoon

دستتون درد نکنه،مثل اینک سایتی که آپلود کردین فیلتره

----------


## fakhravari

نه فیلتر نیست.http://fakhravary.somee.com/test/Default3.aspx

----------


## moferferi

اینم نگاه کنید بد نیست
http://www.trirand.net/demoaspnet.aspx

البته بهتره همیشه دیتا را به صورت خام و سریالایز شده (روش جی سون)سمت کلاینت بفرستیم.و توسط تابع eval خودمون یه گرید طراحی کنیم.اینجوری سرعت لود و بارگزاری فوق العاده سریعتر میشه.

----------


## fakhravari

با سلام
این چیه؟
jqSuite Trial Downloads (30-day trial) 
همین که دیدم پشیمون شدم .
ایا دائمی ؟
سمپلی ندارید؟

----------


## mahmood_4246

اینا هم بد نبستن برای صفحه بندی مخصوصا لینک اول که میشه Ajax کردش
http://www.dotnetcurry.com/ShowArticle.aspx?ID=345
http://www.dotnetfunda.com/articles/...t-control.aspx

این یکی کنترلش کرده
http://www.codeproject.com/Articles/...or-an-Enumerab

----------


## abbas3zaar

لینک پست اول خرابه. لطفا چک کنید

----------


## alonemm

> با سلام خدمت alon 
> چنتا نکنه که بتونی داینامیکتر کنی این قسمت.
>     string ConnectionString = DAL.ConnectionString;
> 
>     public DataTable ExecuteDataset(string SQLTableName, int PageIndex, int PageSize, string Sort,string asc_dsc)
>     {
>        SqlConnection con = new SqlConnection(ConnectionString);
>        SqlCommand cmd = new SqlCommand("SELECT * FROM (SELECT * , ROW_NUMBER() OVER(ORDER BY " + Sort + ") as RowNum FROM " + SQLTableName + ") as DerivedTableName WHERE RowNum BETWEEN (" + PageIndex + ")  AND  ((" + PageIndex + " + " + PageSize + ") - 1) Order by " + Sort + " " + asc_dsc + " ", con);
>        cmd.CommandType = CommandType.Text;
> ...


سلام دوست عزیز:

1-بهتره از کاراکتر * در کوئری ها استفاده نشه و سرعت نام فیلد از * خیلی بالاتر هست چون کاراکتر * با نام فیلد طی یک پروسه قبل از اجرا جای گزاری میشه.
2-بهتره از ُ SP استفاده بشه هم از نظر سرعت و هم از نظر امنیت.
3-بهتره از پارامتر ها استفاده کنید تا اینکه خود متغییر رو در کوئری جای گزاری کنید امنیت برابر 0 میشه اینجوری..!


موفق باشید.

----------


## farnooshhp

آیا برای صفحه بندی دیتالیست هم روش خوبی سراغ دارید؟

----------


## mahmood_4246

> آیا برای صفحه بندی دیتالیست هم روش خوبی سراغ دارید؟


 لینکایی که بالا گذاشتم کارت رو راه میندازه

----------


## alonemm

> آیا برای صفحه بندی دیتالیست هم روش خوبی سراغ دارید؟


شما میتونید کنترل ها رو به این روش DataSource بدید و عملیات Paging رو پیاده سازی کنید.

----------


## alonemm

باسلام:

در راستای بهینه سازی در سرعت لود و بالا رفتن راندمان صفحه  به لینک زیر برید و حتما نکات زیر رو هم در مورد کنترل های صفحتون پیاده سازی کنید:
https://barnamenevis.org/showthread.p...B1-UpdatePanel


موفق باشید.

----------


## Fartaj

سلام خدمت دوستان 

می خواستم بپرسم تو این روش صفحه بندی اگه بخوایم یک query هم بررسی کنیم باید کجاش اضافه کنیم من هر چی دستکاریش کردم نشد می خوام gridview براساس موضوع کتاب انتخاب شده بیاد ، تو sp باید کجاش این پارامتر موضوع رو بگیره و تو اون دستور select تو sp بعد where باید کجاش این رو بررسی کنم ؟؟

ممنون می شم اگه راهنماییم کنید

----------


## fakhravari

نمونه
http://fakhravary.somee.com/Like_Top...A7%D9%85%D9%87
توی ورژن 2 هست
*https://barnamenevis.org/showthread.php?319398*

----------


## alonemm

> سلام خدمت دوستان 
> 
> می خواستم بپرسم تو این روش صفحه بندی اگه بخوایم یک query هم بررسی کنیم باید کجاش اضافه کنیم من هر چی دستکاریش کردم نشد می خوام gridview براساس موضوع کتاب انتخاب شده بیاد ، تو sp باید کجاش این پارامتر موضوع رو بگیره و تو اون دستور select تو sp بعد where باید کجاش این رو بررسی کنم ؟؟
> 
> ممنون می شم اگه راهنماییم کنید


باسلام:

به شکل زیر عمل کنید در SP:

ROW_NUMBER() OVER(ORDER BY "+ Sort +" ASC)

----------


## Fartaj

> باسلام:
> 
> به شکل زیر عمل کنید در SP:
> 
> ROW_NUMBER() OVER(ORDER BY "+ Sort +" ASC)


ممنون از پاسختون اما این کدی که شما گفتید فکر می کنم نحوه چیدمان و مرتب سازی رکوردها رو تعیین می کنه
اما من می خوام با querystring بعد از انتخاب موضوع کتاب توسط کاربر گریدویو برپایه همون موضوع نمایش داده بشه و صفحه بندی بشه :
من sp رو به اینصورت نوشتم :

USE [DIGlibrary]
GO
/****** Object:  StoredProcedure [dbo].[BookCastumPaging]    Script Date: 07/10/2012 10:37:01 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
 
ALTER PROCEDURE  [dbo].[BookCastumPaging]
(
   @SqlTableName nvarchar(100),
   @PageIndex int,
   @title nvarchar(200),
   @PageSize int
)
AS
BEGIN
declare @SQLText nvarchar(500)
--set@SqlTableName = 'book'
--set@PageIndex = 0
--set@PageSize = 10
--set@title = title
set @SQLText = 'SELECT * FROM (SELECT * , ROW_NUMBER() OVER(ORDER BY title) as RowNum FROM '+@SqlTableName+'  ) as DerivedTableName WHERE  RowNum BETWEEN '+ str(@PageIndex)+' AND'+ (@title)+' AND'+ str((@PageIndex+ @PageSize) - 1)  
exec(@SQLText)
END


مشکل داره باید بعد شرطتون بگم به شرطی نمایش بده که title با title انتخاب شده یکی باشه اما با روش شما نمی دونم باید چجوری پارامتر موضوع رو بررسی کنم ممنون می شم اگه اصلاحش کنید و اگه امکان داره یک توضیح بدید

----------


## alonemm

> ممنون از پاسختون اما این کدی که شما گفتید فکر می کنم نحوه چیدمان و مرتب سازی رکوردها رو تعیین می کنه
> اما من می خوام با querystring بعد از انتخاب موضوع کتاب توسط کاربر گریدویو برپایه همون موضوع نمایش داده بشه و صفحه بندی بشه :
> من sp رو به اینصورت نوشتم :
> 
> USE [DIGlibrary]
> GO
> /****** Object:  StoredProcedure [dbo].[BookCastumPaging]    Script Date: 07/10/2012 10:37:01 ******/
> SET ANSI_NULLS ON
> GO
> ...


درود:

دوست عزیز کوئری رو به شکل زیر تغییر بدید:

set @SQLText = 'SELECT * FROM (SELECT * , ROW_NUMBER() OVER(ORDER BY title) as RowNum FROM '+@SqlTableName+' where title = @title ) as DerivedTableName WHERE  RowNum BETWEEN '+ str(@PageIndex)+' ' AND'+ str((@PageIndex+ @PageSize) - 1)  



موفق باشید.

----------


## Fartaj

من این کار رو کردم اما این ارور رو می ده :



> Must declare the scalar variable "@title"


ممنون می شم اگه کلا کدهام رو یک نگاه بندازی :

sp :

USE [DIGlibrary]
GO
/****** Object:  StoredProcedure [dbo].[BookCastumPaging]    Script Date: 07/14/2012 18:34:53 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
 
ALTER PROCEDURE  [dbo].[BookCastumPaging]
(
   @SqlTableName nvarchar(100),
   @PageIndex int,
   @title nvarchar(200),
   @PageSize int
)
AS
BEGIN
declare @SQLText nvarchar(500)
 
--set@SqlTableName = 'book'
--set@PageIndex = 0
--set@PageSize = 10



set @SQLText = 'SELECT * FROM (SELECT * , ROW_NUMBER() OVER(ORDER BY bookid) as RowNum FROM '+@SqlTableName+' WHERE title = @title ) as DerivedTableName WHERE  RowNum BETWEEN '+ str(@PageIndex)+' AND'+ str((@PageIndex+ @PageSize) - 1)  
exec(@SQLText)
END



paging.cs :

public class paging
{
    public paging()
    {

    }

    public string ConnectionString
    {
        get
        {
            return ConfigurationManager.ConnectionStrings["constr"].ToString();
        }
    }

    public DataSet ExecuteDataset(string title,string SQLTableName, int PageIndex, int PageSize)
    {
        using (SqlConnection con = new SqlConnection(ConnectionString))
        {
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = con;
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.CommandText = "[BookCastumPaging]";
            cmd.Parameters.AddWithValue("@SqlTableName", SQLTableName);
            cmd.Parameters.AddWithValue("@title", title);
            cmd.Parameters.AddWithValue("@PageIndex", PageIndex);
            cmd.Parameters.AddWithValue("@PageSize", PageSize);
            DataSet ds = new DataSet();
            SqlDataAdapter da = new SqlDataAdapter(cmd);
            con.Open();
            da.Fill(ds);
            con.Close();
            return ds;
        }
    }

    public int countall(string SQLTableName, string title)
    {
        using (SqlConnection con = new SqlConnection(ConnectionString))
        {
            con.Open();
            string commandText55 = "select  count(bookid)as mm from " + SQLTableName + " where title = @title ";
            SqlCommand cmdObj55 = new SqlCommand(commandText55, con);
            SqlDataReader ddr = cmdObj55.ExecuteReader();
            ddr.Read();
            int code22;
            if (ddr.HasRows == true)
            {
                code22 = int.Parse(ddr["mm"].ToString());
                con.Close();
                return code22;
            }
            else
                con.Close();
            return 0;
        }
    }
}


تو صفحه book.aspx جایی که گریدویو قراره بیاد :

        #region Property
        protected int PageIndex
        {
            get
            {
                object value = this.ViewState["PageIndex"];
                if (value != null)
                    return System.Convert.ToInt32(value);
                else
                    return 1;
            }
            set
            {
                this.ViewState["PageIndex"] = value;
            }
        }

        protected int PageCount
        {
            get
            {
                object value = this.ViewState["PageCount"];
                if (value != null)
                    return System.Convert.ToInt32(value);
                else
                    return 1;
            }
            set
            {
                this.ViewState["PageCount"] = value;
            }
        }

        protected int PageSize
        {
            get
            {
                object value = this.ViewState["PageSize"];
                if (value != null)
                    return System.Convert.ToInt32(value);
                else
                    return 1;
            }
            set
            {
                this.ViewState["PageSize"] = value;
            }
        }

        public string SQLTableName
        {
            get
            {
                object value = this.ViewState["SQLTableName"];
                if (value != null)
                    return value.ToString();
                else
                    return null;
            }
            set
            {
                this.ViewState["SQLTableName"] = value;
            }
        }

        public string title
        {
            get
            {
                object value = this.ViewState["title"];
                if (value != null)
                    return value.ToString();
                else
                    return null;
            }
            set
            {
                this.ViewState["title"] = value;
            }
        }
        #endregion


        public void DataBindGrid()
        {
                GridView1.DataSource = ADO.ExecuteDataset(title,SQLTableName, PageIndex, PageSize);
                GridView1.DataBind();
 
        }



        protected void Page_Load(object sender, EventArgs e)
        {
            if (Request.QueryString["title"] != null)
            {
               
                if (!IsPostBack)
                {
                    SQLTableName = "[book]";
                    title = Request.QueryString["title"];
                    PageSize = 10;
                    PageIndex = 1;
                    PageCount = Convert.ToInt32(Math.Ceiling((double)ADO.countall(  SQLTableName, title) / (double)PageSize));
                    DataBindGrid();
                }
            }

        }

----------


## fakhravari

با سلام
توی نمونه پروژه که گذاشتم اینو پیاده سازی کردم.
دانلود کنید و مقایسه کنید.
31

----------


## azam2005

با سلام 
من از این روش استفاده کردم ولی قصد دارم یک صفحه بندی مانند GridView  معمولی داشته باشم که شماره بخوره و حتما می خواهم LinkButton باشد در  PagerTemplate گرید ویو یک PlaceHolder قراردادم و در کد برای صفحه بندی  LinkButton ایجاد کردم و درPlaceHolder اضافه کردم

<PagerTemplate>
                        <asp:PlaceHolder runat="server" ID="PlhGVPager"></asp:PlaceHolder>
           </PagerTemplate>


*Dim PagerRow As GridViewRow = GVForum.BottomPagerRow
                Dim PlhGVPager As PlaceHolder
                PagerRow.Visible = True
                For i = 1 To _ClsForum.Count(_StrFilter)
                    Dim LB As New LinkButton
                    LB.ID = "Page" + i.ToString
                    LB.CausesValidation = False
                    LB.Text = i.ToString
                    LB.Width = Unit.Pixel(20)

                    'LB.OnClientClick = "GVForum_PageIndexChanging"
                    LB.CausesValidation = False
 LB.CommandArgument = i.ToString
 LB.CommandName = "Page"
                         PlhGVPager = CType(PagerRow.FindControl("PlhGVPager"), PlaceHolder)
                    PlhGVPager.Controls.Add(LB)
                Next*


مشکلی که به وجود می آید این است که 
در صفحه بندی معمولی LinkButton ها تبدیل به تگ زیر  میشود 
<a *href**="**javascript:__doPostBack('ctl08$GVCompany','Page$2'  )*">2</a>و در CustomePage  
LinkButton ها تبدیل به تگ زیر  میشود
<a id="ctl08_GVForum_ctl20_Page1" *href**="javascript:__doPostBack('ctl08$GVForum$ctl20$Pag  e1','')*" style="display: inline-block; width: 20px;">چرا با وجود دادن در کد  *CommandName و* *CommandArgument* در CustomePage اعمال نمی شود

----------


## azam2005

کسی نمی دونه این مشکل چرا به وجود می آید؟؟؟؟؟؟؟

----------


## hrs.1989

لینک دانلود در پست 1 خرابه میشه دوباره upload کنید

----------


## mahtab kf

> باسلام:
> با درخواست چندنفر از دوستان فایل پروژه رو در پست شماره 1 ضمیمه کردم.
> 
> 
> موفق باشید.


لینک تون کار نمی کنه ممنون میشم رسیدگی کنید

----------


## mahtab kf

> من این کار رو کردم اما این ارور رو می ده :
> Must declare the scalar variable "@title"
> ممنون می شم اگه کلا کدهام رو یک نگاه بندازی :


منم دقیقاً مشکل شما رو دارم :ناراحت: 
دوستان کسی نمی تونه کمک کنه؟

----------


## mahtab kf

> من این کار رو کردم اما این ارور رو می ده :
>  	 		 			 			 				Must declare the scalar variable "@title" 			 		
> 
> 
>  ممنون می شم اگه کلا کدهام رو یک نگاه بندازی :


دوست عزیز من تونستم مشکلمو حل کنم دقت کنید همه جا SqlTableName رو دقیقاً به یک صورت تعریف کنید یعنی به حروف کوچک و بزرگ حساس است ولی بعدش به مقدار title  گیر میده خطای زیر



> Invalid column title 'Cpu'


اگه حلش کردید به منم بگید.

----------


## alonemm

> دوست عزیز من تونستم مشکلمو حل کنم دقت کنید همه جا SqlTableName رو دقیقاً به یک صورت تعریف کنید یعنی به حروف کوچک و بزرگ حساس است ولی بعدش به مقدار title  گیر میده خطای زیر
> 
> اگه حلش کردید به منم بگید.


باسلام:

لطفا کل کدتو رو بزارید تا برسی کنم.
این خطایی هم که داره میده میگه ستونی به نام CPU وجود نداره. شما باید در قسمت شرط WHERE مقدار بدید.

----------


## saeed31641

من کد دوست  عزیزمون که فرستاده بود (*alonemm* 	    				) استفاده کردم به چند تا مشکل برخوردم که میگم شادی بر طرف بشه.
۱- زمانی که شما میخای  در داخل گرید  جستجو کنی بعد نتایج جستجو بوسیله گرید نمایش داده بشه.شما فرض کنیم تو بانک 1000 رکورد داریم رکوردی کهجستجو کرده رکورد 500 در بانک تو صفحه 5 گرید نمایش میده  
نتایج جستجو رو میاد تو صفحه ۵ نمایش میده یعنی باید ۵ صفحه بری جلو تا نتیجه رو ببینی .خودش نمیاد نتایج تو همون صفحه اول نمایش بده.این مشکل بخاطر کویری که نوشته چند تا چند تا دنبال بگرد هست.
۲- من داخل گرید یه دکمه حذف گذاشتم که وقتی عملیلت حذف انجام شد یه پیغام بصورت اژاکسی نمایش بده چون خود گرید  آژاکس هست زمان حذف  مشکل برخورد میکنه پیام قاطی میشه یعنی هم پیام با منوفق حذف شد رو نشون میده بو هم پیام حذف ناموفق که خود طراحی کردم رو نشون میده.

----------


## mostafa.hnz

سلام
فایل پروژه حذف شده اگه می تونید یه بار دیگه upload کنید
با تشکر

----------


## zhr.rezae66i

من تمام مراحلو مو به مو رفتم اما error میده که stor procedure  به این نام پیدا نمیکنم
درحالیکه تو لیست نشون میدتش

چرا آخه

----------


## alonemm

> من تمام مراحلو مو به مو رفتم اما error میده که stor procedure  به این نام پیدا نمیکنم
> درحالیکه تو لیست نشون میدتش
> 
> چرا آخه


باسلام:

لطفا کدتون رو قرار بدید تا بهتر راهنمایی کنم.

----------


## H.Zeinali

سلام
فایل پروژه حذف شده اگه می تونید یه بار دیگه upload کنید
با تشکر

----------


## powerdangerouseb

با درود به دوستان 

بخشید می شود یکی از دوستان لینک دانلود پروژه رو بگذارد لینک اولی خرابه ؟؟

من از روی کد هایی که بود تلاش ردم درست کنم و همش با پیروز پیش رفت فقط یک جاس به ایراد می خورد 
اگر ممکن است کسی کمکم کنه 
بسیار سپاسگذار می شوم 

اینم لینک پروژه ی خودمه که به مشکل بر خورد 

دانلود پروژه

پروژه web Application است نه web site 
اگر کسی بی زحمت بفرماید که ایراد این پر.ژه کجاست بسیار ممنون می شم 

سپاس از همگی

----------


## alonemm

> با درود به دوستان 
> 
> بخشید می شود یکی از دوستان لینک دانلود پروژه رو بگذارد لینک اولی خرابه ؟؟
> 
> من از روی کد هایی که بود تلاش ردم درست کنم و همش با پیروز پیش رفت فقط یک جاس به ایراد می خورد 
> اگر ممکن است کسی کمکم کنه 
> بسیار سپاسگذار می شوم 
> 
> اینم لینک پروژه ی خودمه که به مشکل بر خورد 
> ...


دوست من شما کجا به مشکل خوردید؟

----------


## elyas_delshadnbe

دستشون درد نکنه که لینک مدیا فایرو فیلتر کردن

----------

