Has anybody seen anything on a custom gridview with builtin alpha paging - asp.net

I have a a custom gridview control that I like to incorpoarate different features as I come across them. Is there a way to access the datasource and the method being used to update the data with clicked letter? I have figured out how to create the alpha links in the footer like so
Protected Overloads Overrides Sub OnRowCreated(ByVal e As GridViewRowEventArgs)
MyBase.OnRowCreated(e)
If e.Row.RowType = DataControlRowType.Footer Then
Dim intNoOfMergeCol As Integer = e.Row.Cells.Count
'except last column
For intCellCol As Integer = intNoOfMergeCol - 1 To 1 Step -1
e.Row.Cells.RemoveAt(intCellCol)
Next
e.Row.Cells(0).ColumnSpan = Me.HeaderRow.Cells.Count
For i As Integer = 65 To (65 + 25)
Dim lb As LinkButton = New LinkButton()
lb.Text = Char.ConvertFromUtf32(i) & " "
lb.CommandArgument = Char.ConvertFromUtf32(i)
lb.CommandName = "AlphaPaging"
e.Row.Cells(0).Controls.Add(lb)
Next
e.Row.Cells(0).HorizontalAlign = HorizontalAlign.Left
End If
End Sub
I can use the rowCommand event to check for the click like so
Protected Overloads Overrides Sub OnRowCommand(ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs)
If e.CommandName = "AlphaPaging" Then
'todo
End If
End Sub
But I am unsure of where to get the data information needed to make the functionality work. Any clues will be very much appreciated

