Udostępnij za pośrednictwem


Dynamic Datagrid Series - 4.Multiselect Datagrid behaving like most other Mail Service's Datagrid

Requirement 4
=============
This is the 4th requirement of the Dynamic Datagrid Series at my blog. For previous Requirements, click here. Till now, we have a datagrid which is dynamically created with nicely formatted columns and rows which changes color whenever the mouse is hovered over any row!

We need 3 more things now...

1) Add Checkboxes in the first column of our datagrid
2) Whenever we check on the "Header" Checkbox all checkboxes in the other rows should get checked and vice versa.
3) There should be a way to list out all the checked rows so that we could do the *processing* on them at one shot.
4) For robustness, we want postback to happen only on the Header Checkbox.

In a nutshell, it should behave as a Yahoo Mail's or most other mail datagrids behave. Here is what the output looks like...

Let's create a new ASP.NET Web Application under Visual Basic Projects called DataGridDemo4.
Add the following lines just after your <configuration> tag in the web.config. I will be working with the "pubs" database all the time. Better to have it in the web.config.

 <appSettings>
<add key="ConnectionInfo" value="server=(local);database=Pubs;user id=sa;password="/>
</appSettings>

1) Create a new Page called "MultiSelectGrid.aspx"
2) Drag and drop a PlaceHolder control and change the ID to "PlaceHolder". Go to the code behind of this page and delete everything. Now paste the following...

Imports System.Data
Imports System.Data.SqlClient
Imports System.Text
'
Public Class CheckBoxTemplate
Implements ITemplate
'
Private i As Integer
Private chkBox As CheckBox
Private strID As String
Private strText As String
Private blnChecked As Boolean
Private blnAutoPostBack As Boolean
'
Sub New(ByVal ID As String, _
ByVal Text As String, _
ByVal Checked As Boolean, _
ByVal AutoPostBack As Boolean _
)
'
strID = ID
strText = Text
blnChecked = Checked
blnAutoPostBack = AutoPostBack
End Sub
'
Public Sub InstantiateIn( _
ByVal container As System.Web.UI.Control _
) Implements System.Web.UI.ITemplate.InstantiateIn
'
chkBox = New CheckBox()
chkBox.ID = strID + i.ToString
chkBox.Text = strText
chkBox.Checked = blnChecked
chkBox.AutoPostBack = blnAutoPostBack
'The following AddHandler is just to ensure that the Checked Changed is not fired
'for all the checkbox controls. If that happens, you will get weird out. Try
'commenting the following If and End If and you will come to know ;o)
If strID = "Header" Then
AddHandler chkBox.CheckedChanged, AddressOf chkCheckBox_CheckedChanged
End If
i += 1
container.Controls.Add(chkBox)
End Sub
'
Private Sub chkCheckBox_CheckedChanged( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs _
)
Dim chkBox As CheckBox
Dim dgiItem As DataGridItem
Dim dgGrid As DataGrid
Dim blnIsHeaderChecked As Boolean
chkBox = CType(sender, CheckBox)
blnIsHeaderChecked = chkBox.Checked
dgiItem = chkBox.NamingContainer()
dgGrid = dgiItem.NamingContainer()
For Each dgiItem In dgGrid.Items
chkBox = CType(dgiItem.Cells(0).Controls(0), CheckBox)
chkBox.Checked = blnIsHeaderChecked
Next
End Sub
End Class
'
Public Class MultiSelectGrid
Inherits System.Web.UI.Page
'
#Region " Web Form Designer Generated Code "
'
'This call is required by the Web Form Designer.
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
    End Sub
