Accessing controls located in a dynamically created user control vb.net - vb.net

I am a casual programmer with not a lot of experience. I am happy I have made it this far on my own (with help of course from this site and others like it). But now I need some help.
I have created a user control with several text boxes, masked text boxes, combo boxes, a check box and 3 buttons.
I have created a form (Form1) with a tab control (TabControl1) that has 1 tab page on it (TabPage1). I have added my user control to TabPage1 and the control assumes the name ContactTab1. This was done through the VB.net form design, not by code.
When I run my form I have code so that when I click on my add button, it adds another tab with my user control added to it (no matter which tab I may be on). It works great, I can add as many tabs as I want. When I click on my edit or delete button, they work great in the sense that I know which tab the button is on when it gets clicked. My problem is when I click the edit button I need to set ckbDeleteContact.Checked = False and ckbDeleteContact.Visible = False on the tab that the button was clicked. When I click the delete button I need to set ckbDeleteContact.Checked = True and ckbDeleteContact.Visible = True on the tab that the button was clicked. I can access the check box on the first tab without a problem with the statement ContactTab1.ckbDeleteContact.Checked = False.
So my question is, how do I access all these text boxes, masked text boxes, combo boxes, and my check box on these dynamically added controls? Below is my code for Form1 and I have commented out what I need working:
Public Class Form1
Private intTabPage As Integer = 1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
TabPage1.Text = "Contact #" & intTabPage
ContactTab1.ckbDeleteContact.Checked = False
ContactTab1.ckbDeleteContact.Visible = False
TabPage1.Name = "TabPage" & intTabPage
intTabPage = intTabPage + 1
End Sub
Private Sub UC_btnAddContact_Click() Handles ContactTab1.UC_btnAddContact_Click
AddNewTab()
End Sub
Private Sub UC_btnEditContact_Click() Handles ContactTab1.UC_btnEditContact_Click
'**DEBUG: See which tab the button is on when clicked
MessageBox.Show("The edit button from the following tab was clicked: " & TabControl1.SelectedTab.Name() & vbCrLf & "The edit button on the following contact tab was clicked: " & TabControl1.SelectedTab.Controls.Item(0).Name(), "Check", MessageBoxButtons.OK, MessageBoxIcon.Information)
'This code is what needs to work. ContactTabObject would have naming convention "ContactTabX" where X = the tab # 1 through the highest tab #
'ContactTabObject.ckbDeleteContact.Checked = False
'ContactTabObject.ckbDeleteContact.Visible = False
End Sub
Private Sub UC_btnDeleteContact_Click() Handles ContactTab1.UC_btnDeleteContact_Click
'**DEBUG: See which tab the button is on when clicked
MessageBox.Show("The delete button from the following tab was clicked: " & TabControl1.SelectedTab.Name() & vbCrLf & "The delete button on the following contact tab was clicked: " & TabControl1.SelectedTab.Controls.Item(0).Name(), "Check", MessageBoxButtons.OK, MessageBoxIcon.Information)
'This code is what needs to work. ContactTabObject would have naming convention "ContactTabX" where X = the tab # 1 through the highest tab #
'ContactTabObject.ckbDeleteContact.Visible = True
'ContactTabObject.ckbDeleteContact.Checked = True
End Sub
Function AddNewTab()
Dim NewTab As New TabPage
Dim NewContactTab As New ContactTab
TabControl1.Controls.Add(NewTab)
TabControl1.SelectTab(NewTab)
NewTab.Text = "Contact #" & intTabPage
NewTab.BackColor = System.Drawing.Color.Transparent
NewTab.Controls.Add(NewContactTab)
NewTab.Name = "TabPage" & intTabPage
NewContactTab.Location = New System.Drawing.Point(6, 6)
NewContactTab.BackColor = System.Drawing.Color.Transparent
NewContactTab.ckbDeleteContact.Checked = False
NewContactTab.ckbDeleteContact.Visible = False
AddHandler (NewContactTab.btnAddContact.Click), AddressOf UC_btnAddContact_Click
AddHandler (NewContactTab.btnEditContact.Click), AddressOf UC_btnEditContact_Click
AddHandler (NewContactTab.btnDeleteContact.Click), AddressOf UC_btnDeleteContact_Click
NewContactTab.Name = "ContactTab" & intTabPage
intTabPage = intTabPage + 1
End Function
End Class
Once I get this figured out, I should be good to go and I should be able to get the rest on my own. In case you are wondering, I will also be filling in the options for my combo boxes with data from a database. I will then be using the form to take all the data in it and either adding, editing, or deleting the information from a database.
Thanks in advance.

