Question button object from variable, buttonx

holdenz

New member
Joined
Feb 24, 2010
Messages
4
Programming Experience
1-3
Ok, new to vb.net and I want to create a basic app that reads the contents of an xml file (this part works) and then enable (make visible) the required number of buttons (already created on the form but set as not visible by default) for each line of the xml file.

The xml file just lists a program name (which would become the button text) and the path to the file (which should be stored as a variable that is used in the button code (handle?)

The idea is that I have an app that once created, I just update the xml file with new drivers or programs that I want to install or run without having to rebuild the application.

VB.NET:
Imports System.IO
Imports System.Xml
Imports System

Public Class Form1
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Dim idx = 1
        Dim settings As New XmlReaderSettings()
        settings.IgnoreComments = True
        Dim XMLfile As String = Application.StartupPath & "_AutoStart\config.xml"
        Using reader As XmlReader = XmlReader.Create(XMLfile, settings)
            While (reader.Read())
                If (reader.NodeType = XmlNodeType.Element And "name" = reader.LocalName) Then

                    Dim NameValue = reader.ReadElementString("name")
                    Dim PathValue = reader.ReadElementString("path")

                    Dim button_x = "Button" & idx
                    button_x.Text = NameValue
                    button_x.Visible = True

                    Dim button_xPath
                    button_xPath = PathValue

                    idx = idx + 1
                    'MsgBox(NameValue & " " & PathValue)
                End If
            End While
        End Using
    End Sub


    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        System.Diagnostics.Process.Start(button_xPath)

    End Sub
End Class

As you would see the line "button_x.Text = NameValue" is not allowed, same with the line below it. I am trying to go from button1 to button2 etc for each line that is read.

The next item that I have a problem with is passing a variable to another sub routine. For example having the button_xPath created within the formload routine and then not passed down to the button1 code. I would have code for each button on the form but want to use the variable to store the path to the file that should be run.

Any help or suggestions would be great.

Cheers

Baz.
 
If you do something like
Dim Button_X = SomeString
then Button_X becomes a variable with type string

To create a "Button", you do
Dim bt As NEW Button
bt.text = "Hello World"

You have to add the button to the Form (or any other container that is itself inside the form):
Me.Controls.Add(bt) or JustAControl.Controls.Add

To dynamically add event handling (like what happens if the button is clicked), you use AddHandler:
AddHandler bt.click AddressOf ASubWithTheCorrectSignature

To store additional infos (like a path of an exe that should run, when the button is clicked), you could use the .Tag property which is of type object and therefore can store almost everything.
bt.Tag = "PathToFile"

Sample-Code:
VB.NET:
Public Class Form1

    Private Sub ButtonClickHandler(ByVal sender As Object, ByVal e As System.EventArgs)

        If sender IsNot Nothing AndAlso TypeOf sender Is Button Then
            Dim b As Button = DirectCast(sender, Button)
            If b.Tag IsNot Nothing AndAlso TypeOf b.Tag Is System.String Then
                ' run the app that is defined in .Tag
                Process.Start(b.Tag)
            End If
        End If

    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Dim b As Button

        b = New Button
        b.Text = "Run A.exe"
        b.Tag = "C:\a.exe"
        AddHandler b.Click, AddressOf ButtonClickHandler
        Me.Controls.Add(b)

        b = New Button With {.Text = "Run B.exe", .Tag = "C:\b.exe"}
        AddHandler b.Click, AddressOf ButtonClickHandler
        Me.Controls.Add(b)

    End Sub
End Class
 
a step further

Thanks picoflop

That works great for the first line of the xml file but I don't see how I can add any extra buttons as b = button there is no way that I can then say c = button (automatically) which is what I was trying to do with the idx variable and adding 1 to it each time a line within the xml file is read so that I would end up with b1, b2, b3 etc but I see what you mean that it turns it into a string.

Anyone know of a method to work around/solve this?

An example of the xml file...

<?xml version="1.0" encoding="iso-8859-2" standalone="no"?>
<!--Store configuration data-->
<SOFTWARE>
<name>chipset</name><path>_Drivers\_5500 MB's\intel_chipset_v9.1.1.1025\Setup.exe</path>
<name>NIC_2K8_x64</name><path>_Drivers\intel-lan_msft_v14.7_whql\W2K8-Vista_x64_Install.bat</path>
<name>NIC_2K8_R2_x64</name><path>_Drivers\intel-lan_msft_v14.7_whql\W2K8_R2-Win7_x64_Install.bat</path>
</SOFTWARE>

Many thanks for the quick response.

Cheers

Baz
 
Baz - I suggest you turn Option Strict On.

You can also shorten:-

VB.NET:
idx = idx + 1

to

VB.NET:
idx += 1
 
how I can add any extra buttons as b = button there is no way that I can then say c = button (automatically)
is not required!

dim b as button
for i = 1 to 10
b = new button
me.controls.add(b)
next i

Now you have 10 "different" Buttons on the form.
 
Only one button is displayed with example code

I see what you mean now.

However when I use your example code (without changing anything), there is only one button displayed on the form with text of "Run A.exe" so the second button is not displayed.

With your changes my code now looks like the following: (I use the msgbox to show me what variables are being used as a check).

VB.NET:
Imports System.IO
Imports System.Xml
Imports System

Public Class Form1

    Private Sub ButtonClickHandler(ByVal sender As Object, ByVal e As System.EventArgs)

        If sender IsNot Nothing AndAlso TypeOf sender Is Button Then
            Dim b As Button = DirectCast(sender, Button)
            If b.Tag IsNot Nothing AndAlso TypeOf b.Tag Is System.String Then
                ' run the app that is defined in .Tag
                MsgBox(b.Tag)
                Process.Start(b.Tag)
            End If
        End If

    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Dim settings As New XmlReaderSettings()
        settings.IgnoreComments = True
        Dim XMLfile As String = Application.StartupPath & "_AutoStart\config.xml"
        Using reader As XmlReader = XmlReader.Create(XMLfile, settings)
            While (reader.Read())
                If (reader.NodeType = XmlNodeType.Element And "name" = reader.LocalName) Then

                    Dim NameValue = reader.ReadElementString("name")
                    Dim PathValue = reader.ReadElementString("path")

                    Dim b As New Button
                    b = New Button With {.Text = NameValue, .Tag = PathValue}
                    AddHandler b.Click, AddressOf ButtonClickHandler
                    Me.Controls.Add(b)
                    b.Visible = True

                    MsgBox(NameValue & " " & PathValue)
                    MsgBox("button text " & b.Text & " " & "Path " & b.Tag)

                End If
            End While
        End Using
    End Sub
End Class

If we could get the other buttons to be displayed then the app will work as I had expected.

Many thanks for your assistance.

Kind regards

Barry.
 
there is only one button displayed on the form with text of "Run A.exe" so the second button is not displayed.
Believe me: It IS displayed.

Unfortunately (in my sample) all buttons have the same size and same LOCATION. So one sits on the other and you can only SEE the topmost button ;)
The solution is easy ...
 