'
Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
'CODEGEN: This method call is required by the Web Form Designer
'Do not modify it using the code editor.
InitializeComponent()
End Sub
#End Region
'
Protected WithEvents PlaceHolder As System.Web.UI.WebControls.PlaceHolder
Dim dg As New DataGrid()
Dim btnShowChecked As New Button()
Dim strConn As String = ConfigurationSettings.AppSettings("ConnectionInfo")
Dim strCommand As String = "select top 10 au_id as Author_ID, au_lname as " & _
"Last_Name, au_fname as First_Name, phone as Phone_Number, state as State " & _
"from authors"
'
Private Sub Page_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs _
) Handles MyBase.Load
'
'Put user code to initialize the page here
Dim tblData As DataTable
tblData = GetData(strCommand, strConn)
dg.DataSource = tblData
dg.ID = "DataGrid1"
dg.AutoGenerateColumns = False
AddHandler dg.ItemCreated, AddressOf DataGrid_ItemCreated
AddCheckBoxColumn()
FormatColumns(tblData)
dg.DataBind()
PlaceHolder.Controls.Add(dg)
FormatDataGrid()
btnShowChecked.Text = "Show Checked"
AddHandler btnShowChecked.Click, AddressOf btnShowChecked_Click
PlaceHolder.Controls.Add(btnShowChecked)
End Sub
'
Private Sub AddCheckBoxColumn()
'
Dim chkColumn As New TemplateColumn()
'
chkColumn.HeaderTemplate = New CheckBoxTemplate("Header", "", False, True)
chkColumn.ItemTemplate = New CheckBoxTemplate("Item", "", False, False)
chkColumn.HeaderStyle.Width = New Unit(5)
chkColumn.ItemStyle.Width = New Unit(5)
dg.Columns.Add(chkColumn)
End Sub
'
Protected Sub DataGrid_ItemCreated( _
ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs _
)
'
'Since we are using alternate colors and won't like to miss out on the colors,
'we need to add the attributes such that it reverts back whatever color was used before.
Dim Remainder As Integer
Remainder = e.Item.ItemIndex Mod 2
Select Case Remainder
Case -1 'It is a header
Case 0 'Item
e.Item.Attributes.Add("OnMouseOver", "this.style.backgroundColor = 'beige';")
e.Item.Attributes.Add("OnDblClick", "alert('" & e.Item.Cells(0).Controls(0).ID & "');")
e.Item.Attributes.Add("OnMouseOut", "this.style.backgroundColor = 'cyan';")
Case 1 'Alternate Item
e.Item.Attributes.Add("OnMouseOver", "this.style.backgroundColor = 'beige';")
e.Item.Attributes.Add("OnDblClick", "alert('" & e.Item.Cells(0).Controls(0).ID & "');")
e.Item.Attributes.Add("OnMouseOut", "this.style.backgroundColor = '#CED8FD';")
End Select
End Sub
'
Protected Sub btnShowChecked_Click( _
ByVal sender As Object, _
ByVal e As System.EventArgs _
)
Dim strSelectedItems As New StringBuilder()
Dim diDataGridItem As DataGridItem
Dim chkBox As CheckBox
'
For Each diDataGridItem In dg.Items
chkBox = CType(diDataGridItem.Cells(0).Controls(0), CheckBox)
If chkBox.Checked Then
strSelectedItems.Append("<B>ID = </B>")
strSelectedItems.Append(diDataGridItem.Cells(1).Text)
strSelectedItems.Append(" <B>Name = </B>")
strSelectedItems.Append(diDataGridItem.Cells(2).Text)
strSelectedItems.Append("<BR>")
End If
Next
Response.Write(strSelectedItems.ToString)
End Sub
'
Private Sub FormatDataGrid()
'
dg.CellPadding = 5
dg.BorderColor = Color.Black
'Set Font settings
dg.Font.Name = "Arial"
dg.Font.Size = New FontUnit(10)
'Show Header and Footer
dg.ShowHeader = True 'Default is true
'Set Header Style
dg.HeaderStyle.Font.Bold = True
dg.HeaderStyle.BackColor = Color.DarkGray
dg.HeaderStyle.ForeColor = Color.Black
dg.HeaderStyle.HorizontalAlign = HorizontalAlign.Center
dg.HeaderStyle.VerticalAlign = VerticalAlign.Middle
'Set Item Style
dg.ItemStyle.BackColor = Color.Cyan
dg.ItemStyle.ForeColor = Color.Black
'Set Alternating Item Style
dg.AlternatingItemStyle.BackColor = Color.FromArgb(206, 216, 253) 'In Hex = #CED8FD
dg.AlternatingItemStyle.ForeColor = Color.Black
End Sub
'
Private Sub FormatColumns(ByRef tblData As DataTable)
'
Dim colDataColumn As DataColumn
For Each colDataColumn In tblData.Columns()
dg.Columns.Add(CreateBoundColumns(colDataColumn))
Next
End Sub
'
Private Function GetData(ByVal strCommand As String, _
ByVal strConn As String _
) As DataTable
'
Dim adpSQLAdapter As New SqlDataAdapter(strCommand, strConn)
Dim tblData As New DataTable()
'
adpSQLAdapter.Fill(tblData)
Return tblData
End Function
'
Private Function CreateBoundColumns( _
ByRef colDataColumn As DataColumn _
) As DataGridColumn
'
Dim bndColumn As New BoundColumn()
'
bndColumn.DataField = colDataColumn.ColumnName
bndColumn.HeaderText = colDataColumn.ColumnName.Replace("_", " ")
bndColumn.DataFormatString = SetFormatString(colDataColumn)
Return bndColumn
End Function
'
Private Function SetFormatString( _
ByRef colDataColumn As DataColumn _
) As String
'
Dim strDataType As String
'
Select Case colDataColumn.DataType.ToString()
Case "System.Int32"
strDataType = "{0:#,###}"
Case "System.Decimal"
strDataType = "{0:c}"
Case "System.DateTime"
strDataType = "{0:dd-mm-yyyy}"
Case "System.String"
strDataType = ""
Case Else
strDataType = ""
End Select
Return strDataType
End Function
End Class