As #HansPassant said you just need to add properties to your user control to get access to your controls in it. I'm not a vb.net guy, but I think this is going to help you:
Public Function MyTextbox() As System.Windows.Forms.TextBox
Return Textbox1
End Function
You can write this in your user control code.

Ok, maybe I was not the clearest in my post or I just don't understand the encapsulation thing. I can access all my controls since they are standard controls. I just needed to know how I could get the name of the parent control, which in this case is the user defined control named ContactTabX where X = 1 through n controls that were added when I pressed my add button n times. I could always access them by saying something likeContactTab5.ckbDeleteContact.Visible = True or whatever. I did not want to hardcode since I would not be sure how many tabs were added so I wanted a way to know which tab I was on when the button was pressed that way I could change that check box property on that particular tab (since every tab is identical).
I spent hours trying to figure it out and well here is what I was able to figure out about 10 mins after posting the question (go figure). I hope this helps anyone else. And for you experts out there, any feedback is appreciated on my solution. I always like to learn :)
So replacing the subs I originally posted with these worked perfectly.
Private Sub UC_btnEditContact_Click() Handles ContactTab1.UC_btnEditContact_Click
'**DEBUG: See which tab the button is on when clicked
'MessageBox.Show("The edit button from the following tab was clicked: " & TabControl1.SelectedTab.Name() & vbCrLf & "The edit button on the following contact tab was clicked: " & TabControl1.SelectedTab.Controls.Item(0).Name(), "Check", MessageBoxButtons.OK, MessageBoxIcon.Information)
Dim Contact As ContactTab = TabControl1.SelectedTab.Controls.Item(0)
Contact.Name = TabControl1.SelectedTab.Controls.Item(0).Name()
Contact.ckbDeleteContact.Visible = False
Contact.ckbDeleteContact.Checked = False
Contact = Nothing
End Sub
Private Sub UC_btnDeleteContact_Click() Handles ContactTab1.UC_btnDeleteContact_Click
'**DEBUG: See which tab the button is on when clicked
' MessageBox.Show("The delete button from the following tab was clicked: " & TabControl1.SelectedTab.Name() & vbCrLf & "The delete button on the following contact tab was clicked: " & TabControl1.SelectedTab.Controls.Item(0).Name(), "Check", MessageBoxButtons.OK, MessageBoxIcon.Information)
Dim Contact As ContactTab = TabControl1.SelectedTab.Controls.Item(0)
Contact.Name = TabControl1.SelectedTab.Controls.Item(0).Name()
Contact.ckbDeleteContact.Visible = True
Contact.ckbDeleteContact.Checked = True
Contact = Nothing
End Sub
Thanks again for the input.

Related

How can I force a navigation control to refresh?

In my Clients form I have 2 textboxes (tbHHName, and tbHHID) and a navigation control (nav) displaying subforms/subreports.
When the user clicks tbHHName, a modal form opens to select which client to view.
Before switching clients, the form shows:
tbHHName: Client123
nav: Account1, Account2, Account3
After switching to Client456, here's what it displays:
tbHHName: Client456
nav: Account1, Account2, Account3
Here's what it should be displaying:
tbHHName: Client456
nav: Account4, Account5, Account6
After the user clicks on one of the nav tabs it displays correctly, but I can't figure out how to force refresh the nav control without that click. Any advice would be very much appreciated.
All of the nav's subforms/subreports have the NavigationWhereClause set to: "[HH_ID] = tbHHID"
Below is the Form_Load, and the tbHHName_Click subs
Private Sub Form_Load()
On Error Resume Next
'Set form recordsource
Me.RecordSource = "SELECT * FROM _HOUSEHOLDS WHERE HH_ID = " & GetSetting(AppName, Reg_JBGeneral, Reg_HH_ID, 0)
'Apologize to users
MsgBox "Please click on the Holdings tab again to refresh the data." & vbNewLine & _
" Sorry for the extra click," & vbNewLine & _
" -MaybeOn8", , AppName
End Sub
Private Sub tbHHName_Click()
On Error Resume Next
'open the form that sets new HH_ID value using the SaveSetting method
DoCmd.OpenForm "Households_Select", WindowMode:=acDialog
Form_Load
End Sub
Thanks in advance, SO
I tested with UNBOUND combobox sitting on main form to select filter parameter and NavigationWhereClause has criteria expression HH_ID=Forms![NavForm]!Combo9. Code in combobox AfterUpdate event:
Forms![NavForm]!NavigationSubform.Requery
Then I tested with code to change value of combobox and requery.
Forms!NavForm.Combo9 = 17
Forms!NavForm.NavigationSubform.Requery
This all works and does not involve changing RecordSource. Now just decide where to place code that changes control's value and requery subform.
Also, can use DoCmd.BrowseTo method to set focus on particular Navigation tab.
Found a fix. I tacked this onto the end of the Form_Load sub:
Forms("Households").NavigationSubform.Report.FilterOn = False
Forms("Households").NavigationSubform.Report.FilterOn = True
Even though there are mixed subforms and subreports in the navigation control, everything seems to load fine.

