How to disable SortMode in dynamically load table? - vb.net

Actually i have an application where the user is able to load an excel file to it and that excel file will be shown in a DataGrid.
Now i would implement a method where the user will be able to select different interesting columns by clicking it but the issue is that i get the error "SortMode can't be automatic when SelectionMode is set to FullColumnSelect"
if i set other SelectionMode all works fine but i need the "FullColumnSelect". I've yet read in other question that i should disable SortMode for each column but the issue is that the columns doesn't exist till the user load the excel file.
Dim myTableName = con.GetSchema("Tables").Rows(0)("TABLE_NAME")
Dim sqlquery As String = String.Format("SELECT * FROM [{0}]", myTableName)
Dim da As New OleDbDataAdapter(sqlquery, con)
da.Fill(dt)
dt.Rows.Remove(dt.Rows(0))
MetroGrid1.DataSource = dt 'App crash here
con.Close()

You could set the SortMode programmatically by looping through all the columns after the user has loaded the excel file.
'---> load the grid
dg1.SelectionMode = DataGridViewSelectionMode.FullRowSelect
For Each col As DataGridViewColumn In dg1.Columns
col.SortMode = DataGridViewColumnSortMode.NotSortable
Next

Related

Read CSV to series of existing textbox in Vb.net

I have a code to import csv to auto generated text box which was a part of my previous app. However I had to re do the whole script which involves importing csv to multiple existing textbox.
Below is my old code which worked like a charm but in this code my textbox were getting auto generated based on the numbers of value present in my csv.
Dim T(100) As TextBox
Using ofd As New OpenFileDialog()
If ofd.ShowDialog() = DialogResult.OK Then
TextBox1.Text = (ofd.FileName)
End If
Using MyReader As New Microsoft.VisualBasic.
FileIO.TextFieldParser(TextBox1.Text)
MyReader.TextFieldType = FileIO.FieldType.Delimited
MyReader.SetDelimiters(",")
Dim numer As Integer
Dim currentRow As String()
numer = 1
While Not MyReader.EndOfData
Try
currentRow = MyReader.ReadFields()
Dim currentField As String
For Each currentField In currentRow
If (currentField IsNot "") Then
Dim myTB As New TextBox
T(numer) = myTB
myTB.Text = currentField
myTB.Visible = True
myTB.Location = New Point(550, 92 + (numer * 28))
myTB.Name = "ADBox" + numer.ToString
myTB.ReadOnly = True
Me.Controls.Add(myTB)
numer += 1
End If
Next
Catch ex As Microsoft.VisualBasic.
FileIO.MalformedLineException
MsgBox("Line " & ex.Message &
"is not valid and will be skipped.")
End Try
End While
End Using
End Using
But that created a lot of issue in my app hence I had to load the values on an existing textboxes(Multiple) but I am somehow not able to.
Edit1:
*** The code above creates a textbox and adds my csv values to it and what I am looking for is inject csv to existing textbox which I have created and not automatically generated text box.
For Example my code creates text box called ADUser1,2,3,4 and enters all the value but my following code which will create a textfile by fetching the values from the text box is not working because when I declare
My.Computer.FileSystem.WriteAllText(aduser1, ADBox1.Text, True)
it says it doesn't exists because when a form loads it never created such textboxes. This is the challenge I am facing
Any help will be a great value
Thanks
I agree that this is a very awkward design and should be redone, but for the purpose of answering your question...
The reason your code here: My.Computer.FileSystem.WriteAllText(aduser1, ADBox1.Text, True) doesn't find ADBox1 is that it is not created and referenced like an object you drag on to the form. It could be, by the way, but that is more work than dragging and naming 100+ text boxes on your form. Nuts. Creating the textboxes in code is better.
If you "manually" add one textbox to a form, then examine the designer-generated code for the form you will see that it created a textbox for you. You would find something similar to Friend WithEvents ADBox1 As System.Windows.Forms.TextBox. This is the reason you can reference the textbox in your form code. There is no magic here and you are technically doing the same thing in your code, here:
Dim T(100) As TextBox
...
Dim myTB As New TextBox
T(numer) = myTB
You can use the reference T(n) to refer to any of your textboxes. It is not clear where the WriteAllText function is but you may need to be sure Dim T(100) As TextBox is a form global, then change the WriteAllText line like this to get at ADBox1:
My.Computer.FileSystem.WriteAllText(aduser1, T(1).Text, True)

How to make sortable a DataGrid bounded with a table

