Duplicate a DataGridView on a second windows form - vb.net

I have a bound DGV that took a bit of work to get its columns set up. I'd like to show a 1-row version of this identical DGV on a second windows form. Is there a way to programatically place a copy on the second form. I would adjust the height and position of the 1-row version, and create a new binding source on the second form so that I could filter the data.

MyForm.Controls.Add(myDataGridView)
So further explanation:
In your first for you will need to make a variable or property that contains a reference to the DataGridView that you want to access.
I'd suggest doing something like this.
Public Shared Property myDataGridView As DataGridView
then after you get it set up in the form the way you want it set up
myDataGridView = originalDataGridView
Then in the second form
SecondForm.Controls.Add(FirstForm.myDataGridView)
Will add the DataGridView exactly as it is on the first form.
Edit
If you are creating it in a designer, you can just either copy and past it from the original for to the second form.
Or just on the Form.Shown or in the New() of the first form set the myDataGridView to the DataGridView that you created.

Related

How to Update the Values of a Dropdown in a Subform when the Main Form Changes

I have two forms:
InterviewMaster and InterviewDetail
InterviewDetail opens up as a subform in InterviewMaster and these two forms are linked through a common field called InterviewID
In InterviewDetail I have a textbox called Questiontype as well as combobox called InterviewDropdown.
The data in the dropdown varies based on the data on in the textbox. To make this happen, I have a next button to move to the next question. Whenever I click on next the following runs:
Dim ctlCombo As Control
Set ctlCombo = Forms!InterviewDetail!cmbInterviewDropdown
ctlCombo.Requery
The Row Source setting for my combobox is set to look up the required answers, again this is based on the value as per the textbox:
SELECT [queryAnswerOptions].[Answer] FROM queryAnswerOptions ORDER BY [Answer];
So the options are determined by my query called queryAnswerOptions
So as I cycle through my questions using my next and previous buttons, the dropdown options are updated based on the value of my textbox. This works perfectly when I open the subform from the navigation pane. However, when I open the main form and click on the next button my dropdown does not have any values. I've tried requerying the subform with no luck. I've also tried opening the subform in full screen from my main form but this also does not work. I also don't want to go that route as it does not work well with the overall flow of my form.
Any assistance will be greatly appreciated.
Problem with the query WHERE criteria parameter is when form is installed as a subform, the form reference no longer works because it must use the subform container control name. I always name container control different from the object it holds, such as ctrDetails.
Option is to put SQL statement directly in combobox RowSource instead of basing combobox RowSource on a dynamic parameterized query object - then it will work whether form is standalone or a subform.
SELECT Answer FROM InterviewAnswers WHERE QuestionID = [txtQuestionID] ORDER BY Answer;

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.

Setting ComboBox RowSource property to query in "GotFocus()" method leaves blank values in ComboBox Access VBA

I want to populate my ComboBox in an Access form using VBA based on data from another table. Previously to do this I did the following:
In the Property Sheet -> Data tab I filled out Row Source and Row Source Type fields with this information:
Now whenever I clicked on the dropdown for my combobox, it would populate the dropdown list with all of the names from t_people table.
This limited me however to when data changed in the t_people's name column. In order to get an updated list, I must close the form and re-open it so that the query runs again. I have limited the access to this Access file so that the user is only presented with x number of forms, and cannot close/open them or others.
My solution is to remove the query on the form load, and instead run the query every time the combobox gains focus, has a click event or something of the same sorts. I did this with the following event in VBA:
'Run when the "name" combobox gains focus
Private Sub nameCb_GotFocus()
[nameCb].RowSource = "SELECT name FROM t_people"
End Sub
I have set breakpoints and this code does run. However, the the combobox is not populated after it does. How can I get the combobox to populate with the values from a query for each time the combobox gains focus?
Set the RowSource in design and add a .Requery when entering the control.
Private Sub nameCb_Enter()
nameCb.Requery
End Sub

Datagridview should not clear on datasource = nothing

I am loading my datagridview through databinding. After that I would want to allow the user to add more rows to the datagridview.
This is only possible if I make the datasource of the datagridview to nothing.
When I do that , the datagridview clears when I say rows.add command.
How can I add a new row without clearing the data?
If you are using a Data-Bound DataGridView control, you cannot just simply add new row by using the cell property of the control.
A DataGridView that is bound using a DataSet can be access only using the DataSet properties. Forcing it to use the cell property can cause an error "Rows cannot be programmatically added to the DataGridView's rows collection when the control is data-bound."
Adding new row to a DataGridView control programmatically is useful when you want to pull some data from another table to a Bound DataSet with another table.
These links may help you :
http://social.msdn.microsoft.com/Forums/windows/en-US/c291d580-5a52-422a-b798-fbfb5f799b6a/cannot-add-new-rows-to-a-databound-datagridview-programmatically
http://www.codeproject.com/Questions/411452/Add-Rows-To-Databound-DatagridView

Updating a control on another form with the results of a dialog box

I made a windows form which contains a listbox (named VenueList). The listbox is pulling it's values from a list provided by a binding source VenuesBindingSource which is pulling in a ID for the value and a name for the text.
There is a button which is causing a DialogBox to appear which is asking for values to store in the database for a NEW venue. Once the values are filled and insert the database, what's supposed to happen is that the dialog box closes and goes back to the original form which invoked it.
However, instead of updating the list. The list stays the same. But if you close the form and reopen it, you see that a new value was added.
TournamentSettings.VenuesTableAdapter.InsertVenueQuery(Trim(VenueNameTxt.Text), Trim(VenueAddress1Txt.Text), Trim(VenueAddress2Txt.Text), Trim(VenueCityTxt.Text), Trim(VenueProvinceTxt.Text), Trim(VenueZipTxt.Text), Trim(CountryBox.SelectedValue), Trim(VenuePhoneNo.Text), VenueType.SelectedText, VenueWebAddress)
TournamentSettings.VenuesTableAdapter.Fill(TournamentSettings.VenueNameList.Venues)
In the above code, InsertVenueQuery is the name of a query from the designer which is invoked to add the values onto the tableadapter VenuesTableAdapter which is used to fill the combo box on load. I also sent the Fill command to refill the table with the new value.
So the question is, should I go about doing this another way, rather than feeding the Table adapter and sending a fill command on to the datatable? Or is there something that I'm not doing here which I should to force that value into the list. I'm tempted to redo everything outside of the designer but that's a lot of code since I have to essentially run two commands (one to insert the data, and another to get the ##IDENTITY value since this is run on an access database.)
Okay. This one I had to think about for a moment.
Instead of me creating a block of done on the load event, I instead created a sub function called "FillVenueList".
I used the following block of code:
Public Sub FillVenueList()
' Adding values from database to a datatable.
' From there will add to the list box.
Dim VenueConnection As New OleDb.OleDbConnection(DBconnection)
VenueConnection.Open()
Dim VenueConnectionQuery As New OleDb.OleDbCommand("SELECT VenueID, VenueName FROM Venues", VenueConnection)
Dim VenueDataAdapter As New OleDb.OleDbDataAdapter(VenueConnectionQuery)
Dim VenueDataSet As New DataSet
VenueDataAdapter.Fill(VenueDataSet, "Venues")
TrnVenueLst.DataSource = VenueDataSet.Tables("Venues")
TrnVenueLst.DisplayMember = "VenueName"
TrnVenueLst.ValueMember = "VenueID"
VenueConnection.Close()
End Sub
From there I called THIS sub on both the form AND the Add Venue window and I can safely see that this works. SO THAT is how you get a new value onto the form, don't use it as a part of the Load Event but rather call it from the load event block, then call it when you want to add to the list.