Change the visibility of a panel (Windows Forms)

I leave it to you because I can't find a solution to my problem : /
Let me explain, when I press a button I display a panel containing other buttons, at the click of one of the buttons on the panel it should launch a method that will convert the selected files to pdf. As soon as the user has clicked on one of the buttons and confirmed the choice of file, I make my panel invisible and I then launch the conversion method.
The problem is that my panel disappears let's say by half (not entirely) because it launches the conversion method as quickly. I told myself that I was going to go through a secondary thread, however I cannot modify graphic elements on the second thread.
There is my code :
Private Sub PBFolder_Click(sender As Object, e As EventArgs) Handles PBFolder.Click
Try
Insert2Db("Debut de la fonction BTransforme_Click " + Environment.UserName.ToString, 1, 0, "ConvertFiles2PDF")
'Log("Debut de la fonction BTransforme_Click")
Dim OFD As New FolderBrowserDialog
If OFD.ShowDialog = Windows.Forms.DialogResult.OK Then
PanFileFolder.Visible = False
ConvertFileFolder(False, OFD.SelectedPath.ToString)
End If
Catch ex As Exception
'Log("Error " + ex.Message)
Insert2Db("Error " + ex.Message + "User : " + Environment.UserName.ToString, 0, 3, "ConvertFiles2PDF")
Finally
Insert2Db("function BTransforme_Click Terminé " + Environment.UserName.ToString, 1, 0, "ConvertFiles2PDF")
'Log("function BTransforme_Click Terminé")
End Try
LAppOne.Visible = True
GifLoad.Visible = False
Button1.Enabled = True
BLog.Enabled = True
End Sub
As you can see I hide my panel thanks to line: PanFileFolder.Visible = False then I launch my conversion method convertFileFolder (False, OFD.SelectedPath.ToString)
I have put 2 images to illustrate my problem.
the 1st image shows you the panel that appears on click:
the second image shows you the problem that this causes me to choose the folder:
When it has finished converting the files, the panel disappears correctly at this time.
Do you have an idea to solve this problem thank you in advance ;)
I told myself that I was going to go through a secondary thread,
however I cannot modify graphic elements on the second thread.
That is exactly what will fix your problem; ConvertFileFolder() needs to be running in a different thread so that GUI can refresh itself and be responsive to user interact. You can update the GUI from that secondary thread using Invoke() calls.
Here I've added Async to the Button click handler, then we Await the ConvertFileFolder() FUNCTION, which now returns a Task:
Private Async Sub PBFolder_Click(sender As Object, e As EventArgs) Handles PBFolder.Click
' ... other code ...
Using OFD As New FolderBrowserDialog
If OFD.ShowDialog = DialogResult.OK Then
PanFileFolder.Visible = False
Await ConvertFileFolder(False, OFD.SelectedPath.ToString)
End If
End Using
' ... other code ...
End Sub
Public Function ConvertFileFolder(ByVal someFlag As Boolean, ByVal someString As String) As Task
Return Task.Run(Sub()
' ... long running code in here ...
For i As Integer = 1 To 10
System.Threading.Thread.Sleep(1000) ' some "work"
' whenever you need to update the GUI, use Invoke()
Dim value As String = i.ToString
Me.Invoke(Sub()
Label1.Text = value
End Sub)
Next
End Sub)
End Function

Checkedlistbox: uncheck items and re-run action upon new selection

