14 VB 2005 Gridview Samples by Hannes
i collected my 14 best gridview samples which are diging deeper to share it now.
formated Boundfield
If you want to format a column you can do it with a templatefield and the new Eval expression
<%eval("field",formatexpression)%>
or shorter with 2 attributes. Take care on HTMLEncode
<asp:BoundField DataField="OrderDate" HeaderText="OrderDate" SortExpression="OrderDate" DataFormatString="{0:d}" HtmlEncode="False" /> <asp:BoundField DataField="Freight" HeaderText="Freight" SortExpression="Freight" DataFormatString="{0:c}" HtmlEncode="False" />Paging huge amount of data
Many of ASP.NET developers doesnt know that, on paging all data from the select query is transfered for every page request. You can activate Caching in SQLDatasource to prevent that.
<asp:SqlDataSource ID="SqlDataSource1" runat="server" EnableCaching CacheDuration=60Also there exists a new data cache dependency which allows to update data when the source have changes. But you have still the issue to load the complete data into the cache.
Custom paging can be implemented with objectdatasource. You need a method name for the selection of the data and 2 numbers which controls the page and size.
<asp:GridView AutoGenerateColumns=true PageSize=10 ID="GridView1" runat="server" AllowPaging="True" DataSourceID="ObjectDataSource1"> </asp:GridView> <asp:ObjectDataSource ID="ObjectDataSource1" runat="server" EnablePaging=true SelectMethod="GetProducts" TypeName="ProductDAL" StartRowIndexParameterName="startIndex" MaximumRowsParameterName="maxRows" SelectCountMethod="CountProducts" ></asp:ObjectDataSource> The dataobject can be stored as source file into the app_code directory. The sample doesnt implement the real kernel of the paging logic.Imports
Microsoft.VisualBasicImports
System.ConfigurationImports
System.DataImports
System.Data.SqlClientImports
System.Collections.GenericPublic
Class ProductDAL Public _countproducts As Integer Public Function GetProducts() As DataSet Return GetProducts(Integer.MaxValue, 0) End Function Public Function GetProducts(ByVal maxRows As Integer, ByVal startIndex As Integer) As DataSet Dim sql As String = "SELECT ProductID, ProductName, QuantityPerUnit, UnitPrice, UnitsInStock FROM Products" Using myConnection As New SqlConnection(ConfigurationManager.ConnectionStrings("NorthwindConnectionString").ConnectionString) Dim myCommand As New SqlCommand(sql, myConnection) Dim myAdapter As New SqlDataAdapter(myCommand)myConnection.Open()
Dim DS As New DataSetmyAdapter.Fill(DS)
_countproducts = DS.Tables(0).Rows.Count
Dim i As Integer = startIndex Dim itemsRead As Integer = 0 Dim totalRecords As Integer = DS.Tables(0).Rows.Count Dim dt As New DataTabledt = DS.Tables(0).Clone
While itemsRead < maxRows AndAlso i < totalRecordsdt.ImportRow(DS.Tables(0).Rows(i))
itemsRead += 1
i += 1
End WhilemyConnection.Close()
Dim ds2 As New DataSetds2.Tables.Add(dt)
Return ds2 End Using End Function Public Function CountProducts() As Integer Return _countproducts End FunctionEnd
ClassSearch data
Search can be done very easily with the controlparameter form the sqldatasource. A user types into the string into a textbox. The wizard creates a sql command which includes a WHERE condition. The problem is that this makes also a lot of traffic and caching doenst solve the problem cause a cache for each query will be stored. There exists a second type to find the data the filterparameter.
<
asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>" SelectCommand="SELECT [CustomerID], [CompanyName], [ContactName], [ContactTitle], [Address] FROM [Customers] "> <FilterParameters> <asp:ControlParameter ControlID="TextBox1" Name="CompanyName" PropertyName="Text" Type="String" /> </FilterParameters> </asp:SqlDataSource>The filtering is done with a attribute.
FilterExpression="companyname like '{0}'"Now you can cache the data.
Insert Record
Gridview have now default Insert feature. Anyway the wizard of sqldatasource creates the insert command. You can swith to other controls like detailsview or use my approach.
Add a textbox for primarey key and a button to the form. Change the Insert command to insert only the necesarry field like PK.
Click Event: set parameter, call insert, databind to refresh, find new added row
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)SqlDataSource1.InsertParameters(0).DefaultValue = TextBox1.Text
SqlDataSource1.Insert()
GridView1.DataBind()
Dim dk As DataKey Dim i As Integer = 0 For Each dk In GridView1.DataKeys If dk.Value = TextBox1.Text ThenGridView1.EditIndex = i
Exit For End Ifi += 1
Next End Sub
Multirow select
A quite well known sample. I will show it for the complete picture. A Checkbox in any row gives the user the possibility to select the row (Templatefield). A button handles the event to handle the selection.
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Dim i As Int16 For i = 0 To GridView1.Rows.Count - 1 If CType(GridView1.Rows(i).FindControl("check"), CheckBox).Checked() ThenLabel1.Text += (
"-" & GridView1.DataKeys(i).Value.ToString) End If Next End SubTo check or uncheck all rows with one click, i added another Checkbox in the header of the templatefield.
<asp:TemplateField> <HeaderTemplate> <asp:CheckBox ID="Alle" OnClick="javascript: return selectAll (this.checked);" runat="server" /> </HeaderTemplate> <ItemTemplate> <asp:CheckBox runat=server ID="check" /> </ItemTemplate> </asp:TemplateField>You must use some jscript to do the client job.
<
script language=javascript>function
selectAll (alle){
var frm = document.forms[0];for
(i=0; i<frm.length; i++){
if (frm.elements[i].id.indexOf('check') != -1){frm.elements[i].checked = alle;
}}}
</script>Calculated row
There are nearly no limitations in templatefields. Also you can call a "external" function to calculate some thing.
<asp:TemplateField HeaderText="summe"> <ItemTemplate><%
#summe(Eval("unitprice"), Eval("quantity"))%> </ItemTemplate> </asp:TemplateField>Dropdown in gridview edit mode
I have made several postings about the details so i only put the code here.
<asp:TemplateField HeaderText="PostalCode" SortExpression="PostalCode"> <EditItemTemplate> <asp:DropDownList ID="DropDownList1" runat="server" DataSourceID="DSPLZ" DataTextField="PostalCode" DataValueField="PostalCode" SelectedValue='<%# Bind("PostalCode") %>'> </asp:DropDownList> </EditItemTemplate> <ItemTemplate> <asp:Label ID="Label1" runat="server" Text='<%# Bind("PostalCode") %>'></asp:Label> </ItemTemplate> </asp:TemplateField>Nested Master Detail
Following the logic from the previous sample you can handle also a gridview as child control. To control the where condition from the related child table i use a hidden field in the same template.
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="OrderID" DataSourceID="DSOrders"> <Columns> <asp:BoundField DataField="OrderDate" HeaderText="OrderDate" SortExpression="OrderDate" /> <asp:BoundField DataField="EmployeeID" HeaderText="EmployeeID" SortExpression="EmployeeID" /> <asp:BoundField DataField="Freight" HeaderText="Freight" SortExpression="Freight" /> <asp:BoundField DataField="OrderID" HeaderText="OrderID" InsertVisible="False" ReadOnly="True" SortExpression="OrderID" /> <asp:TemplateField> <ItemTemplate> <asp:HiddenField ID="HiddenField1" runat="server" Value='<%# Eval("OrderID") %>' /> <asp:GridView ID="GridView2" runat="server" AutoGenerateColumns="False" DataSourceID="DSDetails"> <Columns> <asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice" SortExpression="UnitPrice" /> <asp:BoundField DataField="Quantity" HeaderText="Quantity" SortExpression="Quantity" /> <asp:BoundField DataField="Discount" HeaderText="Discount" SortExpression="Discount" /> </Columns> </asp:GridView> <asp:SqlDataSource ID="DSDetails" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>" SelectCommand="SELECT [UnitPrice], [Quantity], [Discount] FROM [Order Details] WHERE ([OrderID] = @OrderID)"> <SelectParameters> <asp:ControlParameter ControlID="HiddenField1" Name="OrderID" PropertyName="Value" Type="Int32" /> </SelectParameters> </asp:SqlDataSource> </ItemTemplate> </asp:TemplateField> </Columns> </asp:GridView> <asp:SqlDataSource ID="DSOrders" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>" SelectCommand="SELECT [OrderDate], [EmployeeID], [Freight], [OrderID] FROM [Orders]"> </asp:SqlDataSource>Rows with buttons
Not realy a secret: If you add buttons to rows you can make the selection of the button action with the attribute commandname
<asp:ButtonField Text="new order" CommandName="order" ButtonType=Button/>
The Event have as second argument a reference to that command.
Protected Sub GridView1_RowCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs) Select Case e.CommandName Case "order"Label1.Text =
"new order for:" + GridView1.DataKeys(e.CommandArgument).Value End Select End SubFull row select and hovering
During the creation of the gridview you can add functionality in the rowcreated event. In this sample i add Jscript which changes the background color and fires a event for a existing button.
Protected Sub GridView1_RowCreated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs)e.Row.Attributes.Add(
"onMouseOver", "this.style.background='silver'")e.Row.Attributes.Add(
"onMouseOut", "this.style.background='white'")e.Row.Attributes.Add(
"onClick", "__doPostBack('GridView1','Hannes$" + e.Row.DataItemIndex.ToString + "')") End SubThis is a kind of trick which can be figured out if you look at the generated page source.
<asp:ButtonField ButtonType="Button" CommandName="Hannes" Text=">>" />Show the ordering with image
If you click on a column header user changes the sorting. To show the acutal status i add a arrow image which is named like the ortdirection.
Protected Sub GridView1_RowCreated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Dim x As Integer Select Case e.Row.RowType Case ListItemType.Header For x = 0 To GridView1.Columns.Count - 1 Dim lb As LinkButtonlb =
CType(e.Row.Cells(x).Controls(0), LinkButton) If lb.CommandArgument = GridView1.SortExpression Then Dim img As New System.Web.UI.WebControls.Imageimg.ImageUrl = GridView1.SortDirection.ToString +
".gif"e.Row.Cells(x).Controls.Add(img)
End If Next End Select End SubDelete Confirmation
<
asp:TemplateField ShowHeader="False"> <ItemTemplate> <asp:LinkButton ID="LinkButton1" runat="server" CausesValidation="False" CommandName="Delete" OnClientClick="return confirm('are you sure?');" Text="L”schen"></asp:LinkButton> </ItemTemplate> </asp:TemplateField>(no comment)
CSS Control Adapters
No source code here. But cou can use the CSS control adapters to change the renderd HTML code without changing page or page code.
eg TH instead of TH rendering
(from my point of view this is a kind of bugfixing)
http://www.asp.net/cssadapters/GridView.aspx
Smarter UI (Callback)
Gridview have a atrribute
EnableSortingAndPagingCallbacks
which do this both jobs without a visible postback. Also page have a attribute
MaintainScrollPositionOnPostbackwhich directs the user to the same position after postback.
Much better is to use ATLAS (now AJAX). You only have to put the gridview into a updatepanel. No more visible postbacks!