Gridview dropping milliseconds from database timestamp - asp.net

I have a Gridview that displays record from a database, including a timestamp.
In the RowDataBound event, I'm trying to check the timestamp to see if I need to disable a button but the milliseconds are dropped and so my comparisons aren't working correctly.
How do I preserve the milliseconds from the database all the way to the RowDataBound event?
My code:
Dim dt As New DataTable
Using cn = New SqlConnection(ConfigurationManager.AppSettings("MyConStr"))
cn.Open()
Dim cmd As SqlCommand = New SqlCommand("spGetRecords", cn)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.AddWithValue("#FirstParm", FirstParm)
cmd.Parameters.AddWithValue("#SecondParm", SecondParm)
Using reader = cmd.ExecuteReader()
dt.Load(reader)
End Using
End Using
gvMyGrid.DataSource = dt
gvMyGrid.DataBind()
And my RowDataBound:
Protected Sub gvMyGrid_RowDataBound(sender As Object, e As GridViewRowEventArgs) Handles gvMyGrid.RowDataBound
If gvNotes.DataSource.Rows.Count > 0 Then
Dim someTime As DateTime = "03/18/2019 08:28:09.090"
If e.Row.Cells.Item(timestampIndex).Text = someTime 'This is never true because the cell text drops the milliseconds
'Disable button here...
End If
End If
End Sub

Related

Deleting multiple Rows in GridView using Checkbox, Delete button outside of the Grid, without going to database

How do I delete multiple Rows in a GridView using a Checkbox, Delete button outside of the Grid, without going to database?
My purpose is to be able to delete multiple rows by SelectedCheckbox in the Gridview. After that, I use data show in gridview to make changes in database.
Dim dt As DataTable = ViewState("gridview")
Dim row As GridViewRow
For Each row In gridview.Rows
Dim SelectedRow As CheckBox = CType(row.FindControl("cbSelect"), CheckBox)
If SelectedRow.Checked Then
'gridview.rows(row.index).visible = false is not my case because those indexes are still there
End If
Next
I couldn't usegridview.rows(row.index).remove()/delete()
My 2nd option is store gridview to datatable by viewstate(). When i try to remove index in the FOR EACH loop, it showed error because after the 1st remove the datatable reindex.
Thanks for your help.
I got my 2nd option done by deleting row from bottom up.
I really appreciate If anyone could help me with my 1st option.
Dim dt As DataTable = ViewState("gridview")
For i As Integer = gridview.Rows.Count - 1 To 0 Step -1
Dim row As GridViewRow = gridview.Rows(i)
Dim SelectedRow As CheckBox = CType(row.FindControl("cbSelect"), CheckBox)
If SelectedRow.Checked Then
dt.Rows(i).Delete()
End If
Next
gridview.DataSource = dt
gridview.DataBind()
Yes, yes, delete each row from the bottom up. I believe it will be like this.
Private Sub Button_Delete_Checked_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button_Delete_Checked.Click
For Each row As DataGridViewRow In DataGridView1.Rows
If row.Cells("ToDelete").Value Then
MessageBox.Show(row.Cells("SomeText").Value & " will be deleted.")
End If
Next
End Sub
As for the Insert Into, this methodology should work fine.
Dim Con As OleDbConnection = New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Music_Sales_Database.mdb;")
Dim Com As OleDbCommand
Dim SaleCode As Integer
Dim MusicID As String
Dim SubTotalPrice As Decimal
Dim Copies1 As Integer
Dim STR1 As String
SaleCode = 1
Com = New OleDbCommand
Com.Connection = Con
Connection.open()
For x As Integer = 0 To SalesDataGridView.Rows.Count - 1
MusicID = SalesDataGridView.Rows(x).Cells(0).Value
SubTotalPrice = SalesDataGridView.Rows(x).Cells(5).Value
Copies1 = SalesDataGridView.Rows(x).Cells(3).Value
STR1 = "INSERT INTO Sales(Sales_ID, Sales_Date, Copies, Music_ID, Staff_ID, Total_Price) VALUES (#Sales_ID, #Sales_Date, #Copies, #Music_ID, #Staff_ID, #Total_Price)"
Dim Comm As New OleDbCommand(STR1, Con)
Comm.Parameters.AddWithValue("#Sales_ID", SaleCode)
Comm.Parameters.AddWithValue("#Sales_Date", txtDateAndTime)
Comm.Parameters.AddWithValue("#Copies", Copies1)
Comm.Parameters.AddWithValue("#Music_ID", MusicID)
Comm.Parameters.AddWithValue("#Staff_ID", txtStaff_ID)
Comm.Parameters.AddWithValue("#Total_Price", SubTotalPrice)
Command.ExecuteNonQuery()
Comm.Dispose()
Next
Connection.Close()
Obviously, you need to modify this to suit your specific needs.