Unfortunately (in my sample) all buttons have the same size and same LOCATION. So one sits on the other and you can only SEE the topmost button ;)
The solution is easy ...
Yes, use a FlowLayoutPanel as container for the buttons.
 
Fantastic

Way cool, thanks for that. I've updated my coe with the following and while the way I have layed out the buttons might not be the best, it works and I can now spend some time to make it look better.

VB.NET:
Imports System.IO
Imports System.Xml
Imports System

Public Class Form1

    Private Sub ButtonClickHandler(ByVal sender As Object, ByVal e As System.EventArgs)

        If sender IsNot Nothing AndAlso TypeOf sender Is Button Then
            Dim b As Button = DirectCast(sender, Button)
            If b.Tag IsNot Nothing AndAlso TypeOf b.Tag Is System.String Then
                'run the app that is defined in .Tag
                'MsgBox(b.Tag)
                Process.Start(b.Tag)
            End If
        End If

    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Dim settings As New XmlReaderSettings()
        Dim x, y
        x = 20
        y = 20
        settings.IgnoreComments = True
        Dim XMLfile As String = Application.StartupPath & "_AutoStart\config.xml"
        Using reader As XmlReader = XmlReader.Create(XMLfile, settings)
            While (reader.Read())
                If (reader.NodeType = XmlNodeType.Element And "name" = reader.LocalName) Then

                    Dim NameValue = reader.ReadElementString("name")
                    Dim PathValue = reader.ReadElementString("path")
                    Dim b As New Button
                    b = New Button With {.Text = NameValue, .Tag = PathValue, .Location = New Point(x, y), .Size = New Size(105, 23)}
                    'b.Location = New Point(x, y)
                    AddHandler b.Click, AddressOf ButtonClickHandler
                    Me.Controls.Add(b)
                    b.Visible = True
                    'x = x + 100
                    y = y + 30
                    'MsgBox(NameValue & " " & PathValue)
                    'MsgBox("button text " & b.Text & " " & "Path " & b.Tag)
                End If
            End While
        End Using
    End Sub
End Class

Anyway, many thanks for your help with this little project.

Kind regards

Baz
 
Back
Top