OnSelectedIndexChanged no working in aspx Page - vb.net

i have this dropdownlist in my page
<asp:DropDownList ID="ddlselectTaxas" runat="server" AutoPostBack="True" CssClass="form-control" OnSelectedIndexChanged="ddlselectTaxas_SelectedIndexChanged"
EnableViewState="True" ViewStateMode="Enabled"></asp:DropDownList>
and this is the function in the vb file
Public Sub ddlselectTaxas_SelectedIndexChanged(sender As Object, e As EventArgs)
taxas.TryGetValue(ddlselectTaxas.SelectedItem.Text, valorTxt.Text)
valorTxt.Text = valorTxt.Text.Substring(0, valorTxt.Text.Length - 2)
End Sub
I want to change the value of a textbox (valorTxt) when I select a diferent value in the dropdownlist, but the function is not firing. I dont know why, i have zero experience with VB and asp pages. I apreciate your help. thanks in advance.
EDIT
here is the full code of the page
Public Class Emitir
Inherits System.Web.UI.Page
Public taxas As New Dictionary(Of String, String)
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
CarregaValores()
valorTxt.ReadOnly = True
End If
End Sub
Private Sub CarregaValores()
Dim dt As DataTable
Dim objAcesso As New AcessoBD
Dim consulta As String = "SELECT TE.COD_TAXA, TE.DESC_TAXA, TV.VL_TAXA FROM TAXAS_EXPEDIENTE TE JOIN TAXAS_EXPEDIENTE_VALOR TV ON TE.COD_TAXA = TV.COD_TAXA"
dt = objAcesso.DataTable(consulta, CommandType.Text)
For Each linha As DataRow In dt.Rows
taxas.Add(linha.ItemArray(1), linha.ItemArray(2))
Next
valorTxt.Text = dt.Rows.Item(0).ItemArray(2)
valorTxt.Text = valorTxt.Text.Substring(0, valorTxt.Text.Length - 2)
ddlselectTaxas.DataTextField = "DESC_TAXA"
ddlselectTaxas.DataValueField = "COD_TAXA"
ddlselectTaxas.DataSource = dt
ddlselectTaxas.DataBind()
End Sub
Protected Sub ddlselectTaxas_SelectedIndexChanged(sender As Object, e As EventArgs)
taxas.TryGetValue(ddlselectTaxas.SelectedItem.Text, valorTxt.Text)
valorTxt.Text = valorTxt.Text.Substring(0, valorTxt.Text.Length - 2)
End Sub
End Class

