Obviously I cannot use strName in the Dictionary declaration line, but I'm just placing it there to represent what I'm trying to do. For example, if the User enters "carrot", I want the dictionary created to be named carrot. Is there a way to do this?
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim strName As String
strName = TextBox1.Text
Dim strName As New Dictionary(Of String, String)
End Sub
End Class
You can't. The name is useful for debugging and in reality the compiler will not use the name anyway - the name will be kept in the pdb file, nowhere else.
If you need to keep track of some dictionary by name, you could use another dictionary such as:
Private dictionaries As New Dictionary(Of String, Dictionary(Of String, String))()
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim strName = TextBox1.Text
Dim myNamedDictionary As Dictionary(Of String, String)
If dictionaries.ContainsKey(strName) Then
myNamedDictionary = dictionaries(strName)
Else
myNamedDictionary = New Dictionary(Of String, String)()
dictionaries.Add(strName, myNamedDictionary)
End If
' now you have a dictionary for the name you entered (carrot)
End Sub
To retrieve
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim carrotDictionary = dictionaries("carrot")
End Sub
I think this is as close as you will get.
You can, kind of. Using a compiler you can compile your own code, but the end result seems so unusable, I doubt this is what you want to do
Option Strict Off
Imports System.Reflection
Imports System.CodeDom.Compiler
Public Class Form1
Private dictionaryInstance As Object
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim strName = TextBox1.Text
Dim t = GetType(Form1)
Dim ns = t.Namespace
Dim provider = New VBCodeProvider()
Dim params = New CompilerParameters()
params.GenerateInMemory = True
params.ReferencedAssemblies.Add(Assembly.GetEntryAssembly().Location)
params.OutputAssembly = "OutputAssembly"
Dim code =
$"
Imports System
Imports System.Collections.Generic
Namespace {ns}
Partial Public Class DictionaryClass
Public {strName} As New Dictionary(Of String, String)
End Class
End Namespace"
Dim results = provider.CompileAssemblyFromSource(params, {code})
Dim assy = results.CompiledAssembly
Dim o As Object = assy.CreateInstance($"{ns}.DictionaryClass")
Me.dictionaryInstance = o
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
dictionaryInstance.carrot.Add("a", "b")
End Sub
End Class
Related
I am trying to pass the selected nodes from a treeview to another form that is displayed in the text boxes.
this is my code in TreeView1_NodeMouseDoubleClick event
the code works fine when the data from the selected treeview is shown in the same form, but the problem is when I want to pass it to the other form 4 nothing is shown and the debug shows me that if it receives the values but they are not reflected, maybe my code to refer to the other form is wrong I would like a support with this case.
Private Sub TreeView1_NodeMouseDoubleClick(ByVal sender As System.Object, ByVal e As System.Windows.Forms.TreeNodeMouseClickEventArgs) Handles TreeView1.NodeMouseDoubleClick
Dim nodeKey As String = TryCast(e.Node.Tag, String)
Dim form4 As New Form4
' Dim nodetext As String = TryCast(e.Node.Tag, String)
'Dim nodeKey As String = DirectCast(e.Node.Tag, String)
If nodeKey IsNot Nothing AndAlso nodeKey.StartsWith("DIST") Then
'You have double clicked a district node
Dim IDDISTRITO As Integer = Integer.Parse(nodeKey.Substring(4))
form4.lblco.Text = IDDISTRITO
'Do something with the district id here
'...
form4.txtdis.Text = e.Node.Text
form4.txtpro.Text = e.Node.Parent.Text
form4.txtdepa.Text = e.Node.Parent.Parent.Text
End If
End Sub
so I call form 3 where is the treeview
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim for3 As New Form3
for3.Show()
End Sub
As you assumed, yes you are referencing the forms incorrectly. Please follow this technique. In form3 class, declare a public variable Public Dim form4 As New Form4.
Then modify the form3 calling procedure like this:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim for3 As New Form3
for3.form4 = Me
for3.Show()
End Sub
Now modify your existing code to this :
Private Sub TreeView1_NodeMouseDoubleClick(ByVal sender As System.Object, ByVal e As System.Windows.Forms.TreeNodeMouseClickEventArgs) Handles TreeView1.NodeMouseDoubleClick
Dim nodeKey As String = TryCast(e.Node.Tag, String)
' Dim nodetext As String = TryCast(e.Node.Tag, String)
'Dim nodeKey As String = DirectCast(e.Node.Tag, String)
If nodeKey IsNot Nothing AndAlso nodeKey.StartsWith("DIST") Then
'You have double clicked a district node
Dim IDDISTRITO As Integer = Integer.Parse(nodeKey.Substring(4))
form4.lblco.Text = IDDISTRITO
'Do something with the district id here
'...
form4.txtdis.Text = e.Node.Text
form4.txtpro.Text = e.Node.Parent.Text
form4.txtdepa.Text = e.Node.Parent.Parent.Text
End If
End Sub
I have not tested the above code, but I believe you have got the idea.
Well I managed to solve it, the simplest thing was complicated, I publish the solution.
form 4 by calling 3
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim for3 As New Form3
AddOwnedForm(for3)
for3.ShowDialog()
End Sub
just add this code and voila
Dim form4 As Form4 = CType(Owner, Form4)
Have anyone idea why my code return "" inside my Textbox ? :-)
This i have in main Class
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim My_Thread as Threading.Thread
My_Thread = New Threading.Thread(AddressOf Module1.MyTest)
My_Thread.Start()
End Sub
And this in module1
Sub MyTest()
Dim TestingValue as string = "Test"
MainForm.Textbox1.Text = TestingValue
End sub
Invoke all time crash code and another try return "" inside texbox1 :-/
Create a Sub Class with public declarations to any object you want on MainForm, then pass the class as a parameter to the module. This would be a cleaner approach than passing the entire Form class instance. Then using the method that Jimi has suggested you can setyou textboxs without cross thread violation.
Public Class MainForm
Public Class PassToModule
Public TxBx1 As TextBox = MainForm.TextBox1
Public TxBx2 As TextBox = MainForm.TextBox2
End Class
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim PassToModule As New PassToModule
Dim My_Thread As Threading.Thread
My_Thread = New Threading.Thread(AddressOf MyTest)
My_Thread.Start(PassToModule)
End Sub
End Class
Module Module1
Dim FromMainForm As MainForm.PassToModule
Sub MyTest(PasToModule As MainForm.PassToModule)
FromMainForm = PasToModule
FromMainForm.TxBx1.BeginInvoke(New MethodInvoker(Sub()
FromMainForm.TxBx1.Text = "Test"
FromMainForm.TxBx2.Text = "Test"
End Sub))
End Sub
End Module
I'm declaring two strings into my main form this way:
Public Shared SerNum As String = vbNullString
Public Shared SKey As String = vbNullString
Then I give some values to them. After that, I open another form and I try to get values from the two variables but only SerNum preserves his value while SKey turns out to be Nothing.
I repeatedly checked my code but I didn't found a reason for this to happen.
The second form is showed immediatly after giving values.
What can I check to find the error?
At the moment I solved by using a Public Shared Dictionary(of String, String) and putting both strings into it, but I would like to understand where I'm wrong.
EDIT
I found the mistake: SKey was also declared into my sub so the value wasn't assigned to the Public Shared variable but to the local variable.
I thought I had 'commented' that row...
I have a proposition for acceding to your variable from other form :
In From main let's name it "From1" must be like :
Public Class Form1
Public SerNum As String = vbNullString
Public SKey As String = vbNullString
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim fr As New Form2(Me)
SerNum = "ValueNum"
SKey = "ValueKey"
fr.Show()
End Sub
End Class
In your seconde from "Form2" :
Public Class Form2
Dim fr As New Form1
Public Sub New(fr As Form1)
InitializeComponent()
Me.fr = fr
End Sub
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
MsgBox(fr.SKey)
MsgBox(fr.SerNum)
End Sub
I have built a basic VB app in the latest visual studio community. It's a simple app to load a text file into a list box then allow the list to be filtered down and finally the selected value to be copied.
It all works fine but I am curious, if I want to distribute this to other users I need to send them the text file (and the location is currently hard coded).
There has to be a better way to do this, do I need to import the text file as some sort of object in my project so it is then part of the project as opposed to a text file on its own?
Here is my code:
Public Class Form1
Dim MyArray() As String = My.Computer.FileSystem.ReadAllText("C:\Temp\Products.txt").Split(Environment.NewLine)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ListBox1.DataSource = MyArray
End Sub
Private Sub ListBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ListBox1.SelectedIndexChanged
TextBox2.Text = ListBox1.SelectedValue
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Clipboard.Clear()
Clipboard.SetText(TextBox2.Text)
End Sub
Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
Dim FilteredArray(0) As String
Dim ProdName As String
Dim X As Long = 0
ListBox1.DataSource = MyArray
For Each ProdName In ListBox1.Items
If InStr(UCase(ProdName), UCase(TextBox1.Text)) > 0 Then
ReDim Preserve FilteredArray(X)
FilteredArray(X) = ProdName
X = X + 1
End If
Next
ListBox1.DataSource = FilteredArray
End Sub
End Class
Any help is appreciated.
For completeness, here is my final solution:
Imports System.IO
Imports System.Reflection
Public Class Form1
Dim MyArray() As String
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Using sr As StreamReader = New StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream("WindowsApplication2.Products.txt"))
MyArray = Split(sr.ReadToEnd(), vbLf)
End Using
ListBox1.DataSource = MyArray
End Sub
Private Sub ListBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ListBox1.SelectedIndexChanged
TextBox2.Text = ListBox1.SelectedValue
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Clipboard.Clear()
Clipboard.SetText(TextBox2.Text)
End Sub
Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
Dim FilteredArray(0) As String
Dim ProdName As String
Dim X As Long = 0
ListBox1.DataSource = MyArray
For Each ProdName In ListBox1.Items
If InStr(UCase(ProdName), UCase(TextBox1.Text)) > 0 Then
ReDim Preserve FilteredArray(X)
FilteredArray(X) = ProdName
X = X + 1
End If
Next
ListBox1.DataSource = FilteredArray
End Sub
End Class
I think is a good way to store such file is resources of assembly.
Include your file into project. Set Build Action to Embedded Resource and then this file will be store inside the assembly.
How to read resource file from assembly you can find here: How to read embedded resource text file
The idea is simple, if I have a string value "ABCD" then with a ButtonClick event it should randomly reveal a char while others are hidden. i.e, "B*" another click would "AB**" and so on.
So far, my I have been stuck in a for loop.
For Each c As Char In x
y = Random.Next(0, x.IndexOf(c))
Next
I'm still learning VB.NET at this phase.
Public Class Form1
Private _indexes As Integer()
Private _currentIndex As Integer
Private _chars As Char()
Private _template As String
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim rnd = New Random()
_template = "ABCD"
' Create indexes that are randomly sorted
_indexes = Enumerable _
.Range(0, _template.Length) _
.OrderBy(Function(i) rnd.Next()) _
.ToArray()
'Create an array of chars with stars '****'.
_chars = New String("*"c, _template.Length).ToCharArray()
_currentIndex = 0
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
If _currentIndex < _template.Length Then
Dim index As Integer = _indexes(_currentIndex)
_currentIndex += 1
_chars(index) = _template(index)
Dim result As String = New String(_chars)
Label1.Text = result
End If
End Sub
End Class
I have already posted an answer where I focused on the algorithm. The algorithm code was directly integrated into a form. This works but is not a good practice. The code would be more reusable, more understandable and could be tested more easily if it was extracted to a separate class.
Public Class RandomTextRevealer
Private _indexes As Integer()
Private _currentIndex As Integer
Private _chars As Char()
Private _template As String
Private _result As String
Public Sub New(ByVal templateText As String)
Dim rnd = New Random()
_template = templateText
' Create indexes that are randomly sorted
_indexes = Enumerable _
.Range(0, _template.Length) _
.OrderBy(Function(i) rnd.Next()) _
.ToArray()
'Create an array of chars with stars '****'.
_chars = HiddenText.ToCharArray()
_currentIndex = 0
End Sub
Public Function RevealNext() As String
If _currentIndex < _template.Length Then
Dim index As Integer = _indexes(_currentIndex)
_currentIndex += 1
_chars(index) = _template(index)
_result = New String(_chars)
End If
Return _result
End Function
Public ReadOnly Property HiddenText() As String
Get
Return New String("*"c, _template.Length)
End Get
End Property
End Class
We can test the class like this in a little console application, without a form:
Module Programm
Public Sub Main()
Dim revealer = New RandomTextRevealer("Just a test")
Console.WriteLine(revealer.HiddenText)
For i As Integer = 1 To 12
Console.WriteLine(revealer.RevealNext())
Next
Console.ReadKey()
End Sub
End Module
Now we can integrate it in a form like this (I added a Reset-button, in order to be able to repeat the test with different random values):
Public Class Form2
Dim revealer As RandomTextRevealer
Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Reset()
End Sub
Private Sub btnReveal_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnReveal.Click
Label1.Text = revealer.RevealNext()
End Sub
Private Sub btnReset_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnReset.Click
Reset()
End Sub
Private Sub Reset()
revealer = New RandomTextRevealer("ABCD")
Label1.Text = revealer.HiddenText
End Sub
End Class
Now our form-code looks much cleaner.