I have a checkedlistbox1 which is filled through a search function with a folderbrowserdialog. Once I check one item (=XML file) it fills a listbox according to certain nodes by calling a separate class. This works fine.
What I want it to do next is when I select another item in checkedlistbox1 it unchecks the previously checked item and again runs the separate class to display the nodes of the newly selected item.
My code is a blur of tries according to other searches I've made. Please take note of what I want it to do, this is not like I have my code now because I don't want it to throw an error when I select another item. I just want it to de-select the previous and perform the action again on the newly selected item.
I hope someone can help me out on this one.
code:
Try
Dim checkLstBox As CheckedListBox = CType(sender, CheckedListBox)
Dim targetNum As Integer = 1
If e.NewValue = CheckState.Checked AndAlso checkLstBox.CheckedItems.Count + 1 > targetNum Then
Call ClsMessageBoxes.CheckedListbox1_maxcheck_Form2()
e.NewValue = CheckState.Unchecked
For i As Integer = 0 To f5.CheckedListBox1.Items.Count - 1
f5.CheckedListBox1.SetItemChecked(i, False)
Next 'This part at least throws an error if I select a new item in checkedlistbox1 and de-selects the previous item'
Else
'this part does not work'
f5.ListBoxDestPlate.Items.Clear()
f5.CheckedListlistbox2.SelectedItems.Clear()
'this part is meant to select an item in another checkbox according to certain tekst in the filename'
Dim i As Integer
If ClsSharedProperties2.filePath2.Contains("Text1") Then
i = 1
f5.Checkedlistbox2.SetItemChecked(i, True)
Call ClsScan.scanning2()
ElseIf ClsSharedProperties2.filePath2.Contains("Text2") Then
i = 2
f5.Checkedlistbox2.SetItemChecked(i, True)
Call ClsScan.scanning2()
End If
End If
Catch ex As Exception
MessageBox.Show(ex.Message & vbCrLf & "Stack Trace: " & vbCrLf & ex.StackTrace)
End Try
Your code is a bit messy with references to other forms I'm guessing (f5? ClsScan?).
In general, this code will work with the checked item and uncheck any existing items:
Private Sub clb_ItemCheck(sender As Object, e As ItemCheckEventArgs) Handles clb.ItemCheck
If e.NewValue = CheckState.Checked Then
For Each i As Integer In clb.CheckedIndices
clb.SetItemChecked(i, False)
Next
MessageBox.Show("Checked " & clb.Items(e.Index).ToString)
End If
End Sub
The MessageBox line would be replaced with you passing the item reference to whatever function or method you need to do your filtering.
One thing to note regarding the ItemCheck event is that the item in the collection isn't actually checked yet. That is why you would have to rely on the e.Index value.

Making a form that users enter a value into text boxes a certain number of times

I have a series of text boxes that are hidden, except one which users enter a value into. After a button is pressed, this text box disappears and the rest appear. From there, I want users to be able to enter different values into each text box. These values will be saved as variables. From there, users press a button and enter new values into the text boxes, until values have been entered into the text boxes for each number up to the first value entered into the hidden text box.
I'm not sure how else to explain this, but please let me know if you have any questions.
Correct me if im wrong. i think you want an input in different textbox?
Like textbox1 = 1, textbox2 = 2 and so on. If this is right then try this.
Lets try this to your 3 textbox for an example.
Private Sub Button_Click(sender As Object, e As EventArgs) Handles Button.Click
If TextBox1.Visible = True Then
If Trim(TextBox1.Text) <> "" Then
TextBox1.Visible = False
TextBox2.visible = True
Else
MsgBox("Required")
'or user error provider.
End If
Exit Sub
End If
If textbox2.visible = True Then
If Trim(TextBox2.Text) <> "" Then
TextBox2.Visible = False
TextBox3.visible = True
Else
MsgBox("Required")
'or user error provider.
End If
Exit Sub
End If
'and so on
End Sub
hope this is what you want. just basic but maybe usefull :)
This is the workflow of what you want to accomplish in JavaScript. VB.Net has similar functions to Visibility. https://msdn.microsoft.com/en-us/library/ms748821(v=vs.85).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-2
In the visual editor you can create buttons and add Click events to them, this is basic so I won't tell you how to do it. Google if you can't.
var options = document.getElementsByClassName("options");
var optionsSetOne = document.getByClassName('optionsSetOne');
This will select all your options. Now that you have all your options selected and in a variable called options you can play around with the visibility, as the user progresses thought the buttons.
First I would set all my options to hidden with:
options.style.visibility = 'hidden';
After the users progresses and clicks the button, I will make the first set of the options visible. With:
$('#buttonOne').click(function(){
optionsSetOne.style.visibility = 'visible';
});
This is the basic workflow of what you want to accomplish, you have to figure out how to save all the information the user gives to you.