You don't show your code to load up the drop list.
Remember, your page load code fires EVERY time on post back.
So, if in code on page load, you load up the drop list? You need to do this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
LoadData()
LoadCal()
End If
End Sub
Sub LoadData()
Dim cmdSQL As New SqlCommand(
"SELECT ID,(FirstName + ' ' + LastName) as EmpName
FROM Employee ORDER BY FirstName")
lstEmployee.DataSource = MyRstP(cmdSQL)
lstEmployee.DataBind()
End Sub
Function MyRstP(cmdSQL As SqlCommand) As DataTable
Dim rstData As New DataTable
Using conn As New SqlConnection(My.Settings.TEST4)
Using cmdSQL
cmdSQL.Connection = conn
conn.Open()
rstData.Load(cmdSQL.ExecuteReader)
End Using
End Using
Return rstData
End Function
Now, in above, I was using a listbox, but they work the same as a drop down list (combo box).
but, if you do NOT place the loading up of data inside of the If Not IsPostBack?
Then what happens is you select a drop down, and say click on a button (or in your case autopostback = true, then the page load FIRES FIRST and THEN your code runs!!!
and, if your code re-loads the drop list? Then your selection is lost!!!
So, for just about ANY page you create, ALWAYS, but always use the is postback code stub in on-load - and thus your loading of controls data ONLY occurs one time. Since if you re-load every time, then you lose your changes.

Well, I am not sure of what was happening, but I remade my page and it is working now. something was blocking the event. Thanks for your help.

Related

VB - Gridview style after index changed

i've a gridview with pagesize=10, when i load the page and bind grid i've the correct style applied (checkbox cheched or no), but when i go to second page i can't apply the style (checkbox always not checked) and if i came back to the first page i haven't the correst style applied.
At the page load i store all checkbox states into a dictonary to check when i bind the grid.
Public listaCheckbox As New Dictionary(Of Integer, Boolean)
I tried to apply a style to the first row to understand where I'm wrong but it's always the same thing.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
RecuperaCheckbox() 'to store all checkbox value into listaCheckbox, it works
If IsPostBack = False Then
Me.BindGrid2()
End If
End Sub
Protected Sub OnPageIndexChanging(sender As Object, e As GridViewPageEventArgs) Handles GridViewListaEsp.PageIndexChanging
GridViewListaEsp.PageIndex = e.NewPageIndex
Me.BindGrid2()
End Sub
Private Sub BindGrid2()
Query = "SELECT ...
FROM ...;"
List.SelectCommand = Query
GridViewListaEsp.DataBind()
For i = 0 To GridViewListaEsp.Rows.Count - 1
Dim chk As CheckBox = GridViewListaEsp.Rows(i).FindControl("chkOnOff")
Dim id_azienda As String = GridViewListaEsp.Rows(i).Cells(1).Text
listaCheckbox.TryGetValue(id_azienda, chk.Checked) 'works only at the first page load
Next
GridViewListaEsp.Rows(0).Attributes.Add("style", "background-color:aqua") 'works only at the first page load
End Sub
I found the solution:
to bind grid i used the command:
list.SelectCommand = Query
this was working for all thing except for the application of the style after index changing.
I changed part of code with this:
cmdExist = New SACommand(szPrintf(Query), con)
drExist = cmdExist.ExecuteReader
Dim DT As New DataTable
DT.Load(drExist)
GridViewListaEsp.DataSource = DT
GridViewListaEsp.DataBind()
And now i can apply new style after change index page!

VB.NET: Add\remove row indexes of datagridview checkboxes rows

I am working with forms in VB.NET
There is a DatagridView table with a checkbox column.
See the picture below:
I am interested in the question: how to add the line index to the list when clicking in the checkbox (when we activate the checked status), and remove it from the list when we uncheck the checkbox?
Tried the following but this is not the correct solution:
If e.ColumnIndex = chk_column.Index Then
If e.RowIndex >= 0 Then
Try
For Each row As DataGridViewRow In dataGridNames.Rows
Dim cell As DataGridViewCheckBoxCell = TryCast(row.Cells(5), DataGridViewCheckBoxCell)
If cell.Value Is cell.FalseValue Then
bList_indexes.Add(DataGridnames.CurrentCell.RowIndex)
Exit For
Else 'If cell.Value Is cell.TrueValue Then
bList_indexes.RemoveAt(DataGridnames.CurrentCell.RowIndex)
End If
Next
Catch ex As Exception
'Show the exception's message.
'MessageBox.Show(ex.Message)
'Throw New Exception("Something happened.")
End try
End If
End If
Using DataSources allows you to take the logic out of mucking around in DataGridView events. You shouldn't perform [much] business logic on the UI anyways.
Here is the class I used to represent your data.
Public Class ClassWithSelect
Public Property [Select] As Boolean
Public Property Name As String
Public Sub New(s As Boolean, n As String)
Me.Select = s
Me.Name = n
End Sub
End Class
And all the code to set DataSources
Private myDataSource As List(Of ClassWithSelect)
Private selectedIndices As List(Of Integer)
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
myDataSource = Enumerable.Range(65, 10).Select(Function(i) New ClassWithSelect(False, Chr(i).ToString())).ToList()
DataGridView1.DataSource = myDataSource
updateSelectedIndices()
End Sub
Private Sub DataGridView1_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellValueChanged
updateSelectedIndices()
End Sub
Private Sub DataGridView1_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellContentClick
DataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit)
End Sub
Private Sub updateSelectedIndices()
selectedIndices = New List(Of Integer)()
For i = 0 To myDataSource.Count - 1
If myDataSource(i).Select Then selectedIndices.Add(i)
Next
ListBox1.DataSource = selectedIndices
End Sub
And the end result
Now you don't need to access the UI to get the indices for further processing as they are in the class-level variable selectedIndices. The UI is meant for user I/O, NOT for storing state.
Note: The event handler was taken from this answer but this answer is also linked as an improvement to the check change handler, but I felt the complexity would distract from my answer. If you find you need to click fast, look into the latter.
Also Note: The method updateSelectedIndices() should have inside it an InvokeRequired check if you plan to perform work off the UI thread

Form Loads slowly in vb.net

I am currently working in ERP project on vb.net. I want to load product data in a textbox on form load. I am using autocomplete method but having a data of around 26000 the form loads slowly for 4 mins. Is there any way to avoid this or is there any way to call this function in background when the application starts?
This is my autocomplete textbox code. It works fine but it hangs alot as of the data is so large.
Private Sub pn()
Try
con = Class1.dbconn
Dim dt As New DataTable
Dim ds As New DataSet
ds.Tables.Add(dt)
Dim da As New SqlDataAdapter("select [Part Name] from
Part_Master_Download$", con)
da.Fill(dt)
Dim r As DataRow
TextBox9.AutoCompleteCustomSource.Clear()
For Each r In dt.Rows
TextBox9.AutoCompleteCustomSource.Add(r.Item(0).ToString)
Next
con.Close()
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
the properties of the textbox should be set to true for autocompletetextbox
Don't populate the AutoCompleteCustomSource in a loop. Populate an array first and then load the list in one go with a single call to AddRange:
Dim items = dt.Rows.Cast(Of DataRow)().
Select(Function(row) CStr(row(0)).
ToArray()
TextBox9.AutoCompleteCustomSource.AddRange(items)
You should find that that speeds things up considerably. If there's still a problem with performance, we can look a bit further.
EDIT: To prove my point, I just tested the following code:
Public Class Form1
Private timer As Stopwatch
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
timer = Stopwatch.StartNew()
Dim rng As New Random
Dim a = Convert.ToInt32("a"c)
Dim z = Convert.ToInt32("z"c)
Dim items = Enumerable.Range(1, 26000).Select(Function(n) Convert.ToChar(rng.Next(a, z + 1)).ToString())
For Each item In items
TextBox1.AutoCompleteCustomSource.Add(item)
Next
End Sub
Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown
MessageBox.Show(timer.Elapsed.ToString())
End Sub
End Class
and the message displayed "00:03:08.3167858", i.e. just over three minutes to load the list. I then changed the Load event handler to this:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
timer = Stopwatch.StartNew()
Dim rng As New Random
Dim a = Convert.ToInt32("a"c)
Dim z = Convert.ToInt32("z"c)
Dim items = Enumerable.Range(1, 26000).Select(Function(n) Convert.ToChar(rng.Next(a, z + 1)).ToString())
TextBox1.AutoCompleteCustomSource.AddRange(items.ToArray())
End Sub
so a single call to AddRange instead of calling Add in a loop, and the message was "00:00:00.0557427", i.e. just under 56 milliseconds. Is that better?
You can use paging to control the amount of returned data. Check this link for detailed examples.
Another way is to use (Task Async and await) so you won't lock your UI.
Here is a few last suggestions not related directly to the question but might help clean the code a bit:
you can skip the dataset and use the datatable directly, you don't need it for just one table.
Bind your results in the datatable to a datagridview or a combobox instead of iterating through your results and filling a textbox.
cheers

Refresh/Requery combobox on form after record saved on separate form

I have spent all morning googling and looking through this site and just haven't found anything that seems to work. I have a combobox on form1 that gets its display values from a datasource tblCardTypeDD. Its Display Member is sCardType and its value member is iCardTypeID. Its selected member is fkCardTypeID from tblInventory.
When I click a button form2 pops up with a simple datagridview that allows me to add more card types to be used in the drop down. Currently I have been trying to add code to the save button click method but I just can't find a combination that actually updates the combobox.
I have been trying the following:
frmInventory.SEquipTypeComboBox.DataSource = Nothing
frmInventory.SEquipTypeComboBox.DataSource = Me.EngDBbeDataSet.tblCardTypeDD
but the drop down becomes blank after execution of the above.
Any help would be appreciated.
You should check this page, maybe it'll help you:
http://msdn.microsoft.com/en-us/library/w67sdsex.aspx?cs-save-lang=1&cs-lang=vb#code-snippet-1
In case it didn't:
if you put your breakpoint where you "reset" The combobox Datasource binding, Check if the datasource contains the new values you want to see in your combobox. it might sound stupid but its a mistake that often happens, if this is the case you know that the problem isn't with the binding
Also after making the datasource nothing and adding the datasource again in the way you did you should tell which column will be the displaymember again like so:
ComboBox1.DisplayMember = "Column1"
Though if you look at the site I told you about you should look at the note that tells you how to suspend and resume binding instead of dropping the datasource and adding it again like that.
Though if you're using a datatable the values should automatically change, and there should be no reason to drop and rebind the combobox.
--
To prove that you don't need to rebind i've very quickly made a very dirty piece of code to prove it.
form1 has a combobox that's bound to a datatable, and it also has a button to call a second form named form2.
form2 has a button that adds 2 rows to the Datatable and then goes back to the first screen.
Code Form 1:
Public Class Form1
Private dataSet As New DataSet("DataSet1")
Private dataTable As DataTable = dataSet.Tables.Add("DataTable1")
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
dataTable.Columns.Add("Column1")
Dim row1 As DataRow = dataTable.NewRow()
row1("Column1") = "Data1"
dataTable.Rows.Add(row1)
Dim row2 As DataRow = dataTable.NewRow()
row2("Column1") = "Data2"
dataTable.Rows.Add(row2)
ComboBox1.DataSource = dataTable
ComboBox1.DisplayMember = "Column1"
End Sub
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim form2 As New Form2(dataTable)
form2.Show()
End Sub
End Class
Code Form2:
Public Class Form2
Private _dataTable As DataTable
Public Sub New(ByVal dataTable As DataTable)
InitializeComponent()
_dataTable = dataTable
End Sub
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim row3 As DataRow = _dataTable.NewRow()
row3("Column1") = "Data3"
_dataTable.Rows.Add(row3)
Dim row4 As DataRow = _dataTable.NewRow()
row4("Column1") = "Data4"
_dataTable.Rows.Add(row4)
Me.Close()
End Sub
End Class

Populate an ado.net dataset with only changes from the data source

This is so simple, I must be stupid!
I have a simple access database that a log record gets written to a few times an hour.
I'm trying to make a DataGridView that shows that data as it arrives.
My "Solution" is simple;
when a user clicks the view -> read from the database (fill the datatable) -> update the view.
Not what I dreamed of, but functional, if totally sub-optimal.
However, my "solution" is a dud, using fill draws every single record from the database, even if there are already 599 on screen.
Really, I just want fill the datatable once, and add new records as they arrive (or on click if needs be).
Bonus point if you can also explain another way (that isn't called so often) to hide the ID column, and change the header of column 1 (named DateTimeStamp) to TimeStamp.
Public Class FormMain
Shared dataAdapter As OleDbDataAdapter
Shared logTable As New DataTable("log")
Shared commandBuilder As OleDbCommandBuilder
Shared queryString As String = "SELECT * FROM log"
Shared bindingSource As New BindingSource
Private Sub FormServerBridge_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Try
ConfigureDataSet()
ConfigureBindingSource()
ConfigureDataView()
Catch ex As Exception
' FIXME: Helpful for debugging purposes but awful for the end-user.
MessageBox.Show(ex.Message)
End Try
End Sub
Private Sub ConfigureDataSet()
dataAdapter = New OleDbDataAdapter(queryString, _Config.ConnectionString)
commandBuilder = New OleDbCommandBuilder(dataAdapter)
commandBuilder.GetUpdateCommand()
dataAdapter.Fill(logTable)
With logTable
.Locale = System.Globalization.CultureInfo.InvariantCulture
.PrimaryKey = New DataColumn() {logTable.Columns("ID")}
End With
End Sub
Private Sub ConfigureBindingSource()
With bindingSource
.DataSource = logTable
End With
End Sub
Private Sub ConfigureDataView()
With DataGridView
.DataSource = bindingSource
End With
End Sub
Private Sub DataGridView_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles DataGridView.Click
UpdateUI()
End Sub
Sub UpdateUI()
dataAdapter.Fill(logTable)
End Sub
Private Sub DataGridView_DataBindingComplete(ByVal sender As Object, ByVal e As DataGridViewBindingCompleteEventArgs) Handles DataGridView.DataBindingComplete
' FIXME: This code gets run as many times as there are rows after dataAdapter.Fill!
With DataGridView
.Columns("ID").Visible = False
.Columns(1).HeaderText = "Timestamp"
.Columns(1).AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells
.Columns(2).AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells
.Columns(3).AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
End With
End Sub
End Class
p.s. Links to websites and books will be appreciated, even the right MSDN page (if you know where it is, I admit I find it uncomfortable to peruse, I regularly get lost).
Assuming your IDs are sequential, the way I would approach this is:
1) Record the last id that you retrieved
2) When the user presses view, only get records whose IDs are greater than the last one record
3) Retrieve the records into a new datatable and then merge that with your existing data set.
Here is how I would make the changes (only changed info included):
Public Class FormMain
Shared logTable As DataTable
Shared bindingSource As New BindingSource
Private m_wLastID As Integer
Private Sub FormServerBridge_Load(ByVal sender As System.Object, ByVal e As System.EventArgs)
Try
ConfigureDataSet()
ConfigureBindingSource()
ConfigureDataView()
Catch ex As Exception
' FIXME: Helpful for debugging purposes but awful for the end-user.
MessageBox.Show(ex.Message)
End Try
End Sub
Private Sub ConfigureDataSet()
Dim queryString As String
queryString = "SELECT * FROM log WHERE ID > " & m_wLastID.ToString & " ORDER BY ID"
Using dataAdapter As New OleDbDataAdapter(queryString, _Config.ConnectionString)
Using commandBuilder As New OleDbCommandBuilder(dataAdapter)
Dim oDataTable As New DataTable("log")
commandBuilder.GetUpdateCommand()
dataAdapter.Fill(oDataTable)
With oDataTable
.Locale = System.Globalization.CultureInfo.InvariantCulture
.PrimaryKey = New DataColumn() {.Columns("ID")}
End With
' Record the last id
If oDataTable.Rows.Count <> 0 Then
m_wLastID = CInt(oDataTable.Rows(oDataTable.Rows.Count - 1)("ID"))
End If
If logTable Is Nothing Then
logTable = oDataTable
Else
logTable.Merge(oDataTable, True)
logTable.AcceptChanges()
End If
End Using
End Using
End Sub
Sub UpdateUI()
ConfigureDataSet()
End Sub
' Rest of the form code here