I load data on a DataGrid from a SQLite database with code like this:
conn.Open()
Dim sql = "SELECT * FROM TableDataGrid"
Dim cmdConnection As SQLiteCommand = New SQLiteCommand(sql, conn)
Dim da As New SQLiteDataAdapter
da.SelectCommand = cmdConnection
Dim dt As New DataTable
da.Fill(dt)
MyDataGrid.DataSource = dt
When the user click on a Row I display the data on a few textbox, combobox, no problem at all.
Now I need to let the user sort the DataGrid by clicking the column he want and of course is not that simple.
After research on the "e.RowIndex >= 0" and "System.NullReferenceException" error I understand that "The problem is that out of the box the BindingList does not support sorting! I know - sounds dumb but that is how it is." posted here: WinForms: DataGridView - programmatic sorting
So If I'm right I need to implement my own SortableBindingList but I'm confused because the samples of code are about a LIST and I load the database records on a TABLE (dt)
Example:
http://timvw.be/2007/02/22/presenting-the-sortablebindinglistt/
Another post say I can fix the trouble with a line like:
SortableBindingList<YourListType> sortableBindingList = new SortableBindingList<YourListType>(list)
What is the generic solution to make the DataGrid sortable on this case?
Thanks to the tips of the users I found the solution
Private Sub MyDataGrid_SelectionChanged(sender As Object, e As EventArgs) Handles MyDataGrid.SelectionChanged
'Check if the user clicked on a header or a row
Try
If MyDataGrid.CurrentRow.Index = Nothing Then
'Header clicked!!
Else
'Row clicked!!!
'Here I load the data of the clicked row on my form
FormCleanDataEntry()
FormShowRowData()
End If
Catch ex As Exception
'MsgBox(ex.ToString())
End Try
End Sub
The curiosity is that the exception is thrown but anyway I don't show any message to the user and the DataGrid is sorted and the program works fine

datagridview columns disappears

Guys i have a datagridview and a button on my form.
Under form load event following code runs for displaying data into datagridview columns.. I have manually added some columns in datagridview to populate data from dataset.
The button is placed on the form to clear all data except column..
I have tried several times but with data the columns also disappears..
is there any solution for this ? thanks in advance
I want to use this datagridview column again for displaying data entered in textbox... without dataset..
con.Open()
cmd.CommandText = "select Code,Name,Operations,Rate,Qty,Tax,Tax_amt,Discount,Total_Amount from products where Id = ('" & CStr(i) & "')"
Dim sdr As SqlDataReader = cmd.ExecuteReader
Dim dt As DataTable = New DataTable()
dt.Load(sdr)
dt.Columns("Code").ColumnName = "ii_code"
dt.Columns("Name").ColumnName = "ii_name"
dt.Columns("Operations").ColumnName = "ii_opera"
dt.Columns("Rate").ColumnName = "ii_rate"
dt.Columns("Qty").ColumnName = "ii_qty"
dt.Columns("Tax").ColumnName = "ii_Tax"
dt.Columns("Tax_Amt").ColumnName = "ii_taxamt"
dt.Columns("Discount").ColumnName = "ii_dis"
dt.Columns("Total_Amount").ColumnName = "ii_total"
DataGridView1.DataSource = dt
con.Close()
If the DataGridView is not bound to any data source, this code will do the trick:
DataGridView.Rows.Clear()
Else you can clear you data source in your example it is data table
Datatable.rows.clear()
I mean I have one datagridview on my form to view sales order...
On form load datagridview is filled with data...
But i want to place a button on my form which clears all the data from datagridview to accept new data without deleting data from database..
There are some text box on my form from that new data will be entered temporary on datagridview..

Using DataView with DataGridView breaks connection with BindingNavigator

Having trouble with a form with both a Datagridview control and a BindingNavigator control.
Initially I had the following code:
BS = New BindingSource(DS, dsTable) ' (earlier code) Dim BS as New BindingSource
BNV1.BindingSource = BS ' A BindingNavigator
DGV1.DataSource = BS ' A DataGridView
Everything worked well but when I inserted a new row it was displayed at the end of the DataGridView's list and I wanted it to show in the correct sequential location.
I found a recommendation in a forum somewhere that suggested using a DataView on the Datatable to solve this issue. I tried it and it worked great - almost.
Here's the new code:
BS = New BindingSource(DS, dsTable)
DV.Table = DS.Tables(dsTable) ' (earlier code) Dim DV as New DataView
DV.Sort = DS.Tables(dsTable).Columns(0).ColumnName
DGV1.DataSource = DV < ---- instead of the BindingSource 'BS'
BNV1.BindingSource = BS
New records were displayed right in the correctly sequenced location - but -
The BindingNavigator did not change as I scrolled the DataGridView. It never reflected the correct record number.
But when you clicked on the BindingNavigator's moveNext, Previous, Start and End arrows it changed the count correctly. Nothing happened in the
DataGridView but it seems like the BindingNavigator was tracking something else behind the scenes. I suppose it was the original table.
Any idea how to get the BindingNavigator sync'd to the DataView? So the DatagridView and BindingNavigator are looking at the same data?
(I know I can solve this by refilling the DataGridView each time but that seems wastefiul in resources.)
Additional Info: Code that actually does the Insert/ADD
Dim NewRow As DataRow = DT.NewRow
modCommonMaint.FillNewRow(NewRow, pnlData, dicFields)
NewRow(CntText + 1) = 0
NewRow(CntText + 2) = NewRow(0).ToString
LastAdd = txtID.Text.ToUpper.Trim
DT.Rows.Add(NewRow)
DGV1.Refresh()
Try
DA.InsertCommand = cmdA
DA.UpdateCommand = cmdU
DA.Update(DS, dsTable)
Catch ex As Exception
Console.WriteLine("Error" & ex.ToString)
Finally
End Try
This is the code that actually does the INSERT/ADD. It does NOT change under either scenario. To change the behavior all I do is swap the lines in the first 2 code blocks of this note.