I don't think I would try and add such a filter or setup to the GV.
I would simple drop the filter below the GV.
And that will save a LOT of work. Better yet, we can use say a control like RadioButton list.
Why?
Well a radio button list automatic ONLY allows one choice, and thus clicking on one letter will highlight, and un-highlight for us automatic.
more why?
The RadioButton list has ONE event - so we don't have to write/wire up a whole bunch of buttons to one event - it done for use
more more why?
RadioButton list, like all asp.net controls can be feed data - just like most controls - so we follow the design pattern to fill out that control like anything else.
more more more why?
We can flip the RadioButton list over to a check box - and now we have multiple filters as possible.
So, say we have this simple grid:
<div style="width:60%;padding-25px">
<br />
<asp:GridView ID="GridView1" runat="server"
AutoGenerateColumns="False" DataKeyNames="ID" CssClass="table">
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" />
<asp:CheckBoxField DataField="Active" HeaderText="Active" />
<asp:BoundField DataField="Description" HeaderText="Description" />
</Columns>
</asp:GridView>
</div>
Ok, code to fill is this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
LoadGrid
End If
End Sub
Sub LoadGrid()
Using conn As New SqlConnection(My.Settings.TEST4)
Dim strSQL As String =
"SELECT * FROM tblHotels ORDER BY HotelName"
Using cmdSQL As New SqlCommand(strSQL, conn)
conn.Open()
Dim rstData As New DataTable
rstData.Load(cmdSQL.ExecuteReader)
GridView1.DataSource = rstData
GridView1.DataBind()
End Using
End Using
End Sub
And we now have this:
so, now lets drop in a RadioButton ist - right below the grid.
(I don't think trying to put inside the GV is worth the efforts).
So, we add this mark up -
</asp:GridView>
<div style="border:solid;border-color:black;border-width:1px;padding:5px;margin-top:-12px">
<asp:RadioButtonList ID="RadioAlpha" runat="server"
AppendDataBoundItems="True"
RepeatDirection="Horizontal"
DataTextField="Value"
DataValueField="Key" CssClass="rMyChoice"
AutoPostBack="true">
</asp:RadioButtonList>
So, we drop in that radio button list.
Now, in load grid to the above code, we have this:
Dim bList As New Dictionary(Of Integer, String)
For i As Integer = Asc("A") To Asc("Z")
bList.Add(i, Chr(i))
Next
bList.Add(0, "All") ' we need a "all/no filter"
' bind this to our radio button list
RadioAlpha.DataSource = bList
RadioAlpha.DataBind()
RadioAlpha.SelectedValue = 0
And with that style sheet - we hide the radio button - so only letter shows, and we now have this
And now the filter code is easy - we have ONE RadioButton event, and our code can be this:
Protected Sub RadioAlpha_SelectedIndexChanged(sender As Object, e As EventArgs) Handles RadioAlpha.SelectedIndexChanged
Using conn As New SqlConnection(My.Settings.TEST4)
Dim strSQL As String = "SELECT * FROM tblHotels"
Using cmdSQL As New SqlCommand(strSQL, conn)
conn.Open()
If RadioAlpha.SelectedItem.Text <> "All" Then
cmdSQL.CommandText &= " WHERE HotelName like #H + '%' "
cmdSQL.Parameters.Add("#H", SqlDbType.NVarChar).Value = RadioAlpha.SelectedItem.Text
End If
cmdSQL.CommandText &= " ORDER BY HotelName"
Dim rstData As New DataTable
rstData.Load(cmdSQL.ExecuteReader)
GridView1.DataSource = rstData
GridView1.DataBind()
End Using
End Using
End Sub
So, click on a letter, we get this:
So not only is the filter code quite easy, but MORE imporant, is the "B" button highlights for us, only one button can be clicked.
So, I don't think I would shove such a filter into the GV.
And we can add/turn on data paging for the above. After all, hitting "all" or some letter certainly could produce more then a page of data.

Related

Insert Rows In Gridview

I have a standard Gridview which is populated from a SQLDataSource. The Gridview will always have 17 rows. Can anyone please give me an example of how to manually insert rows into it at designated row spots? For example, insert a new row into rows 3 and 5.
Thanks
Well, it not at all clear why say inserting at row 5, or at row 8 is important here?
Remember, when we used desktop PC - single user, or say used punch cards?
Then order of data entered DID matter. But, we now don't use punched cards, and thus order of such data does not really matter from a database point of view. I mean, if you have multiple users entering data, and I insert at row 5, then what happens if 3 other uses also did the same. Now that record is in the 8th position. So, introduction of a "order" or some "position" NEEDS some further context here - in other words what is the goal here?
when working with a database, the FIRST rule is that data does NOT have order. And if YOU need some kind of order, say like date of entry, or even say order of new records added, then you the developer needs to design that into your software.
Now, having stated the above? Sure, there are class problems or say UI interface types of issues in which you might have say a order of 5 boxes, and you need to offer the user the ability to re-order those 5 items in ANY order you wish.
Ok, so having stated above?
Well, it not clear how the records were entered in the first place. and it not clear HOW the record that exists in the 5th position is supposed to be the 5th record.
Ok, now regardless of the above?
The trick to adding rows, or deleting rows, or inserting data? Do this at the data level, and NOT at the gridview level. This not only separates out the UI layer, and the data layer? It also saves world poverty and boatloads of complex code.
So, lets assume we have a column called "myorder". And if you don't have this column in the table, then you really quite much need to add it, since as I stated, some data order does not exist by magic, but in fact has to be "designed" and "managed" by YOU THE developer!!!
So, lets take a simple gv like this:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" CssClass="table borderhide" >
<Columns>
<asp:TemplateField HeaderText="First" ><ItemTemplate>
<asp:TextBox ID="txtFirst" runat="server" Text='<%# Eval("FirstName") %>' Width="80px">
</asp:TextBox>
</ItemTemplate></asp:TemplateField>
<asp:TemplateField HeaderText="Last"><ItemTemplate>
<asp:TextBox ID="txtLast" runat="server" Text='<%# Eval("LastName") %>' Width="80px">
</asp:TextBox>
</ItemTemplate></asp:TemplateField>
<asp:TemplateField HeaderText="Hotel"><ItemTemplate>
<asp:TextBox ID="txtHotel" runat="server" Text='<%# Eval("HotelName") %>'></asp:TextBox>
</ItemTemplate></asp:TemplateField>
<asp:TemplateField HeaderText="Description" ><ItemTemplate>
<asp:TextBox ID="txtDescription" runat="server" Text='<%# Eval("Description") %>'
TextMode="MultiLine" Rows="3" Columns="45"
></asp:TextBox>
</ItemTemplate></asp:TemplateField>
<asp:TemplateField HeaderText="Active" ItemStyle-HorizontalAlign="Center" ><ItemTemplate>
<asp:CheckBox ID="chkActive" runat="server" Checked='<%# Eval("Active") %>' />
</ItemTemplate></asp:TemplateField>
</Columns>
</asp:GridView>
Ok, and our code to load the grid. and as noted, we will persit the data source for the grid, since we need to do those inserts.
So, our code to load:
Dim rstData As New DataTable
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
LoadData()
LoadGrid()
Else
rstData = ViewState("rstData")
End If
End Sub
Sub LoadData()
Using conn As New SqlConnection(My.Settings.TEST4)
Dim strSQL = "SELECT * FROM tblHotelsA ORDER BY MyOrder"
Using cmdSQL As New SqlCommand(strSQL, conn)
conn.Open()
rstData.Load(cmdSQL.ExecuteReader)
End Using
End Using
End Sub
Sub LoadGrid()
rstData.DefaultView.Sort = "MyOrder"
GridView1.DataSource = rstData
GridView1.DataBind()
RowCount.Value = rstData.Rows.Count
ViewState("rstData") = rstData
End Sub
and we now have this:
So, now we have that add button. That button will add the row to the grid, and prompt us for the location (what row to insert at).
so, the button looks like this:
<asp:Button ID="cmdSave" runat="server" Text="Save Changes" style="float:left" CssClass="btn"/>
<asp:Button ID="cmdAddRow" runat="server" Text="+Add New" style="float:right" CssClass="btn"
OnClientClick="return askwhatrow(this);"
/>
<asp:HiddenField ID="WhatRow" runat="server" ClientIDMode="Static"/>
<asp:HiddenField ID="RowCount" runat="server" ClientIDMode="Static"/>
<script>
function askwhatrow(btn) {
MyRowCount = $('#RowCount').val()
strMsg = "There are row 1 to " + MyRowCount + "\n" +
"What row to insert new record?"
strAns = prompt(strMsg)
if (strAns === null) {
return false
}
if ((strAns < 1) || (strAns > MyRowCount) ) {
alert("only 1 to " + MyRowCount + " is allowed")
return false
}
// ok, set the row insert location, and run our server side buttion
$('#WhatRow').val(strAns)
return true
}
</script>
So, when we click on add row, we get this prompt:
I of course entered say 2 (or your 5 for your example).
the js code will prompt the user, but of couse if the user hits cancel, then the button code (code behind server) will not run. The code to add the row of data now looks like this:
Protected Sub cmdAddRow_Click(sender As Object, e As EventArgs) Handles cmdAddRow.Click
' add new row to grid at location choosen by user:
GridToTable() ' save any possbile edits by user
Dim InsertLocation As Integer = WhatRow.Value
For Each OneRow In rstData.Rows
If Int(OneRow("MyOrder")) >= InsertLocation Then
OneRow("MyOrder") += 1
End If
Next
' setup new row - some defaults
Dim NewRow As DataRow = rstData.NewRow
NewRow("MyOrder") = InsertLocation
NewRow("Active") = False
rstData.Rows.Add(NewRow)
LoadGrid()
End Sub
Again, note how VERY easy it is to add that row of data. That's because we add the row into the table, and then simple re-bind the grid to display that new record. In other words, don't try to manipulate the gv, but ONLY manipulate the data!!! (that way we save world poverty and you starving from having to write too much code).
So, after we do the above, we see this:
So, with above grid? You can tab around (almost like excel). You can edit any row, make any changes you want.
We then have that ONE save button. All that does is send gv data back to the table, AND THEN IN ONE operation sends the data back to the database.
The code looks like:
Protected Sub cmdSave_Click(sender As Object, e As EventArgs) Handles cmdSave.Click
GridToTable()
Using conn As New SqlConnection(My.Settings.TEST4)
Dim strSQL = "SELECT * FROM tblHotelsA"
Using cmdSQL As New SqlCommand(strSQL, conn)
conn.Open()
Dim da As New SqlDataAdapter(cmdSQL)
Dim daU As New SqlCommandBuilder(da)
da.Update(rstData)
End Using
End Using
End Sub
Sub GridToTable()
' send all data from gv to local table
For Each gvRow As GridViewRow In GridView1.Rows
Dim pkID As Integer = GridView1.DataKeys(gvRow.RowIndex).Item("ID")
Dim OneRow As DataRow = rstData.Select("ID = " & pkID).FirstOrDefault
OneRow("FirstName") = CType(gvRow.FindControl("txtFirst"), TextBox).Text
OneRow("LastName") = CType(gvRow.FindControl("txtLast"), TextBox).Text
OneRow("HotelName") = CType(gvRow.FindControl("txtHotel"), TextBox).Text
OneRow("Description") = CType(gvRow.FindControl("txtDescription"), TextBox).Text
OneRow("Active") = CType(gvRow.FindControl("chkActive"), CheckBox).Checked
Next
End Sub
So in above, we send all edits, all additions (and if you have or add a delete button to each row, then even deletions are ALL SEND back to the database with the above simple few lines of code. As noted, this was and is possible since we persisted the rstData that drives the GV.
and really nice? Well, for 30+ years, every user on the planet who used Excel, or used any accounting system, or any other computer software? They can bounce around in that grid, make changes. And then with one simple save button send the whole she-bang back to the database.

Edit Gridview update issue

I have got a gridview which when you press select on a row it transfers you to another gridview page,
which displays more columns from that table to give more detail about that row.
I know how to do this using:
<asp:HyperLinkField DataNavigateUrlFields="MISAppID" DataNavigateUrlFormatString="ApplicationsDetails.aspx?MISAppID={0}" Text="Select" />
In the 1st Gridview then using a Stored-procedure on the second page it displays the correct row using the ID field.
In my current site on the second page, I have added an edit button that does edit the row correctly in my database but on completion, it breaks the site and I can't work out how to get it to just refresh the gridview
This is the error I get:
Exception Details: System.NotSupportedException: Updating is not
supported by data source 'SqlDataSource1' unless UpdateCommand is
specified.
Is it the case that my BindGrid is missing something or is the way I am using my Stored-procedure?
Here is my VB code:
Public Sub BindGrid() Handles SqlDataSource1.Selecting
End Sub
Protected Sub OnRowEditing(sender As Object, e As GridViewEditEventArgs)
GridView1.EditIndex = e.NewEditIndex
Me.BindGrid()
End Sub
Protected Sub OnRowUpdating(sender As Object, e As GridViewUpdateEventArgs)
Dim row As GridViewRow = GridView1.Rows(e.RowIndex)
Dim misappId As Integer = Convert.ToInt32(GridView1.DataKeys(e.RowIndex).Values(0))
Dim application As String = TryCast(row.Cells(2).Controls(0), TextBox).Text
Dim url As String = TryCast(row.Cells(3).Controls(0), TextBox).Text
Dim access_group As String = TryCast(row.Cells(4).Controls(0), TextBox).Text
Dim creator_ein As String = TryCast(row.Cells(5).Controls(0), TextBox).Text
Dim data_location As String = TryCast(row.Cells(6).Controls(0), TextBox).Text
Dim purpose As String = TryCast(row.Cells(7).Controls(0), TextBox).Text
Dim active As String = TryCast(row.Cells(8).Controls(0), TextBox).Text
Dim business_owner As String = TryCast(row.Cells(9).Controls(0), TextBox).Text
Dim area As String = TryCast(row.Cells(10).Controls(0), TextBox).Text
Dim constr As String = ConfigurationManager.ConnectionStrings("myLocalConnectionString").ConnectionString
Using con As New SqlConnection(constr)
Using cmd As New SqlCommand("UPDATE tbl_AutomationCompassApplications SET Application = #Application, URL = #URL, Access_Group = #Access_Group, Creator_EIN = #Creator_EIN, Data_location = #Data_location, Purpose = #Purpose, Active = #Active, Business_Owner = #Business_Owner, Area = #Area WHERE MISAppID = #MISAppID")
cmd.Parameters.AddWithValue("#MISAppID", misappId)
cmd.Parameters.AddWithValue("#Application", application)
cmd.Parameters.AddWithValue("#URL", url)
cmd.Parameters.AddWithValue("#Access_Group", access_group)
cmd.Parameters.AddWithValue("#Creator_EIN", creator_ein)
cmd.Parameters.AddWithValue("#Data_location", data_location)
cmd.Parameters.AddWithValue("#Purpose", purpose)
cmd.Parameters.AddWithValue("#Active", active)
cmd.Parameters.AddWithValue("#Business_Owner", business_owner)
cmd.Parameters.AddWithValue("#Area", area)
cmd.Connection = con
con.Open()
cmd.ExecuteNonQuery()
con.Close()
End Using
End Using
GridView1.EditIndex = -1
Me.BindGrid()
End Sub
Ok, say we have a list of hotels - we want to display them, and then click on a row to eit.
(and you writing WAY too much code here).
So, lets say we drop in a gridview. Use the connection wizard - let it generate the markup.
THEN REMOVE the data source on the page, remove the datasource property of the gridview.
So, in less time then it takes me to write above? We have this markup:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:Button ID="cmdView" runat="server" Text="Edit"
PK = '<%# Container.DataItemIndex %>' OnClick="cmdView_Click" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" />
<asp:BoundField DataField="City" HeaderText="City" />
</Columns>
</asp:GridView>
Note the cool trick I used to get the PK row index.
When you are looking at the grid, you can't double click on the button to wire up a event (code behind), but you CAN DO THIS!!!!
Note VERY care full in above - I typed in OnClick "=", when you HIT "=", then NOTE the inteli-sense that popped up - the create NEW event is what we need. Click on create new event - NOTHING seems to happen, but if we NOW go to code behind, we have a code stub for the button!!!
And note how I needed/wanted the PK row value - so I just shoved in and created my OWN custom attribute for that button. ("PK").
Ok, so our code to load up the grid is now this - and I included the button click code:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If IsPostBack = False Then
LoadGrid()
End If
End Sub
Sub LoadGrid()
Dim strSQL As String
strSQL = "SELECT * from tblHotels Order by HotelName"
Using cmdSQL As New SqlCommand(strSQL, New SqlConnection(My.Settings.TEST3))
cmdSQL.Connection.Open()
Dim MyTable As New DataTable
MyTable.Load(cmdSQL.ExecuteReader)
GridView1.DataSource = MyTable
GridView1.DataBind()
Session("MyTable") = MyTable
End Using
End Sub
Protected Sub cmdView_Click(sender As Object, e As EventArgs)
Dim MyBtn As Button = sender
Session("RowID") = MyBtn.Attributes.Item("PK")
Response.Redirect("~/EditHotel.aspx")
End Sub
Look how clean and simple the above is!!! I find this as easy say as MS-Access coding!!!
Ok, so the grid now looks like this:
Note the button click code.
So, our markup is this for the new page (to edit hte ONE row).
<div style="float:left;width:20%">
<div style="text-align:right">
First Name :<asp:TextBox ID="txtFirstname" runat="server" Width="150"></asp:TextBox> <br />
Last Name :<asp:TextBox ID="txtLastname" runat="server" Width="150"></asp:TextBox> <br />
Hotel Name :<asp:TextBox ID="txtHotel" runat="server" Width="150"></asp:TextBox> <br />
City :<asp:TextBox ID="txtCity" runat="server" Width="150"></asp:TextBox> <br />
Active :<asp:CheckBox ID="Active" runat="server" Width="150"></asp:CheckBox>
</div>
</div>
<div style="clear:both">
<br />
<asp:Button ID="cmdSave" runat="server" Text ="Save " />
<asp:Button ID="cmdCancel" runat="server" Text="Cancel" Style="margin-left:20px" />
</div>
</form>
and it looks like this:
and the load code and save button code for this page?
This:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If IsPostBack = False Then
LoadInfo()
End If
End Sub
Sub LoadInfo()
Dim MyTable As DataTable = Session("MyTable")
Dim MyRow As DataRow = MyTable.Rows(Session("RowID"))
txtFirstname.Text = MyRow("FirstName")
txtLastname.Text = MyRow("LastName")
txtCity.Text = MyRow("City")
txtHotel.Text = MyRow("HotelName")
Active.Checked = MyRow("Active")
End Sub
Protected Sub cmdSave_Click(sender As Object, e As EventArgs) Handles cmdSave.Click
Dim MyTable As DataTable = Session("MyTable")
Dim MyRow As DataRow = MyTable.Rows(Session("RowID"))
MyRow("FirstName") = txtFirstname.Text
MyRow("LastName") = txtLastname.Text
MyRow("City") = txtCity.Text
MyRow("HotelName") = txtHotel.Text
MyRow("Active") = Active.Checked
Using cmdSQL As New SqlCommand("SELECT * from tblHotels where ID = 0",
New SqlConnection(My.Settings.TEST3))
Dim da As New SqlDataAdapter(cmdSQL)
Dim cmdUpdate As New SqlCommandBuilder(da)
da.Update(MyTable)
End Using
Response.Redirect("~/MyTours.aspx")
End Sub
Again, look how easy, clean and readable the code is.
Study the above example - you see that you don't need all that parameters code, and you see how little code is in fact required to select a row - jump to page to edit, and then you hit save - update the data and jump back to the grid row page.

Gridview sorting up/down arrow in column headers

I'm currently working on some code which is taking care of sorting and paging data in a gridview. I'm now trying to implement sorting arrow (up/down arrows next to column headers) but I have no success. The code to implement the sorting arrows is located in the *GridView1_RowCreated* sub routine. Right now, when I run the code, I don't see the sorting arrows at all. The problematic line is the following one: "If tblAdministrators.SortExpression = lnk.CommandArgument Then" I can't figure out what's wrong with that line. It's always False therefore the arrows don't show up.
Private Function GetData(sort As SortDirection) As Data.DataView
Dim connection As OracleDBConnect = DAL.GetOracleDBConnection()
Dim request As OracleDBRequest = Nothing
Dim result As OracleDBResult = Nothing
Dim trace As OracleDBChronoTrace = Nothing
Dim status As DBStatus
Dim sb As New StringBuilder
Dim dv As DataView
With sb
.Append("SELECT * FROM USERS")
End With
request = New OracleDBRequest(sb.ToString, CommandType.Text)
status = connection.Execute(request, result, trace)
dv = New DataView(result.DataSet.Tables(0))
If (ViewState("sortExp") IsNot Nothing) Then
dv = New Data.DataView(result.DataSet.Tables(0))
If (GridViewSortDirection = SortDirection.Ascending) Then
GridViewSortDirection = SortDirection.Descending
dv.Sort = CType(ViewState("sortExp").ToString() & DESCENDING, String)
Else
GridViewSortDirection = SortDirection.Ascending
dv.Sort = CType(ViewState("sortExp").ToString() & ASCENDING, String)
End If
Else
dv = result.DataSet.Tables(0).DefaultView
End If
Return dv
End Function
Public Property GridViewSortDirection() As SortDirection
Get
If ViewState("sortDir") Is Nothing Then
ViewState("sortDir") = SortDirection.Ascending
End If
Return CType(ViewState("sortDir"), SortDirection)
End Get
Set(ByVal value As SortDirection)
ViewState("sortDir") = value
End Set
End Property
Protected Sub GridView1_PageIndexChanging(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewPageEventArgs) Handles tblAdministrators.PageIndexChanging
tblAdministrators.PageIndex = e.NewPageIndex
GridViewSortDirection = If(GridViewSortDirection = SortDirection.Descending, SortDirection.Ascending, SortDirection.Descending)
tblAdministrators.DataSource = GetData(GridViewSortDirection)
tblAdministrators.DataBind()
End Sub
Protected Sub GridView1_Sorting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewSortEventArgs) Handles tblAdministrators.Sorting
ViewState("sortExp") = e.SortExpression
tblAdministrators.DataSource = GetData(GridViewSortDirection)
tblAdministrators.DataBind()
End Sub
Protected Sub GridView1_RowCreated(sender As Object, e As GridViewRowEventArgs) Handles tblAdministrators.RowCreated
If e.Row.RowType = DataControlRowType.Header Then
For Each tc As TableCell In e.Row.Cells
If tc.HasControls() Then
Dim lnk As LinkButton = DirectCast(tc.Controls(0), LinkButton)
If lnk IsNot Nothing Then
Dim img As New System.Web.UI.WebControls.Image()
img.ImageUrl = "/images/" & (If(GridViewSortDirection = SortDirection.Ascending, "asc", "desc")) & ".gif"
If tblAdministrators.SortExpression = lnk.CommandArgument Then
tc.Controls.Add(New LiteralControl(" "))
tc.Controls.Add(img)
End If
End If
End If
Next
End If
End Sub
ASPX code:
<asp:GridView ID="tblAdministrators" runat="server" AutoGenerateColumns="false" EmptyDataText="No records found" PageSize="25" AllowPaging="True" AllowSorting="True" OnRowCreated="GridView1_RowCreated">
<Columns>
<asp:BoundField HeaderText="Name" DataField="Name" SortExpression="NAME"></asp:BoundField>
</Columns>
<Columns>
<asp:BoundField HeaderText="City" DataField="City" SortExpression="CITY"></asp:BoundField>
</Columns>
</asp:GridView>
Take a look at my sample:
<asp:GridView ID="GridView1" runat="server" AllowPaging="True"
AllowSorting="True" AutoGenerateColumns="False" DataKeyNames="CustomerId"
DataSourceID="SqlDataSource1">
<SortedAscendingHeaderStyle CssClass="sortasc" />
<SortedDescendingHeaderStyle CssClass="sortdesc" />
<Columns>
<asp:CommandField ShowSelectButton="True" />
<asp:BoundField DataField="CustomerId" HeaderText="CustomerId"
InsertVisible="False" ReadOnly="True" SortExpression="CustomerId" />
<asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" />
<asp:BoundField DataField="IdNumber" HeaderText="IdNumber"
SortExpression="IdNumber" />
</Columns>
</asp:GridView>
Pay attention on SortedAscendingHeaderStyle and SortedDescendingHeaderStyle. Just create apropriate css classes with background image (arrow up and arrow down) and you are done.
In Order to add a sorting arrow in a Data Grid on a VB.net Windows Form, you don't even have to write any code
On form in Design Mode - select the grid you are working with, right click go to properties, set Selection Mode = Cell Select
On form in Design Mode - click the arrow on the grid on the right up, to edit column properties, select edit or add columns, set SortMode = Automatic
If you have code for your cell content (say you want user to open another form while clicking on any row in the data grid) then use CellDoubleClick property to handle the event. If the you have used single click then it will sort the header and also open the form for the given cell
Private Sub _CellDoubleClick(sender As Object, e As DataGridViewCellEventArgs) Handles DGAcctGrpList.CellDoubleClick

How to Make Boolean Column Editable (asp.net VB gridView filled by DataTable that has Boolean Column) ?

After Filling a DataTable in GridView's DataSource . A column with check box Type appears but it created as read only column
and I can't enable it or make it editable... even i tried .readonly = false
and still can't be edited
can any one help please ?
you can try like this..
This is by design; rows in a GridView are not editable by default.
There's two ways you might address this:
Add an Edit link
In your GridView tag, add AutoGenerateEditButton="True". When your GridView renders in the browser, you should now find a hyperlink labelled 'Edit'. If you click it, the fields in your GridView will become editable, and the Edit link will become two links, one to save your changes to the database and the other to discard them. Using this method, all the plumbing to wire up changes in the GridView to the database can be done for you, depending on how you're doing the databinding. This example uses a SqlDataSource control.
(source: philippursglove.com)
Add a TemplateField with a CheckBox inside it
Inside the <columns> tag, you can add TemplateFields that you set the databinding up for yourself e.g.
<asp:TemplateField HeaderText="Discontinued">
<ItemTemplate>
<asp:CheckBox runat="server" ID="DiscontinuedCheckBox" Checked="<%# Eval("Discontinued") %>" AutoPostback="true" OnCheckedChanged="DiscontinuedCheckBox_CheckedChanged" />
</ItemTemplate>
</asp:TemplateField>
(source: philippursglove.com)
This checkbox will be enabled, but you need to do the work yourself to reflect any changes back to the database. This is straightforward as long as you can get a database key, as you'll need to run an UPDATE statement at some point and you want to run it on the right row! Here's two ways you could do this:
In your Gridview tag, add DataKeyNames="MyDatabasePrimaryKey". Then in your CheckedChanged event handler, you need to find out which row you are in and look that up in the DataKeys array.
Protected Sub DiscontinuedCheckBox_CheckedChanged(ByVal sender As Object, ByVal e As EventArgs)
Dim DiscontinuedCheckBox As CheckBox
Dim conn As SqlConnection
Dim cmd As SqlCommand
Dim productId As Integer
Dim selectedRow As GridViewRow
' Cast the sender object to a CheckBox
DiscontinuedCheckBox = CType(sender,CheckBox)
' We can find the row we clicked the checkbox in by walking up the control tree
selectedRow = CType(DiscontinuedCheckBox.Parent.Parent,GridViewRow)
' GridViewRow has a DataItemIndex property which we can use to look up the DataKeys array
productId = CType(ProductGridView.DataKeys(selectedRow.DataItemIndex).Value,Integer)
conn = New SqlConnection(ProductDataSource.ConnectionString)
cmd = New SqlCommand
cmd.Connection = conn
cmd.CommandType = CommandType.Text
If DiscontinuedCheckBox.Checked Then
cmd.CommandText = ("UPDATE Products SET Discontinued = 1 WHERE ProductId = " + ProductId.ToString)
Else
cmd.CommandText = ("UPDATE Products SET Discontinued = 0 WHERE ProductId = " + ProductId.ToString)
End If
conn.Open
cmd.ExecuteNonQuery
conn.Close
End Sub
Or, you could add the key in a HiddenField control:
<asp:TemplateField HeaderText="Discontinued">
<ItemTemplate>
<asp:hiddenfield runat="server" id="ProductIdHiddenField" Value='<%# Eval("ProductID") %>' />
<asp:CheckBox runat="server" ID="DiscontinuedCheckBox" Checked="<%# Eval("Discontinued") %>" AutoPostback="true" OnCheckedChanged="DiscontinuedCheckBox_CheckedChanged" />
</ItemTemplate>
</asp:TemplateField>
Protected Sub DiscontinuedCheckBox_CheckedChanged(ByVal sender As Object, ByVal e As EventArgs)
Dim DiscontinuedCheckBox As CheckBox
Dim ProductIdHiddenField As HiddenField
DiscontinuedCheckBox = CType(sender,CheckBox)
ProductIdHiddenField = CType(DiscontinuedCheckBox.Parent.FindControl("ProductIdHiddenField"),HiddenField)
conn = New SqlConnection(ProductDataSource.ConnectionString)
..................
If DiscontinuedCheckBox.Checked Then
cmd.CommandText = ("UPDATE Products SET Discontinued = 1 WHERE ProductId = " + ProductIdHiddenField.Value)
End If
...............
End Sub
i hope it will helps you....

Repeater Button CommandArgument is Empty String

Losing my mind with this one. My button gets a commandargument of empty string even though the commandargument gets set. I have verified it gets set to the correct ID in debug mode, but then when I go to access this commandargument later in the repeaters ItemCommand event the commandarguments are empty string. And I have no idea why. I end up getting a sq foreign key exception because it is inserting an ID of 0 from the empty string values. There is no other code regarding the repeaters buttons that would be resetting it.
Repeater:
<asp:Repeater ID="repeaterAddresses" ViewStateMode="Enabled" DataSourceID="sqlFacilityAddresses" runat="server">
<ItemTemplate>
<Select:Address ID="AddressControl" runat="server" />
<asp:Button ID="btnMarkAsBilling" runat="server" EnableViewState="true" CommandName="Billing" Text="Mark as billing address" />
<asp:button ID="btnMarkAsPhysical" runat="server" EnableViewState="true" CommandName="Physical" Text="Mark as physical address" />
</ItemTemplate>
</asp:Repeater>
Code behind:
Protected Sub repeaterAddresses_ItemCreated(ByVal sender As Object, ByVal e As RepeaterItemEventArgs) Handles repeaterAddresses.ItemCreated
If Not IsNothing(DirectCast(e.Item.DataItem, DataRowView)) Then
If (e.Item.ItemType = ListItemType.Item) Or (e.Item.ItemType = ListItemType.AlternatingItem) Then
Dim addressControl As Address = DirectCast(e.Item.FindControl("AddressControl"), Address)
addressControl.AddressID = CInt(DirectCast(e.Item.DataItem, DataRowView)("Address_ID").ToString())
Dim btnBilling As Button = DirectCast(e.Item.FindControl("btnMarkAsBilling"), Button)
btnBilling.CommandArgument = CInt(DirectCast(e.Item.DataItem, DataRowView)("Address_ID").ToString())
Dim btnPhysical As Button = DirectCast(e.Item.FindControl("btnMarkAsPhysical"), Button)
btnPhysical.CommandArgument = CInt(DirectCast(e.Item.DataItem, DataRowView)("Address_ID").ToString())
End If
End If
End Sub
Protected Sub repeaterAddress_ItemCommand(ByVal sender As Object, ByVal e As RepeaterCommandEventArgs) Handles repeaterAddresses.ItemCommand
Dim conn As New SqlConnection(ConfigurationManager.ConnectionStrings("Trustaff_ESig2").ConnectionString)
Dim button As Button = CType(e.CommandSource, Button)
Select Case e.CommandName
Case "Billing"
Dim cmdBillingAddress As New SqlCommand("[SP_Facility_UpdateBillingAddress]", conn)
With cmdBillingAddress
.CommandType = CommandType.StoredProcedure
.Parameters.Add(New SqlParameter("#Facility_ID", DbType.Int32)).Value = sqlFacilityAddresses.SelectParameters("Facility_ID").DefaultValue
.Parameters.Add(New SqlParameter("#BillingAddress_ID", DbType.Int32)).Value = e.CommandArgument
End With
conn.Open()
cmdBillingAddress.ExecuteNonQuery()
conn.Close()
Case "Physical"
Dim cmdPhysicalAddress As New SqlCommand("[SP_Facility_UpdatePhysicalAddress]", conn)
With cmdPhysicalAddress
.CommandType = CommandType.StoredProcedure
.Parameters.Add(New SqlParameter("#Facility_ID", DbType.Int32)).Value = sqlFacilityAddresses.SelectParameters("Facility_ID").DefaultValue
.Parameters.Add(New SqlParameter("#PhysicalAddress_ID", DbType.Int32)).Value = e.CommandArgument
End With
conn.Open()
cmdPhysicalAddress.ExecuteNonQuery()
conn.Close()
End Select
PopulateBillingPhysicalAddresses(sqlFacilityAddresses.SelectParameters("Facility_ID").DefaultValue)
End Sub
Try this:
<asp:Button ID="btnMarkAsBilling" runat="server" EnableViewState="true"
CommandName="Billing" Text="Mark as billing address"
CommandArgument='<%# Eval("Address_ID") %>'/>
Note the single quotes around the attribute value. ASP.NET will not execute the server side data binding code if they are double quotes. You'll need to remove the CommandArgument assignments from your code behind.
Address_ID will need to be a property on the object you are databinding to the repeater.

Resources