How to remove textboxes on button click (vb.net)?

I am not knowing about how to delete textboxes on the click of a button in my Windows form.
Here is my story:
Initially, I wanted to add textboxes on the click of a button, and upon searching the net, I was able to find out, on this forum, how to do this. https://stackoverflow.com/questions/15461978/adding-new-textbox-with-button-click
I used the code that user "Rajaprabhu Aravindasam" (2nd answer) gave. Here is only part of my code that I used (in order not to confuse you):
Private Sub Button_AddTask_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button_AddTask.Click
count += 1
TabPage_TaskStructure.Controls.Add(New Label() With _
{.Name = "Label_Task" & count})
TabPage_TaskStructure.Controls.Add(New RichTextBox() With _
{.Name = "RichTextBox" & count})
End Sub
Now, as you can see, the purpose of the button 'Button_AddTask" ('+' button on my form) is to create rich textboxes and their respective label. Assume that the rich textboxes and the labels are being created below one another.
Beside the '+' button, there is a '-' button. What I want is to use this '-' button to delete all created textboxes sequentially up. That is, if I have created 4 textboxes with the button '+', textbox no.4 will be deleted first when I click the '-' button, then no. 3 after a second click, then no.2 after a third click and so on.
The sequential part is not a problem, I know perfectly how to do it. Here is part of the code I tried:
Private Sub Button_DeleteTask_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button_DeleteTask.Click
TabPage_TaskStructure.Controls.Remove(New Label() With _
{.Name = "Label_Task" & count})
TabPage_TaskStructure.Controls.Remove(New RichTextBox() With _
{.Name = "RichTextBox" & count})
count -= 1
If count = 1 Then
Button_DeleteTask.Visible = False
End If
End Sub
What I did, logically, was simply replace 'Add' with 'Remove', but I am not knowing with what to replace 'New'. And so my question is: What needs to be used instead of 'New'? If I need to use an entirely different code, please do tell me.
Any help is greatly appreciated.
Update:
Ok, I have done some research since I've asked this question and I've been able to deduce that the removal of the controls (Label & Rich Text Box) can be done by using a For Each loop. In my code for the '-' button, I have replaced the first 4 lines of code with this:
Dim Ctrl As Control
For Each Ctrl In TabPage_TaskStructure.Controls
If TypeOf Ctrl Is Label And Ctrl.Name = "Label_Task" & count Then
TabPage_TaskStructure.Controls.Remove(Ctrl)
ElseIf TypeOf Ctrl Is RichTextBox And Ctrl.Name = "RichTextBox" & count Then
TabPage_TaskStructure.Controls.Remove(Ctrl)
End If
Next
And so, when I click the '-' button, the program checks whether each control on the tab page (TabPage_TaskStructure) is a label with the name ("Label_Task" & count') or a rich text box with the name ("RichTextBox" & count), and if they are, they will be removed. The rest of the code is the same.
It's working, however not completely. It's working for the labels as they are successfully being removed, but not for the rich text boxes. I cannot understand why. I have tried the code for other controls such as date time pickers and text boxes, and it's not working for any of these either. It seems to be working for labels only.
Also, I have tried using the code on a default rich text box, and it worked! But for rich text boxes being created at run time, it's not working.
Can anyone clarify me on this?
I'm not really good at vb but from simple logic if and when an "IF" argument is accepted the code will move to "End If" and skip "Else" altoghter.
Try this instead:
Dim Ctrl As Control
For Each Ctrl In TabPage_TaskStructure.Controls
If TypeOf Ctrl Is Label And Ctrl.Name = "Label_Task" & count Then
TabPage_TaskStructure.Controls.Remove(Ctrl)
End If
If TypeOf Ctrl Is RichTextBox And Ctrl.Name = "RichTextBox" & count Then
TabPage_TaskStructure.Controls.Remove(Ctrl)
End If
Next