Proper use of DataGridView? - vb.net

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.

Related

Determine the Cell of a Table Layout Panel Controls are Contained in

I am working on a project in VB.Net, and am using a Table Layout Panel to allow for multiple windows to be open side by side with one another.
The issue I am dealing with right now is figuring out exactly which Column of the Table Layout Panel components are placed in at run time.
For example, let's say I have two Windows open, with 3 Columns. So there are controls in Columns 1 & 2, and Column 3 is empty. If I close the Window in Column 1, I want to detect the Column it was in, so that I can shift the Window in Column 2 over to Column 1. I'm trying to do this so I can resize the windows based on how many windows are being opened side by side.
However I can't seem to find a way to determine exactly while Column is the 'parent' Column. The parent container is the Table Layout Panel itself, but I don't know how to get the information I am looking for.
You can determine the position of a child control inside a TableLayoutPanel using its GetPositionFromControl() method, which will return a TableLayoutPanelCellPosition structure, identifying the Column and Row of the cell that a control is occupying:
Dim Position As TableLayoutPanelCellPosition =
TableLayoutPanel1.GetPositionFromControl([ControlName])
Position reports Position.Column and Position.Row as Integer values.
You can also detemine which child control is occupying a specified position, using the GetControlFromPosition() method:
Dim MyControl As Control = TableLayoutPanel1.GetControlFromPosition(0, 0)

Number Picker in Access / VBA

I am trying to put a number picker in a form in MS Access 2007. Here's an example of what I am trying to make:
I cannot find this in the default form controls, and have tried to make one myself using a listbox. Listboxes can be modified to look just like the number picker above, however the arrows only change the view, of the list, and not the actual selection (that is the value). For example, with the list box, if I have it range from 1 to 3, and default at 1 - when I change it to 2 via the arrows, the value of the listbox does not change, and is still one.
Does anyone know how to get a number picker in Access?
So you want to create a list of numbers and allow users to change the value displayed (AND stored as the control's value) using up and down arrows, such that they select the next or previous in the list.
I would suggest creating a text box and two buttons. Populate an array with the list of values. When a button is clicked it would:
A. Find the position in the array of any value already entered into the text box (eg loaded from a database)
B. Get the next or previous item from the array.
The array is populated as required (probably when the form is opened).
If you just need to allow the user to enter a whole integer number (ie a number spinner) you would do as follows:
Create one using a (locked) textbox and two buttons. Just add a textbox (name it something like txtValue) and two buttons (btnUp and btnDown), then add code like this to the Click event of those buttons:
Private Sub btnUp_Click()
Me.txtValue = Nz(Me.txtValue, 0) + 1
End Sub
Private Sub btnDown_Click()
Me.txtValue = Nz(Me.txtValue, 0) - 1
End Sub
You could add if statements to limit the data being entered
Or you can use a 3rd party control.
http://www.fmsinc.com/microsoftaccess/controls/components/spin-button/index.html
There are probably more, but be aware that using these sorts of controls in Access is unsupported, and there is no guarantee moving forward that they will work in Access. You're far better off using the native methods described earlier.

Setting the value of cell in datagridview not working in form load

This is my code for setting the value in datagridview cell:
For i = 0 To dvJOBranch.Rows.Count - 1
dvJOBranch.Rows(i).Cells.Item("XS").Value = 0
dvJOBranch.Rows(i).Cells.Item("S").Value = 0
dvJOBranch.Rows(i).Cells.Item("M").Value = 0
dvJOBranch.Rows(i).Cells.Item("L").Value = 0
dvJOBranch.Rows(i).Cells.Item("XL").Value = 0
Next
Its working in button event, shown form event, but not in form load, and there are no errors.
My question is why it does not work in form load?
My guess is that you are using the DataGridView.AutoGenerateColumns functionnality and even if you set the DataSource property, the DatagridView won't create columns until the grid is displayed.
It could explain why it's not working in formload (grid is not initialized yet) and it works after (with shown event for example).
So it's possible that:
you try to access items that do not exist yet (but the code should raise an exception)
or you access valid rows or columns, but they are replaced when the grid is displayed the first time or bound again to a data source, and so your code has no effect (probably your case since you do not mention an exception).
Using form_shown is maybe a possible workaround, but I recommend you to use the DataGridView.DataBindingComplete event which is more especially designed to handle this situation.
See also these related issues (same cause):
Why DataGridColumn not getting removed from DataGridView
Datagirdview and tabcontrol issue
Strange issue with a datagridview and a tabcontrol C#
DataGridView has no columns

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.

figure out rowindex on a row I just inserted?

I've got a vb project I am updating and it has a datagridview, a panel, and buttons along the bottom. The buttons control CRUD operations. The panel shows numerical up/downs and textboxes to represent the selected row.
I use some logic to keep track of current selected row and current row index for timer updates in the background. Upon delete I reset focus on the first row. Upon loading I set focus on first row. On update I keep current row focus.
Upon a good insert I would like to set the focus to the row I just inserted. But I do not know a way to determine what the rowindex value is for this freshly inserted row. My datatable which the datagridview uses is sorted on two id columns so it's not like the new entry will just jump to the bottom.
Any ideas on how I can implement this?
If you don't want to deal with the RowAdded event as Jay Riggs suggested, if you add it using a row object, as opposed to just Rows.Add, you should be able to pull that off of the row object after it's inserted.
Dim dgr As New DataGridViewRow()
DataGridView1.Rows.Add(dgr)
Me.DataGridView1.Rows.IndexOf(dgr)
This should also work for insert as well.
Check out the DataGridView RowAdded event; its DataGridViewRowsAddedEventArgs parameter includes the RowIndex property which gives you what you need.
The event fires everytime a row is added, so you'll have to either wire the event up when you want to check for added rows, or ignore the event when you don't care when a row is added (such as when your grid fills with data).
If you manually add rows to the DataGridView, then you can just use the return value from the Add method. Examples:
Dim newRowIndex As Integer = myDataGridView.Rows.Add()
myDataGridView.Rows(newRowIndex).Selected = True
No need to call IndexOf. If the DataGridView is bound to a DataSource then Jay Riggs' solution of using the RowsAdded event is the way to go.