After every postback dropdownlist items repeats

I have bind my dropdownlist with database. But on each PostBack the items in dropdownlist gets repeat again.
e.g.
OnPage Load I have this items in dropdownlist 1,2,3,4.. etc Now suppose page gets postBack then it looks like 1,2,3,4,1,2,3,4
Vb code
Private Sub hospitals_Load(sender As Object, e As EventArgs) Handles Me.Load
Me.PopulateAreas()
End Sub
Private Sub PopulateAreas()
If IsPostBack Then
Dim citySelector As DropDownList = Page.Master.FindControl("locationSelector")
Using conn As New MySqlConnection()
conn.ConnectionString = ConfigurationManager _
.ConnectionStrings("conio").ConnectionString()
Using cmd As New MySqlCommand()
cmd.CommandText = "Select * from areas where areaCity Like '" + citySelector.SelectedItem.ToString + "%'"
cmd.Connection = conn
conn.Open()
Using sdr As MySqlDataReader = cmd.ExecuteReader()
While sdr.Read()
Dim item As New ListItem()
item.Text = sdr("areaName").ToString()
item.Value = sdr("areaID").ToString()
'item.Selected = Convert.ToBoolean(sdr("IsSelected"))
areasList.Items.Add(item)
End While
End Using
conn.Close()
End Using
End Using
End If
UPDATE
I have master page which has dropdownlist of cities. I am using masterpage control to mycontent page like below.
Dim citySelector As DropDownList = Page.Master.FindControl("locationSelector")
Now in my PopulateArea() class there is query in which WHERE clause have cityselector. So according to city my area gets fetched.
Call your function inside not postback event so that the dropdown is not called on postback events(which fills it everything).
Private Sub hospitals_Load(sender As Object, e As EventArgs) Handles Me.Load
if ispostback = false then
Me.PopulateAreas()
end if
End Sub
its pretty simple.. the page load event is triggered every time anything is post back.
use this
Private Sub hospitals_Load(sender As Object, e As EventArgs) Handles Me.Load
If Page.IsPostBack Then
//do stuff when post back occurs
Else
Me.PopulateAreas() //put this function here so that it executes only once
End If
End Sub
If your dropdown values have to change on the postback. Say initially the values where 1,2,3,4 and on postback if the values has to be 2,3,4,5 based on some of the values you change on the form controls you will have to clear the dropdown values first and then add new values to it.
areasList.Items.Clear()
Also see that AppendDataBoundItems is not true: in your .aspx page
Change your code to,
Private Sub PopulateAreas()
If IsPostBack Then
areasList.Items.clear()
Dim citySelector As DropDownList = Page.Master.FindControl("locationSelector")
Using conn As New MySqlConnection()
conn.ConnectionString = ConfigurationManager _
.ConnectionStrings("conio").ConnectionString()
Using cmd As New MySqlCommand()
cmd.CommandText = "Select * from areas where areaCity Like '" + citySelector.SelectedItem.ToString + "%'"
cmd.Connection = conn
conn.Open()
Using sdr As MySqlDataReader = cmd.ExecuteReader()
While sdr.Read()
Dim item As New ListItem()
item.Text = sdr("areaName").ToString()
item.Value = sdr("areaID").ToString()
'item.Selected = Convert.ToBoolean(sdr("IsSelected"))
areasList.Items.Add(item)
End While
End Using
conn.Close()
End Using
End Using
End If
End Sub

Open DataTable in Excel VB

