Vb.net Freezing column in 2 different datagridviews - vb.net

Googling this gave me only references to the scroll bars, but that is not my issue.
I have a Tab control on my form, it has 2 tabs. On each tab there is a datagridview. The data is retrieved from my database and bound to the datagrid. The two separate tabs hold slightly different data, but with mostly the same columns. I want to freeze the first two columns and I have the code for it and it works fine, except on the initial loading of the form. When the form is loaded for the first time it access the same information that I would get if I clicked the button to import the data into the datagrid. Except when it hits the function to freeze the columns in the first tab the column is frozen, but on the second one it basically dumps all data that was in the datagrid. Which doesn't make sense because the data is still there it just isn't showing when I click on the tab.
Anyone have any idea why it would do this? and how to fix it?
Believe me I have walked through it like 6 times and had someone here look at it and it doesn't make sense. But ok I guess I can put the code in here not that it is going to do any good because the code that breaks is the second call to the frozen column.
Dim DT as New DataTable
Dim DT2 as New DataTable
DT = object.getDataTable 'this is where the sql is being pulled from
Me.DataGridView1.DataSource = DT
DT2 = object.getDataTable 'this is where the sql is being pulled from
Me.DataGridView2.DataSource = DT2
'Frozen function
IF Me.DataGridView1.RowCount > 0 Then
Me.DataGridView1.Columns("ThisColumn").Frozen = True
End If
IF Me.DataGridView2.RowCount > 0 Then
Me.DataGridView2.Columns("ThisColumn").Frozen = True
End If
that's it, there are other functions but they don't break it I have commented all of them out and the only one that breaks it is the Frozen function as defined above.

Related

Proper use of DataGridView?

My application shall allow the user to look at a table (aka "map") 14 x 28 with X and Y axis loaded from a microcontroller (MCU). This can be edited and sent back into microcontroller. I have two arrays that contain the GUI map and MCU map, which allows any differences to be flagged.
I have a DataGridView that displays the data. This works with initial data. I simply can't get new data to be updated into the DataGridView. The DataGridView is in a Form within an Mdi Child. Here's how I command the changes:
'CalDataTable is the DataGridView
'Map is an array of Single
CalDataTable.Rows.Clear()
CalDataTable.Columns.Clear()
For j As Integer = 1 To 16 'Loop through data and populate table
For i As Integer = 1 To 24
CalDataTable.Rows(j).Cells(i).Value = Map(i - 1, j - 1)
Next
Next
This event is launched from a click in the menuStrip of the Mdi Parent, and the data does not update. However, when I launch the update through a button event within the MDI Child form, it works like a charm.
Am I using the wrong tool or what else could I be missing?
Calling .Rows.Clear() and .Columns.Clear() does more work than just emptying the data. It actually removes the rows and columns from the grid. There are no longer any cells in the grid at all. You don't want that. This isn't like Excel, where the workspace is still there even when you delete things. You need the column definitions and row records to still exist.
Instead, loop through and reset each cell to an empty value, whether that's 0, an empty string, or something else. Or, since it looks like the following loop will visit every cell anyway, just remove the Clear() lines completely.

Changes in DataTable not seen from another form

