سلام
اتفاقا مشکل دقیقا مربوط به همین قسمت هست و هیچ ربطی به جاهای دیگه ندارم
اتفاقا مشکل اصلا به این قسمت ارتباطی نداره. (اصلا مشکلی نیست. بیشتر برداشت اشتباه شماس)
قضیه اینه که وقتی ما index رو با کد e.commandargument می گیریم این index در واقع واسه کنترل grid نیست و برای datasource هستش
همیشه اینطوری نیست. به خاطر همین گفتم برداشت اشتباه

اول تو event : page index changing این دستور رو می نویسیم:
protected void GridView1_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
GridView1.PageIndex = e.NewPageIndex;
}

با این کد به گرید می فهمونیم که از این به بعد هرجی index بهت دادیم رو تو صفحه جدید محاسبه کن
هر وقت خواستید گرید رو صفحه بندی کنید این تیکه کد رو باید بنویسید (شماره صفحه رو برای گرید مشخص میکنه) و این اصلا ارتباطی به موضوع نداره
بعدش زمانی که می خوایم index رو بهشت بدیم یه شرط می زاریم که اگه index بزرگتر از paging ما بود اونو از paging کم کنه تا ایندکس صفحه جدید بدست بیاد.
نکنی این کارو یه وقت. چه کاریه آخه. کد پایین رو ببین
کد HTML:
        <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" OnRowCommand="GridView1_RowCommand" AllowPaging="True" PageSize="4" OnPageIndexChanging="GridView1_PageIndexChanging" DataKeyNames="Id" DataSourceID="SqlDataSource1" EnableModelValidation="True">
            <Columns>
                <asp:ButtonField CommandName ="deleteCommand" HeaderText="حذف" ButtonType="Button" Text="حذف" />
                <asp:TemplateField HeaderText="حذف">
                    <ItemTemplate>
                        <asp:Button ID="Button1" runat="server" Text='<%# ((GridViewRow)Container).RowIndex + " :اندیس سطر در گرید" %>' CommandName="deleteCommand" CommandArgument="<%# ((GridViewRow)Container).RowIndex %>" />
                        <asp:Button ID="Button2" runat="server" Text='<%# Container.DataItemIndex + " :اندیس رکورد در دیتاسورس" %>' CommandName="deleteCommand" CommandArgument="<%# Container.DataItemIndex %>" />
                    </ItemTemplate>
                </asp:TemplateField>
            </Columns>
        </asp:GridView>
دکمه ای که توسط asp:ButtonField تو گرید قرار میگیره، به صورت خودکار شماره سطر گرید رو تو e.CommandArgument قرار میده
دکمه اول تو ItemTemplate باز هم شماره سطر گرید رو تو e.CommandArgument قرار میده و فقط تو
دکمه دوم تو ItemTemplate هستش که مقدار e.CommandArgument میشه شماره رکورد تو دیتا سورس. این هم به خاطر این هستش که شما همه رکوردها رو دارید واکشی میکنید. اگه فقط رکوردهای
Page جاری رو از دیتابیس واکشی کنید، اونوقت Container.DataItemIndex هم تو همه صفحات از 0 شروع میشه (که معادل همون شماره سطر گرید خواهد بود)

موفق باشید