3) Open Solution Explorer, right click on "MultiSelectGrid.aspx" and select "Set as Start Page" in the menu
4) Click on Debug -> Start and you should be able to see a table of Data from the Database which changes color whenever you hover your mouse on the row. Apart from that, you will be able to select as many rows as you want. Moreover, you may check/uncheck the Header checkbox and every other checkbox will behave in the same fashion. Clicking on the "Show Checked" button will write every checked rows information using the StringBuilder

MultiselectDatagrid.GIF

Comments

  • Anonymous
    March 16, 2006
    Hi Mr. Soni,
    I want to add the checkbox in vb.net (the same thing as you had developed for asp.net).
    How do i get in vb.net ?
    can you guide me with an answer ?
  • Anonymous
    March 18, 2006
    Hi Vijay...

    I have created a sample, which will show you how to do that! Just drag and drop a datagrid control in any new form and resize it accordingly. Now modify your Form_Load event as follows...  Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
           Dim connStr As String = "server=(local);database=Pubs;user id=sa;password="
           Dim cnnConnection As New SqlConnection(connStr)
           Dim strCommand As String = "select top 10 au_id as Author_ID, au_lname as " & _
           "Last_Name, au_fname as First_Name, phone as Phone_Number, state as State " & _
           "from authors"
           Dim daSqlDataAdapter As New SqlDataAdapter(strCommand, cnnConnection)
           Dim dsDataSet As New DataSet("myDataSet")
           Dim dtDataTable As DataTable
           Dim dtDataColumn As New DataColumn("CheckBox")
           '
           dtDataColumn.DataType = System.Type.GetType("System.Boolean")
           dtDataColumn.DefaultValue = True
           daSqlDataAdapter.Fill(dsDataSet)
           dtDataTable = dsDataSet.Tables(0)
           dtDataTable.Columns.Add(dtDataColumn)
           DataGrid1.DataSource = dsDataSet.Tables(0)
       End Sub Please don't forget to add the following lines on the top of your code-behind page... Imports System.Data
    Imports System.Data.SqlClient Hope that helps,
    -Rahul
  • Anonymous
    July 17, 2006
    The event is firing on Check but not when I uncheck the header checkbox. Any ideas?
  • Anonymous
    January 24, 2008
    The comment has been removed