株式会社ロジステック株式会社ロジステック

By logistech

ASP.NET DataGridのページングのカスタマイズ

●目的
DataGridは、デフォルトでページング機能を持っている。
しかし、これは、モードが、「[次へ]、[戻る]ページボタン」か、「ページ番号」のどちらかしか持っていない。
ここでは、ページ番号と[次へ]、[戻る]ボタンの両方を設置する方法を説明する。
————— こんな感じにしたい —————
                      <前へ 1 2 3 4 5 次へ>

●方法
(1) VisualStudioのデザイナーで通常の方法でページング機能を追加。
   モードは「ページ番号」にしておく。
   HTMLコードでは次のようになる。

   <PagerStyle Font-Size="Small" HorizontalAlign="Center" Mode="NumericPages"></PagerStyle>

(2) VisualStudioのコード編集で以下のとおりプログラムを追加する。

    Private Sub DataGrid1_ItemCreated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles DataGrid1.ItemCreated
        If (e.Item.ItemType = ListItemType.Pager) Then
            Dim pager As TableCell = e.Item.Cells(0)

            Dim btnBeforetPage As LinkButton = New LinkButton
            AddHandler btnBeforetPage.Click, AddressOf BeforetPageOnCLick
            btnBeforetPage.Text = "<前へ"
            pager.Controls.AddAt(0, btnBeforetPage)

            '体裁を整えるためスペースを空ける
            Dim lit1 As Literal = New Literal
            lit1.Text = "  "
            pager.Controls.AddAt(1, lit1)

            '体裁を整えるためスペースを空ける
            Dim numControls As Integer = pager.Controls.Count
            Dim lit2 As Literal = New Literal
            lit2.Text = "  "
            pager.Controls.AddAt(numControls, lit2)

            numControls = pager.Controls.Count
            Dim btnNextPage As LinkButton = New LinkButton
            AddHandler btnNextPage.Click, AddressOf NextPageOnCLick
            btnNextPage.Text = "次へ>"
            pager.Controls.AddAt(numControls, btnNextPage)
        End If
    End Sub

    Private Sub BeforetPageOnCLick(ByVal sender As Object, ByVal e As System.EventArgs)
        If (DataGrid1.CurrentPageIndex > 0) Then  '最初のページ以上戻らないように
            DataGrid1.CurrentPageIndex = DataGrid1.CurrentPageIndex - 1
            DataGrid1Bind() 'データバインド(適宜ご対応ください)
        End If
    End Sub

    Private Sub NextPageOnCLick(ByVal sender As Object, ByVal e As System.EventArgs)
        If (DataGrid1.CurrentPageIndex < DataGrid1.PageCount - 1) Then  '最後のページ以上進まないように
            DataGrid1.CurrentPageIndex = DataGrid1.CurrentPageIndex + 1
            DataGrid1Bind() 'データバインド(適宜ご対応ください)
        End If
    End Sub

●補足
「デリゲートとイベントを使ったコールバックと通知」
http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/dnguinet/htm/drguinet05292001.asp
によると、コントロールのイベントハンドラの結び付けは、VB.NETの場合はVB.NETの作法に従うべきとある。(下記参照)

    Public Sub New()
        myTimer = New Timer()
        ' we could omit WithEvents from myTimer's declaration and
        ' use the below line instead:
        '     AddHandler myTimer.Tick, AddressOf myTimer_Tick
        ' but since we have WithEvents, all we have to do is
        ' use the Handles clause when we declare the event-handling method
    End Sub

これに従うならば、
(1) [次へ]のボタンコントロールをクラスの変数としてWithEvents付で宣言する。
     Protected WithEvents btnNextPage As LinkButton = New LinkButton
(2)これによって、コードエディタの上部のドロップダウンリストにbtnNextPageがリストアップされる。
(3)上記ドロップダウンリストでbtnNextPageを選択し、右の窓でclickイベントハンドラーを選択する。
(4)イベントハンドラー関数を以下のとおり記述する。

    Private Sub btnNextPage_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnNextPage.Click
        If (DataGrid1.CurrentPageIndex < DataGrid1.PageCount - 1) Then
            DataGrid1.CurrentPageIndex = DataGrid1.CurrentPageIndex + 1
            DataGrid1Bind() 'データバインド(適宜ご対応ください)
        End If
    End Sub

とすることで同様の機能が実現可能になるが.....
しかし、なぜか(まだ原因を追究していないが)ページングボタンをグリッドの上下に配置するとうまく動作しない。

●蛇足
ページャコントロール部がDataGridの枠線内に囲まれていていや(格好悪い)という方のために

    Sub Page_Load()内で(Page_Load以外のどこでも適当な場所でよいが)
        DataGrid1.BorderStyle = BorderStyle.None    'データグリッドの外枠を消す
    
    Sub DataGrid1_ItemCreated内で
        Dim pager As TableCell = e.Item.Cells(0)
        pager.BorderStyle = BorderStyle.None        'ページャーコントロール部の外枠を消す

とすればよい。

参考資料:
http://www.atmarkit.co.jp/fdotnet/dotnettips/072modpager/modpager.html

logistech
About logistech