Ok, this is an interesting issue. I have been tasked with modifying an existing VB project. Currently the user selected from a series of dropdowns to select a sql query and then run that query. So the user selects and environment dropdown, the results of that dropdown populates the category dropdown. Once the category is selected, they get a dropdown of available queries. Once they select a query and hit the "Run" button, they get a gridview with the results of the query. Some of the query results are huge. The query I'm running as a test has 40 columns and 20,000 records. The query runs in less than 5 seconds but it takes over a minute to render the gridview. Once the gridview is done rendering, the user has the option to export the results to Excel. And by this, I mean the code opens an instance of Excel through gridview.RenderControl and displays the results in Excel. The user doesn't want to save the excel file and then navigate to the file, they want it to open right from the webform they are using which is what the code does currently.
However, the user doesn't care about the gridview. They don't care if they see it at all. They want to just open Excel. So instead of using gridview.RenderControl, I want to open Excel and populate it with the DataTable (or DataSet) in memory. Any thoughts on the best way to do that?
Here's how they are currently populating the gridview:
Dim MyConnection As SqlConnection
Dim MyCommand As SqlCommand
Dim MyDataTable As DataTable
Dim MyReader As SqlDataReader
MyConnection = New SqlConnection()
MyConnection.ConnectionString = ConfigurationManager.ConnectionStrings(Connection).ConnectionString
MyCommand = New SqlCommand()
MyCommand.CommandText = Sqlquery
MyCommand.CommandType = CommandType.Text
MyCommand.Connection = MyConnection
MyCommand.Connection.Open()
MyReader = MyCommand.ExecuteReader(CommandBehavior.CloseConnection)
MyDataTable = New DataTable()
MyDataTable.Load(MyReader)
If (MyDataTable.Rows.Count > 0) Then
QueryresultPanel.Visible = True
gvLineItems.DataSource = MyDataTable
gvLineItems.DataBind()
End If
MyDataTable.Dispose()
MyCommand.Dispose()
MyConnection.Dispose()
Here's how they're opening and populating the instance of Excel:
Protected Sub btnExportToExcel_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnExportToExcel.Click
Response.Clear()
Response.Buffer = True
'
' Set the content type to Excel.
'
Response.AddHeader("content-disposition", "attachment;filename=GridViewExport.xls")
Response.Charset = ""
Response.ContentType = "application/vnd.ms-excel"
'
' Turn off the view state.
'
Me.EnableViewState = False
Dim oStringWriter As New System.IO.StringWriter()
Dim oHtmlTextWriter As New System.Web.UI.HtmlTextWriter(oStringWriter)
'
' Get the HTML for the control.
'
gvLineItems.RenderControl(oHtmlTextWriter)
'
' Write the HTML back to the browser.
'
Response.Write(oStringWriter.ToString())
Response.[End]()
End Sub
Obviously, there's no RenderControl for a DataTable or DataSet and can't figure out how to get this record set to render in an instance of Excel without saving it to a file first.
Alright, here's the solution I found (in case anyone is interested). It's pretty simple actually. I just looped through the datatable and used StringWriter.
Protected Sub WriteToExcelFile(dt As DataTable)
Dim sw As StringWriter
For Each datacol As DataColumn In dt.Columns
sw.Write(datacol.ColumnName + vbTab)
Next
Dim row As DataRow
For Each row In dt.Rows
sw.Write(vbNewLine)
Dim column As DataColumn
For Each column In dt.Columns
If Not row(column.ColumnName) Is Nothing Then
sw.Write(row(column).ToString() + vbTab)
Else
sw.Write(String.Empty + vbTab)
End If
Next column
Next row
Response.Clear()
Response.ContentType = "application/vnd.ms-excel"
Response.AddHeader("Content-Disposition", "attachment;filename=DataTable.xls")
Response.Output.Write(sw.ToString())
Response.Flush()
System.Web.HttpContext.Current.Response.Flush()
System.Web.HttpContext.Current.Response.SuppressContent = True
System.Web.HttpContext.Current.ApplicationInstance.CompleteRequest()
End Sub

Dynamically adding multiple rows to a ASP Datagrid

