I have a follow-on question about this question:
How to dynamically create a background worker in VB.net
I'm afraid I don't understand how DirectCast would solve my problem. I am creating an array of backgroundworkers: bWorker(0), bWorker (1), etc. each one creates a new form which is also in an array: page(0), page(1) etc.
The background workers need to 'know' their index number so that they can create the appropriate page (which is a form). As I mentioned before, I have found a system that works. I put the backgroundworkers' hashcodes in an array which I use to retrieve their index numbers. It just feels a bit clunky and maybe using DirectCast would be better but I don't understand how.
BackgroundWorker.RunWorkerAsync has two overloads. See BackgroundWorker.RunWorkerAsync(Object).
Now you can pass a variable and get it on BackgroundWorker.DoWork using DoWorkEventArgs.Argument.
Dim BackgroundWorker1 As New System.ComponentModel.BackgroundWorker
AddHandler BackgroundWorker1.DoWork, AddressOf BackgroundWorker_DoWork
Dim BackgroundWorker2 As New System.ComponentModel.BackgroundWorker
AddHandler BackgroundWorker2.DoWork, AddressOf BackgroundWorker_DoWork
' I'm going to pass integers, but you can pass whatever you want.
BackgroundWorker1.RunWorkerAsync(0)
BackgroundWorker2.RunWorkerAsync(1)
Private Sub BackgroundWorker_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs)
Select Case e.Argument
Case 0
' Form1
Case 1
' Form2
End Select
End Sub
I have found the solution. The problem I had with the e.Argument system was that it only applied to DoWork. I use RunWorkerCompleted to show the form created (if I try to show it with DoWork things go badly wrong). RunWorkerCompleted has no e.Argument property. My solution is to do this: e.Result = e.Argument in DoWork because e.Result is available in RunWorkerCompleted.
Related
I am working on a very old visual basic project. I have to rewrite the load and save function of the project. Therefore I wanted to create an array of controls which have all relevant textboxes and checkboxes included. I want to iterate through that array to be able to save the data into a textfile or load from it.
I have looked on the internet of how you can define those arrays, but it doesn't seem to work for me. Maybe I am doing something wrong, cause I am not an expert in Visual Basic.
I have tried to make it work this way:
Dim tbList As TextBox = { Form1.Text1, Form1.Text3, _
Form1.Text10, Form1.Text11, Form1.Text12, Form1.Text13, _
Form2.Text1, Form2.Text3, Form2.Text4, Form2.Text5, _
Form2.Text10, Form2.Text11, Form2.Text12, Form2.Text13, _
Form3.Text1, Form3.Text3, Form3.Text4, Form3.Text5, _
Form3.Text10, Form3.Text11, Form3.Text12, Form3.Text13, _
Form3.Text17, Form3.Text18, Form3.Text19, Form3.Text20, _
Form4.Text1, _
Form5.Text1, Form5.Text2, Form5.Text3, _
Form6.Text2, _
Form7.Text2}
Or with a list:
Dim tbList As New List(Of Controls)
The thing is Visual Basic always tells me there are some kind of compiling issues. There is no real explantation for this issue in VB, so I am asking here.
Your code isn't compiling because it is vb.net code. It should go without saying (but I'll say it anyway) that vb6 and vb.net are not the same thing.
If you want to use an array, you will have to dimension the array with a number that is one less than your number of textboxes (if I counted correctly there are 32 in your example):
'// array is zero based so 0 to 31 = 32 items
Dim tbList(31) As TextBox
tbList(0) = Form1.Text1
tbList(1) = Form1.Text3
'//...I'll leave the rest as an exercise for the programmer
tbList(31) = Form7.Text2
Dim i As Integer
Dim tb As TextBox
'// To loop and work with each textbox
For i = 0 To UBound(tbList)
Set tb = tbList(i)
'// do something with tb
Next
An easier way to do it, however, is to work with a collection:
Dim tbList As New Collection
tbList.Add Form1.Text1
tbList.Add Form1.Text3
'//...I'll leave the rest as an exercise for the programmer
tbList.Add Form7.Text2
Dim tb As TextBox
'// To loop and work with each textbox
For Each tb In tbList
'// do something with tb
Next
Yes, you can use a collection if you want to go to the trouble. But an even easier way to work with it is to use VB6's (now obsolete) control array implementation. Most of us were disappointed when we found it was no longer available in .Net!
All you have to do to get control arrays in VB6 is create a bunch of controls with the same name. (They do have to be the same type of control; you can't make arrays of, say, text boxes and combo boxes.) Start with one text box, name it what you want, and copy it. You will be asked if you want to create a control array. Say yes, copy as many as you want. You will notice that the Index property is no longer blank, starting with 0 and incrementing from there. You will also notice that all of the event handlers have an "Index As Integer" argument to them. This way, you can use the same event handler for all of them, evaluating the Index argument to find out which member of your array is firing the event.
Here is the old doc for it. Microsoft makes it hard to find. :)
I'm new to creating user forms in VBA. I've been using VBA macros for a while now though so I understand some about them. Right now I'm creating a spreadsheet for a user where I'm using a user form with a list box. I have a lot of code in a regular module and need to refernce the module to fill the listbox. What I have right now is this:
Private Sub StartButton_Click()
Dim Number
Call GetTellerNames
For Number = 0 To 40 Step 1
If GetTellerNames(Number) <> "" Then
ListBox1.AddItem (GetTellerNames(Number))
End If
Next
End Sub
When I run this I get an error saying
Sub of Function not defined
How do I fix this so that I can use the array in my module to fill the list box? I've already got the code to fill the array working.
Here is the code for the GetTellerNames sub in the module:
Private Function GetTellerNames()
GetTellerNames = FindOthers(BranchNumber, TellerCode, 2)
End Function
It is using global variables that are set in other parts of the code. I can post all of the code if necessary.
Since the GetTellerNames() code lies within a standard module you need to change the access modifier to public in order to be able to access that method/sub from the UserForm1 object module.
I’m new to Visual Basic 6, so please be patient (and thorough with your answers).
I’m building a form and I need to check if the information entered in one of its fields is numeric, otherwise the program has to beep.
The field is part of an array of controls and it is named txtMyField(0)
Last thing in my code I’ve written:
Private Sub txtMyField_Change(Index As Integer)
If Not IsNumeric(txtMyField(0).Text) Then
Beep
End If
End Sub
I don’t know if this code is correct and I don’t how to call the Sub to use it in order to check the field’s value before inserting in database.
Thanks a lot for your help!
You can do this by using the Validate event. You need to ensure that the CausesValidation property is true, if it is then the Validate event will be raised for that control.
Your event might look something like this:
Private Sub txtMyField_Validate(Index As Integer, Cancel As Boolean)
If Not IsNumeric(txtMyField(Index).Text) Then
Beep
Cancel = True
End If
End Sub
This would ensure that all the controls in your control array are numeric (given that their CausesValidation property is set to True at startup). If one of the controls is empty or contains non-numeric characters you will get a Beep when the control loses focus.
Note some things here
Sounding a Beep is not really a good way to indicate a validation error. A messagebox or textbox in the form to display the error is usually a better way. The user may not hear your beep or may not understand that "a beep" means "you need to provide a number in this field".
Your code referenced control with index = 0. The event may fire for any of the controls in the control array, so checking the value of control(0) is not really a logical thing to do when you should be validating control(5) (for example).
instead of beeping you could also make your texbox only accept certain keys
for example a textbox which will only accept numeric keys and the backspace key :
Private Sub Text1_KeyPress(KeyAscii As Integer)
KeyAscii = NrOnly(KeyAscii)
End Sub
Private Function NrOnly(intKey As Integer)
Dim intReturn As Integer
intReturn = intKey
Select Case intKey
Case vbKeyBack
Case vbKey0 To vbKey9
Case Else
intReturn = 0
End Select
NrOnly = intReturn
End Function
you can add more intelligence to the NrOnly function to allow more keys, or check for certain boundaries
be careful though as the user can still use the mouse to input other data via copy&paste
i am trying to convert Vb.net To C#.net. could any one please help me to find the Equivalent C# coding for Dim dataTable As DataTable = CType(sender, GridView).DataSource.
and also,any tip for soring datas in data gridview.
thanks
You mean like this?:
DataTable dataTable = ((GridView)sender).DataSource;
To cast types in C#, you put the type in parentheses before the value:
(GridView)sender
Then, to access properties on it, you'll want to wrap the whole thing in parentheses:
((GridView)sender).DataSource
(This is because otherwise you'd be trying to call .DataSource on the un-cast sender which would fail.)
Then to declare a value (the variable that you're assigning), the standard syntax is to specify the type and then the variable name:
DataTable dataTable
(I highly recommend using a better variable name, by the way. C# is case-sensitive, so this is valid. But it's unintuitive at best.)
In C# you can also use the var keyword to infer the type, often resulting in cleaner code:
var dataTable = new DataTable();
This only works if there's an inferrable type from the right side of the assignment. Since the DataSource property isn't specifically of type DataTable then you don't want to use var in this particular case, since it would result in an Object (which isn't what you're looking for). But it can be used in cases like my last example above this paragraph where you don't want to repeat the type name twice in the same line of code.
DataTable dataTable = ((GridView)sender).DataSource
Regarding sorting in a GridView, see Sorting Data in a GridView Web Server Control, then post a question with what you have tried if you're having problems.
I'm trying to ReDim a member object array from a different class. For example:
Class1.cls
Dim mStuffArray() As New clsStuff
Property Get StuffArray() As clsStuff()
StuffArray = mStuffArray
End Property
Class2.cls
Private Sub Foo(ByRef pClass1 As Class1)
Dim tStuffArray() As clsStuff
tStuffArray = pClass1.StuffArray
ReDim tStuffArray(1 To 2)
End Private
The problem here is that Foo doesn't seem to be ReDim'ing the member mStuffArray in Class1. Any idea what I'm doing wrong? Forgive me if my VB6 looks odd or the naming conventions aren't standard, I had to dive into some old legacy code and am new to VB6
Dave
Redim doesn't make a copy of the array.
I think it's more likely that 4eturning the array from a property get creates a copy. The docs aren't very clear. http://msdn.microsoft.com/en-us/library/aa261343(VS.60).aspx
It would be simpler to use a Public member variable. And why not use a Collection rather than an array?
I've never looked into VB6, but if I were to take a guess, I think when you use ReDim, it creates a copy of the existing Array and changes tStuffArray to point to the new copy. However, pClass1.mStuffArray still references the old array.
The documentation for ReDim states that "ReDim creates a new array, copying all the elements from the existing array"
I would recommend adding a method to to Class1 that performs ReDim on the private mStuffArray variable.
Dim mStuffArray() As New clsStuff
Property Get StuffArray() As clsStuff()
StuffArray = mStuffArray
End Property
Sub Foo()
ReDim mStuffArray(1 To 2)
End Sub
Hopefully this works. As I said, I'm not a VB6 programmer, so I may be off on this.
You might also want to consider the Dictionary object.