I have a DataTable in my DataSet which is not bound to any table in the SQL Database since I need it only inside 2 forms. When I update it in Form1, it works just fine, the table is populated and I can see the data inside a DataGridView (here is the code I use for updating it):
Dim newProcesRow As DataRow = Me.SampleDataSet.Tables("TableSample").NewRow()
newProcesRow("Col1") = val1.ToString()
newProcesRow("Col2") = val2.ToString()
newProcesRow("Col3") = val3.ToString()
Me.Sample_DataSet.Tables("TableSample").Rows.Add(newProcesRow)
After doing this, the DataGridView in Form1 shows the entire table with no problems. After the user clicks a button, Form2 is shown, where there is a DataGridView as well with the same DataSource as the grid in the first form, the unbound table from the DataSet. I also tryed putting a MessageBox in Form2 to return the number of rows from the DataTable and the result was 0.
Is there any way I could make Form2 see the rows in the DataTable without binding it to the database? (I don't want to do unnecessary changes to the DataBase...) Or are there any saves/changes/updates I am not doing to the DataTable?
If there is anything else I should mention in order to make it easier to find a solution, tell me and I will add. Thanks in advance for any piece of advice, have a nice day! (:

VB stretch DataGridViewImageColumn images programmatically

What I am doing
I am developing a VisualBasic application where the GUI is separated from the data manipulation (frontend and backend). This particular piece of code keeps track of the Serial Numbers already measured and displays them in the Form as a DGV with the serial number and an image or not.
My code
In a class that the GUI Form instantiates, my data is stored in a DataTable with a BindingSource, with the second column displaying an Image when I tell it to in the program (Nothing in the beginning):
Public SerialNumbersBindingSource As New BindingSource
Public SerialNumbersDataTable As New DataTable
(...)
SerialNumbersBindingSource.DataSource = SerialNumbersDataTable
SerialNumbersDataTable.Columns.Add("Serial", Type.GetType("System.String"))
SerialNumbersDataTable.Columns.Add("Pass", MyImage.GetType)
In my GUI Form code, a DataGridView has its DataSource set to the former DataTable:
DataGridViewSerialNumber.DataSource = MyObject.SerialNumbersDataTable
By just updating the DataTable in my class, the DataGridView updates automatically to reflect the current state of it. I do it like:
SerialNumbersDataTable.Add(CurrentSerial, MyImage)
The results I get
The code works, so I can modify and access the DataTable and the DataGridView autoupdates. But the images are not stretching, so I can only see a small part of them.
What I need
I need the second column named "Pass" in DataGridView to stretch the images.
What have I tried
If I access the column, it is treated like a DGVColumn and not a DGVImageColumn, so the Layout operation fails.
DataGridViewSerialNumber.Columns("Pass").DataGridViewImageCellLayout.Stretch
Microsoft's Docs page tells me to do this, which treats the columns like DGVImageColumn as I need "Pass" to. It fails because the first column is a Text one, not image.
For Each column As DataGridViewImageColumn In DataGridViewSerialNumber.Columns("Pass")
column.ImageLayout = DataGridViewImageCellLayout.Stretch
Next
Also I have tried creating a local DGVImageColumn, modify it and write it onto the original column, but it is read-only.
Dim imageColumn As DataGridViewImageColumn
imageColumn = DataGridViewSerialNumber.Columns("Pass")
imageColumn.ImageLayout = DataGridViewImageCellLayout.Stretch
DataGridViewSerialNumber.Columns("Pass") = imageColumn
I have also tried to do it from the designer. If I click the DGV, arrow to the right and 'Edit Column', I can create the two columns and setup Pass as ImageColumn with Stretched Layout. But when I set up DGVSerialNumbers.Datasource to my DataTable, it adds the DataTable's columns to the DGV's.
Failed DGV with columns added in designer
It's time for you to learn how to cast. If you want to access one column then don't use a loop. Simply access the column you want and then cast it as the type you want to use it as. You also need to actually assign the appropriate value to the appropriate property.
DirectCast(DataGridViewSerialNumber.Columns("Pass"), DataGridViewImageColumn).ImageLayout = DataGridViewImageCellLayout.Stretch
If you want to break that up for clarity:
Dim imageColumn = DirectCast(DataGridViewSerialNumber.Columns("Pass"), DataGridViewImageColumn)
imageColumn.ImageLayout = DataGridViewImageCellLayout.Stretch
Also, be aware that Stretch will not retain the original aspect ratio, so you might want to use Zoom instead.

VB.NET web application - Update a data bound Listbox when underlying table / query changes

I have a page in my web application that contains two listboxes with buttons to move items back & forth between them. Each listbox is bound to a SQL query, the results of which change as the selected items are added or removed from the corresponding lists. This all works fine, except I cannot get the list boxes to update their contents on the fly, however if I refresh the web page, the contents update correctly.
Basically the user selects items in LeftListbox and clicks the Add button which calls code to loop through the LeftListbox and for each selected item adds a new record to a table (Score). The RightListbox should then update to show that the items have been added to the table.
Here is a snippet of code from the Click event of the Add button:
Dim i As Integer
For i = 0 To (LeftListbox.Items.Count() - 1)
If LeftListbox.Items(i).Selected Then
Try
DbUtils.StartTransaction()
Dim rec As ScoreRecord = New ScoreRecord
rec.Player_ID = CInt(Me.LeftListbox.Items(i).Value)
rec.Save()
DbUtils.CommitTransaction()
Catch ex As Exception
DbUtils.RollBackTransaction()
Me.Page.ErrorOnPage = True
Finally
DbUtils.EndTransaction()
End Try
End If
Next i
'** Here is where I want to refresh the list **
I've searched quite a bit for a solution, but I can't find anything that works so any help would be much appreciated.
Andrew
Use the same method (or code) used to populate the "right listbox" in the first place. The right ListBox's DataSource will be the same as it was prior to this code snipped being ran, so it must be updated since the underlying data has changed.

Can I page through grouped data in DataGridView?

I have a simple VB.NET 2008 app that helps users to edit fields in the database. Simple enough as a first "real" project in .NET, right?
For one table, I am currently using a DataGridView so it can be edited straight up. However, instead of offering the user the entire table, I'd like to group the data by the 'CompanyNumber' column and use a navigator to page through. In other words, I'd like the DataGridView to show me all the lines related to one company, then click the "next" arrow to show the next company, etc.
(I know I could do this with Xceed DataGrid, but I'm using Windows Forms not WPF, and I'd really prefer to do this with "pure" ADO.NET for this project.)
Update 2009-09-28:
So I have created a ComboBox filled from the same BindingSource, and configured its SelectedIndexChanged to change the Filter value on the DataGridView.
But still, filling the ComboBox--which should be easy!--continues to be a problem. I can either:
(a) fill it from the BindingSource, in which case I see multiples of each 'CompanyNumber' and I can't figure out a way to show only distinct values, or
(b) create another TableAdapter in the data source which is just a "Select DISTINCT CompanyNumber..." query, which mostly works, except that that first value of the list changes when I change the selection (e.g. if the ComboBox shows "100, 101, 102, 103" and I pick "102", then the list will show as "102, 101, 102, 103").
Any recommendations?
(Also, bonus if you can suggest how to make the BindingNavigator's arrows page through the 'CompanyNumber' filters instead of the items in the DataGridView... which is what I'd really like to see.)
What you could do is just force the DataGridView to sort CompanyName, this way all rows with the same company name are next to each other and the user can navigate the data grids with the paging that comes with it.
Alternatly, you could follow through with your combobox/DropDownList idea, which would be best. From what I understand when you select an item in the combobox everything in it changes?
Another way is to create two separate buttons, "Previous" "Next", that when clicked, will change the DataGridView's binding source to only show a certain company. You would need to store an array of company names, then store what the current DataGridView's binding source is displaying.
I ended up figuring it out myself, and the solution is clean and simple. Here are the basic steps:
create a DataView off of the table out of the DataSet
use the DataView.ToTable() method to create a new table filtered to only distinct values from the needed column ('CompanyNumber')
create a BindingSource which uses the new DataTable as its DataSource
bind the ComboBox to the new BindingSource
bind the BindingNavigator to the new BindingSource
Because the ComboBox and the BindingNavigator use the same BindingSource, they will update each other with the changes automagically.
Here's the rough code:
Private Sub CoNumsComboxBox_LoadData()
Dim dvCoNums As DataView, dtCoNums As DataTable
dvCoNums = New DataView(Me.ODBCDataSet.Tables("CompanyFundProfile"))
dvCoNums.Sort = "CompanyNumber ASC, FundNumber ASC"
dtCoNums = dvCoNums.ToTable("CompanyFundProfile", True, "CompanyNumber")
CoNums_BindingSource.DataSource = dtCoNums
CoNumsComboBox.DataSource = CoNums_BindingSource
CoNumsComboBox.DisplayMember = "CompanyNumber"
CoNumsComboBox.ValueMember = "CompanyNumber"
'attach handler which changes DataGridView1's filter when this changes
AddHandler ToolStripComboBox1.SelectedIndexChanged, AddressOf CoNumsComboBox_SelectedIndexChanged
CompanyFundProfile_BindingNavigator.BindingSource = CoNums_BindingSource
End Sub