I have a page with two datagrids. One reads the value from a database and allows selection. When the user selects a grid it adds the data to the second datagrid. This is the code I am using for this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim dc1 As New DataColumn("NAME")
Dim dc2 As New DataColumn("PRICE")
dt.Columns.Add(dc1)
dt.Columns.Add(dc2)
Dim dr1 As DataRow = dt.NewRow()
GridView2.DataSource = dt
GridView2.DataBind()
End Sub
and
Protected Sub GridView1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles GridView1.SelectedIndexChanged
Dim dr1 As DataRow = dt.NewRow()
dr1(0) = Name.ToString
dr1(1) = Price.ToString
dt.Rows.Add(dr1)
GridView2.DataSource = dt
GridView2.DataBind()
Now, this works perfectly.... but this obviously would work under a forms service. In a web based enviroment whenever a user selects a value in Grid 1 it resets the values in Grid 2 and I need that multiple rows are added to the 2nd Datagrid every time the user selects a value. The "data adding" is fired when the selectedindexchanged event takes place in GridView1. I think I need to save the data to a session/cookie but I have no idea how would I do this in the case of a datagrid. Like, what should I save and how I'd read it. Both Gridviews are under an Update Panel control so Postback should be instantaneous (if needed).
Sightly updated code...
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
dt = DirectCast(Session("Purchase"), DataTable)
Else
Dim dc1 As New DataColumn("NAME")
Dim dc2 As New DataColumn("PRICE")
dt.Columns.Add(dc1)
dt.Columns.Add(dc2)
Dim dr1 As DataRow = dt.NewRow()
GridView2.DataSource = dt
GridView2.DataBind()
End If
End Sub
and
Dim dr1 As DataRow = dt.NewRow()
Session.Add("Purchase", dt)
dr1(0) = Name.ToString
dr1(1) = Price.ToString
dt.Rows.Add(dr1)
dt = DirectCast(Session("Purchase"), DataTable)
GridView2.DataSource = dt
GridView2.DataBind()
Try this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
'This will load the DT into the session when the page initially loads and then skip it on subsequent page loads.
If Not IsPostBack Then
Dim dc1 As New DataColumn("NAME")
Dim dc2 As New DataColumn("PRICE")
dt.Columns.Add(dc1)
dt.Columns.Add(dc2)
Session.Add("Purchase", dt)
GridView2.DataSource = dt
GridView2.DataBind()
End If
End Sub
GridView1_SelectedIndexChanged:
'Clear out the old datasource.
GridView2.Datasource = Nothing
GridView2.DataBind()
'Pull the datatable from the session variable
dt = DirectCast(Session("Purchase"), DataTable)
'Create the new row and set the values
Dim dr1 As DataRow = dt.NewRow()
dr1(0) = Name.ToString
dr1(1) = Price.ToString
'Add the row to the table
dt.Rows.Add(dr1)
'If the session variable exists(which is should) then we overwrite it, if not we create it.
If Session("Purchase") Is Nothing Then Session.Add("Purchase", dt) Else Session("Purchase") = dt
'Reset the datasource of the datagrid
GridView2.DataSource = dt
GridView2.DataBind()
One thing I've run into doing this before is that in order for the datasource to actually update as expected I needed to do GridView2.Datasource = Nothing and GridView2.DataBind() as the very first thing in the event handler, I'm not sure why but it works when I do that and it doesn't when I don't so I didn't spend the time looking into it.
Seems to me like the problem is that when you select the first value, it creates a postback and that resets the other grid, you could disable EnableAutoPostback on your original element but i would like to know how are you manipulating the selected data.
I think you can easily accomplish this if instead of using 2 grids use one, add a column with a checkbox to grid named 'selected' and then save the selected row ids. Are you saving the selected rows to a database or how are you going to manipulate the selected rows? Another possibility is to use JQuery Drag and Drop (which in my opinion would be the most elegant solution but would require more time to code) with that, you can drag rows from one grid to another and then save the selected rows.

GridView + Access Database

I'm trying to link Access database with GridView control.
Here's the question:
One successful procedure to link database query.
Protected sub Query(ByVal y as string)
Dim da As New OleDbDataAdapter(y, cn)
Dim dt As New DataTable()
da.Fill(dt)
da.Dispose()
cn.Dispose()
Me.GridView1.DataSource = dt
Me.GridView1.DataBind()
ListBox1.Visible = True
End sub
What I wanted is to re-run query if the first run returns no value/result in another procedure.
Protected Sub btnFind_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnFind.Click
x = "SELECT * From Class Where Gender ='Male' And First_name ='James' "
Query(x)
If gridview.rows.count =0 then
x= "SELECT * From Class Where Gender ='Male'"
query(x)
End If
then put result into listbox.
However, I got error of "The ConnectionString property has not been initialized." on da.Fill(dt) when running the second time. First time was successful.
OK I finally got mistake corrected. I gotta Dim cn As New OleDbConnection("Provider = Microsoft.JET.OLEDB.4.0;" & "Data Source = C:\Class.mdb") again to use query instead of once for all queries.
Create and dispose the connection in the same method
Protected Sub Query(ByVal y as string)
Dim dt As New DataTable()
Using cn as New OleDbConnection("your_connection_string"), _
da As New OleDbDataAdapter(y, cn)
da.Fill(dt)
End Using
Me.GridView1.DataSource = dt
Me.GridView1.DataBind()
End Sub

Resources