Slow DataGridView Drawing\Rendering

I'm using a DataGridView to load data from a DataTable. This DataGridView is located on a tab (Forms.TabPage). When clicking this tab the datagrid takes a second or two to draw from the top down, regardless of wheather data is being loaded or not.
Is there anything I can do to speed up the Drawing\Rendering when clicking the Tab?
I Don't think the actual population of the DGV is causing this, as it's filled during form load so by the time the tabs click it would have loaded the few rows (20 - 30) it displays.
Using cn As New SqlConnection(connectionString)
Using cmd As SqlCommand = cn.CreateCommand()
cmd.CommandType = System.Data.CommandType.Text
cmd.CommandText = _
" SELECT [finish_time], [file_name], [transfer_status]" & _
" FROM dbo.[transfer_log]"
cmd.Notification = Nothing
cn.Open()
Dim columnSpec = New DataColumn()
With columnSpec
.DataType = GetType(System.String)
.ColumnName = "ClmFinishTime"
End With
Datatable1.Columns.Add(columnSpec)
Dim columnSpec2 = New DataColumn()
With columnSpec2
.DataType = GetType(System.String)
.ColumnName = "ClmFilename"
End With
Datatable1.Columns.Add(columnSpec2)
Dim columnSpec3 = New DataColumn()
With columnSpec3
.DataType = GetType(System.Byte())
.ColumnName = "ClmStatus"
End With
Datatable1.Columns.Add(columnSpec3)
Using dr As SqlDataReader = cmd.ExecuteReader()
While dr.Read()
Dim row As DataRow = Datatable1.NewRow
row("ClmFinishTime") = dr.Item("finish_time")
row("ClmFilename") = dr.Item("file_name")
Select Case dr.Item("transfer_status")
Case 0
row("ClmStatus") = ConvertToByte(My.Resources.accept)
Case 1
row("ClmStatus") = ConvertToByte(My.Resources.remove)
End Select
Datatable1.Rows.Add(row)
End While
End Using
End Using
DataGridView2.AutoGenerateColumns = False
DataGridView2.DataSource = Datatable1
I fixed this by double buffering the control:
Public Shared Sub SetDoubleBuffered(ByVal control As Control)
GetType(Control).InvokeMember("DoubleBuffered", BindingFlags.SetProperty Or BindingFlags.Instance Or BindingFlags.NonPublic, Nothing, control, New Object() {True})
End Sub
My two cents on this. I had a DGV that was extremely slow, even with only 100 records. Running the query wasn't the issue -- it returned results in milliseconds.
I tried the various 'doublebuffer' techniques, to no avail.
With my DGV on a TabControl, I was thinking there was possibly an issue with TabControls + DGVs.
To troubleshoot this, I created a new form, added a DGV, and had it populate the DGV on the form load event. I was quite happy to see the data loaded instantly.
I then started going through each property I had set on my original DGV, changing only one at a time, then opening the form. The DGV loaded instantly, until I set the RowHeadersWidthSizeMode. The default setting for this is 'EnableResizing', whereas my original, slow DGV had been changed to 'AutoSizeToAllHeaders'.
vs.
Sure enough, setting this back to the default of 'EnableResizing' resolved my slow DGV issue. I'm able to reproduce this side-by-side. Leave the DGV # 'EnableResizing', DGV loads instantly. Change it to 'AutoSizeToAllHeaders' and it takes 1-2 seconds before the DGV loads.
Just thought I'd share my experience with this.
Alternatively to #madlan simply set the DoubleBuffered property in the constructor by inheriting the control.
public class DoubleBufferedDataGridView : DataGridView
{
public DoubleBufferedDataGridView() : base()
{
this.DoubleBuffered = true;
}
}
I had a similar problem due to placing the DataGridView object into a TableLayoutPanel. The default behavior in Visual Studio of a TableLayoutPanel has the following property:
Focus -> CausesValidation = True
Due to this, it was taking up to 10 minutes to populate the DataGridView from a large DataTable.
In the Forms Designer, I set this value to
Focus -> CausesValidation = False
My DataGridView now works properly, it redraws in a second or less, and its data source is linked to a DataTable containing 2,000 rows and 100 columns, some cells holding text of up to 32,767 characters. Its response to the user editing cells etc. has no apparent delay.