Calculate Button Twice

In response to the following MSDN Forum Thread(Calculate Button Twice)

The original poster asked the following question:

Hello,

I’m having trouble with a simple code in vb. For some reason I’m having to push my calculate button twice to get the result I need with this simple calculator. Anyone see where I may have made a mistake?

Here is the code:

    Public Class Form1
        Dim Number1 As Decimal
        Dim Number2 As Decimal
        Dim Answer As Decimal
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            CheckBox1.Checked = True
            CheckBox2.Checked = False
            CheckBox3.Checked = False
            CheckBox4.Checked = False
        End Sub
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Number1 = Val(TextBox1.Text)
            Number2 = Val(TextBox2.Text)
            Label4.Text = Answer

            If TextBox1.Text = "" OrElse TextBox2.Text = "" Then MsgBox("No Number(s) is given", MsgBoxStyle.Critical, "Error")

            If CheckBox1.Checked = True Then Answer = Number1 + Number2
            If CheckBox2.Checked = True Then Answer = Number1 - Number2
            If CheckBox3.Checked = True Then Answer = Number1 * Number2
            If CheckBox4.Checked = True Then Answer = Number1 / Number2

            If CheckBox1.Checked = False And CheckBox2.Checked = False And CheckBox3.Checked = False And CheckBox4.Checked = False Then MsgBox("No Operators is Checked!", MsgBoxStyle.Critical, "Error")
            If CheckBox1.Checked = True And CheckBox2.Checked = True Then MsgBox("You can not have more than one item checked", MsgBoxStyle.Critical, "Error")
            If CheckBox1.Checked = True And CheckBox3.Checked = True Then MsgBox("You can not have more than one item checked", MsgBoxStyle.Critical, "Error")
            If CheckBox1.Checked = True And CheckBox4.Checked = True Then MsgBox("You can not have more than one item checked", MsgBoxStyle.Critical, "Error")

            If CheckBox2.Checked = True And CheckBox3.Checked = True Then MsgBox("You can not have more than one item checked", MsgBoxStyle.Critical, "Error")
            If CheckBox2.Checked = True And CheckBox4.Checked = True Then MsgBox("You can not have more than one item checked", MsgBoxStyle.Critical, "Error")

            If CheckBox3.Checked = True And CheckBox4.Checked = True Then MsgBox("You can not have more than one item checked", MsgBoxStyle.Critical, "Error")
        End Sub
    End Class

When you are expecting to display a result after calculating it, it is important to write code that executes in that order.

Since you are only displaying your result after it is calculated, I also suggest using variables in a block scope verses using variables in a class scope.

I also suggest making the following changes to your code:

Option Strict On
Public Class Form1
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        rbSubtraction.Checked = True
        rbAddition.Checked = False
        rbDivision.Checked = False
        rbMultiplication.Checked = False
    End Sub
    Private Sub btnCalculate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCalculate.Click
        Dim Number1 As Decimal = 0D
        Dim Number2 As Decimal = 0D
        Dim Answer As Decimal = 0D
        Decimal.TryParse(tbNumber1.Text, Number1)
        Decimal.TryParse(tbNumber2.Text, Number2)
        Dim msg As String() = {"You must provide a Number {0}"}
        Select Case True
            Case tbNumber1.Text = String.Empty : lblResult.Text = String.Format(msg(0), "1") : Exit Sub
            Case tbNumber2.Text = String.Empty : lblResult.Text = String.Format(msg(0), "2") : Exit Sub
            Case rbSubtraction.Checked : Answer = Number1 - Number2
            Case rbAddition.Checked : Answer = Number1 + Number2
            Case rbMultiplication.Checked : Answer = Number1 * Number2
            Case rbDivision.Checked : Answer = Number1 / Number2
        End Select
        lblResult.Text = Answer.ToString
    End Sub
    Private Sub tbNumber1_KeyDown(sender As Object, e As KeyEventArgs) Handles tbNumber2.KeyDown, tbNumber1.KeyDown
        Dim count As Integer = (From c As Char In DirectCast(sender, TextBox).Text Where c = "."c Select c).Count
        Select Case True
            Case {8, 46, 37, 38, 39, 40}.ToList.IndexOf(e.KeyCode) > -1 : Exit Sub
            Case e.KeyCode = Keys.Decimal OrElse e.KeyCode = Keys.OemPeriod
                If tbNumber1.SelectionStart = 0 Then Exit Select
                If count > 0 Then Exit Select Else Exit Sub
            Case Char.IsDigit(ChrW(e.KeyCode)) : Exit Sub
        End Select
        e.SuppressKeyPress = True
        e.Handled = True
    End Sub
End Class

 

 

Don’t use a for next loop if you are not utilizing the iteration object.

A brief summary of what this means is that if you are using a for-next loop, you would only want to use the object that is iterated. You could call a for-next loop an object iteration loop. Where-as a Do-While loop is a condition-iteration loop.

Object Iteration Loop:
In the following loop, a collection(list of string) is iterated.

        Dim items As New List(Of String) From {"a", "b", "c"}
        For Each item As String In items
            MsgBox(item) '<-- utilizing the iteration object
        Next

Condition Iteration Loop:
In the following loop, a collection is not iterated through, instead a value is modified, and the loop ends when a certain condition becomes true.

        Dim i As Integer = 0
        Do
            i += 1
        Loop Until i = 100 '<-- evaluating a condition

How to get state abbreviations quickly with a small amount of code

On the MSDN forums, I suspect the person in this post is attempting to get a state abbreviation.

If I were trying to get a state abbreviation, I would do it like this:

Option Strict On
Public Class Form1
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        MsgBox(GetStateAbbrevation(TextBox1.Text))
    End Sub
    Public Function GetStateAbbrevation(ByVal stateName As String) As Object
        Dim States As New List(Of String) From {"ALabama", "AlasKa", "AriZona", "ARkansas", "CAlifornia", "COlorado", _
                                                "ConnecTicut", "DElaware", "FLorida", "GeorgiA", "HawaiI", _
                                                "IDaho", "ILlinois", "INdiana", "IowA", "KansaS", "KentuckY", _
                                                "LousianaA", "MainE", "MarylandD", "MAssachusetts", "MIchigan", _
                                                "MiNnesota", "MiSsissippi", "MissOuri", "MonTana", "NEbraska", _
                                                "NeVada", "NewHampshire", "NewJersey", "NewMexico", "NewYork", _
                                                "NorthCarolina", "NorthDakota", "OHio", "OKlahoma", "ORegon", _
                                                "PennsylvAnia", "RhodeIsland", "SouthCarolina", "SouthDakota", _
                                                "TenNessee", "TeXas", "UTah", "VermonT", "VirginiA", "WAshington", _
                                                "WestVirginia", "WIconsin", "WYoming"}
        stateName = stateName.Replace(" ", "").ToLower
        Dim result As String = String.Empty
        For Each state As String In States
            If state.ToLower = stateName.ToLower Then
                For Each c As Char In state
                    If Char.IsUpper(c) Then result = result & c
                Next
            End If
        Next
        Return result
    End Function
End Class

Splitting Text Files

I recently responded for a MSDN forum post about splitting text files. Due to the extra level of thought required in dealing with nested operations, I enjoyed creating this code. This code will split a text file with multiple lines and create new files from the original file, and each file will have a specified number of lines. The last file created will have the remaining lines.

    Private Sub splitFileMulti(inFilePath As String, outDirectory As String, outFileBaseName As String, outFileExtension As String, maxLinesPerFile As Integer, lineDelimiter As String)
        'Load the file into memory
        Dim fileContent As String = My.Computer.FileSystem.ReadAllText(inFilePath)
        'Get a list of lines from the file, remove empty lines created by delimiters of more than one character
        Dim allLines As List(Of String) = fileContent.Split(lineDelimiter.ToCharArray, StringSplitOptions.RemoveEmptyEntries).ToList
        'calculate how many lines will be in the last file
        Dim remainingLineCount As Integer = allLines.Count Mod maxLinesPerFile
        'Create a list to hold each files list of lines
        Dim files As New List(Of List(Of String))
        'create a stringbuilder for fast string manipulation
        Dim contentOut As New System.Text.StringBuilder
        'counter is for file naming
        Dim counter As Integer = 0
        'iterate through all the file lines
        For i As Integer = 0 To allLines.Count Step maxLinesPerFile
            'prevent index out of range error by exiting loop before error is possible
            If i + maxLinesPerFile > allLines.Count Then Exit For
            'add each files lines to the list
            files.Add(allLines.GetRange(i, maxLinesPerFile))
        Next
        'add the remaining files lines to the list
        If remainingLineCount > 0 Then files.Add(allLines.GetRange(allLines.Count - remainingLineCount, remainingLineCount))
        'iterate each files lines
        For Each fileLines As List(Of String) In files
            'increment the naming counter
            counter += 1
            'create a zero padded string to append to the file name
            Dim cntString As String = counter.ToString.PadLeft(5, "0"c)
            'clear the stringbuilder
            contentOut.Clear()
            'iterate each line in that files lines
            For Each line As String In fileLines
                'append the line to the stringbuilder
                contentOut.Append(line & lineDelimiter)
            Next
            'create the file name
            Dim fileName As String = outFileBaseName & cntString & "." & outFileExtension
            'remove double periods(happens if user provides extension with a period)
            fileName = fileName.Replace("..", ".")
            'create the outpath
            Dim outPath As String = System.IO.Path.Combine(outDirectory, fileName)
            'write data to file
            My.Computer.FileSystem.WriteAllText(outPath, contentOut.ToString, False)
        Next
    End Sub

It’s garage sale day!

Today I will be running around looking at garage sales, it’s the community garage sale day…

Links to previously published Technet Wiki articles

I have decided that I will be using wordpress as a primary location to publish content to the internet. That being said, I am also including links to past community contributions on my wordpress site. Thank you.

 

Pull Out Panel – Borderless Form – Visual Basic.Net
Visual Basic – Accessing a method Via its declared name string.
Visual Basic – Changing the speed of a wavefile
LoOps! With Visual Basic.Net
Conditional Branches With Visual Basic.Net
Dos Scripts From Visual Basic.Net
Visual Basic.Net Common Errors – Index was out of range.
Pattern Matching Words With Visual Basic
How To Convert a 32 Bit integer into a color
Virtual Memory In Visual Basic.Net
Bitmap.Lockbits De-Mystified .Net
Visual Basic – Knife Thrower!
Visual Basic – Drive Searcher
Workaround – Visual Basic/C# WebBrowser DBLClick Word
Convert System.Decimal to and from Byte Arrays (VB & C#)
Become More Productive by Making Custom Code Generation Tools(VB & C#)
Declaring Numeric Data Types
Braille Code in .Net
Evaluating Expressions – Visual Basic

 

Guild wars 2 API Wrapper

So…. Been working on this wrapper for gw2 client. I really want to explore the whole api and see what I can make……
If you know how to use this, then you are welcome to use it for whatever you want.

Option Strict On
Option Explicit On
Option Infer Off
Imports System.Net
Imports Newtonsoft.Json
Imports System.Xml
Imports System.IO
Namespace GW2API
    Public Class Client
        Public Shared Function ItemJSON(itemID As String) As String
            Dim gw2API As String = "https://api.guildwars2.com/v1/item_details.json?item_id=" & itemID
            Dim json As String = String.Empty
            Using w As New WebClient
                Try
                    json = w.DownloadString(gw2API)
                Catch
                    json = ""
                End Try
            End Using
            Return json
        End Function
        Public Shared Function ItemXMLFromID(itemID As String) As String
            Return ItemXMLFromJSON(ItemJSON(itemID))
        End Function
        Public Shared Function ItemXMLFromJSON(json As String) As String
            Return GetXMLString(ItemJSONToXML(json))
        End Function
        Public Shared Function ItemJSONToXML(json As String) As XmlDocument
            Try
                Return DirectCast(JsonConvert.DeserializeXmlNode("{GuildWars2Item:" & json & "}"), XmlDocument)
            Catch ex As Exception
                Return New XmlDocument
            End Try
        End Function
        Private Shared Function GetXMLString(xmlDoc As XmlDocument) As String
            If xmlDoc Is Nothing Then Return ""
            Dim result As String = String.Empty
            Using sw As New StringWriter
                Using xw As New XmlTextWriter(sw)
                    xw.Formatting = System.Xml.Formatting.Indented
                    xmlDoc.WriteTo(xw)
                End Using
                result = sw.ToString()
            End Using
            Return result
        End Function
    End Class
End Namespace
Option Strict On
Option Explicit On
Option Infer Off
Imports System.Xml
Imports System.IO
Imports System.Text
Imports System.Net
Namespace GW2API
    Public Class Item
#Region "Guild Wars 2 Item Properties"
        Public Property item_id As String
        Public Property name As String
        Public Property description As String
        Public Property type As String
        Public Property level As String
        Public Property rarity As String
        Public Property vendor_value As String
        Public Property icon_file_id As String
        Public Property icon_file_signature As String
        Public Property game_types As New List(Of String)
        Public Property default_skin As String
        Public Property flags As New List(Of String)
        Public Property weapon As String
        Public Property damage_type As String
        Public Property min_power As String
        Public Property max_power As String
        Public Property defense As String
        Public Property suffix_item_id As String
        Public Property secondary_suffix_item_id As String
        Public Property infix_upgrade As String
        Public Property attributes As String
        Public Property attribute As String
        Public Property modifier As String
        Public Property armor As String
        Public Property weight_class As String
        Public Property consumable As String
        Public Property unlock_type As String
        Public Property recipe_id As String
        Public Property container As String
        Public Property bag As String
        Public Property no_sell_or_sort As String
        Public Property size As String
        Public Property infusion_slots As String
        Public Property color_id As String
        Public Property trinket As String
        Public Property gizmo As String
        Public Property back As String
        Public Property upgrade_component As String
        Public Property bonuses As String
        Public Property suffix As String
        Public Property buff As String
        Public Property skill_id As String
        Public Property duration_ms As String
        Public Property restrictions As New List(Of String)
        Public Property infusion_upgrade_flags As String
        Public Property gathering As String
        Public Property tool As String
        Public Property charges As String
#End Region
#Region "Object Properties"
        ''' <summary>
        ''' This image may be assigned if you wish to return a custom 'image not available' image, 
        ''' otherwise the default embedded 'image not available' image will be returned from the image property.
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property OverrideErrorImage As Image = Nothing
        ''' <summary>
        ''' A list of guild wars item properties in this object, that have values assigned to them.
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property UsedProperties As New List(Of String)
        ''' <summary>
        ''' A list of unknown properties and their values, which did not exist at the time of the development of this wrapper.
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property UnknownProperties As New List(Of UnknownProperty)
#Region "Embedded File"
        Public Shared Property defaultImageBytes As Byte() = {137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 64, 0, 0, 0, 64, 8,
                                   2, 0, 0, 0, 37, 11, 230, 137, 0, 0, 0, 1, 115, 82, 71, 66, 0, 174, 206, 28, 233, 0, 0, 0, 4,
                                   103, 65, 77, 65, 0, 0, 177, 143, 11, 252, 97, 5, 0, 0, 0, 9, 112, 72, 89, 115, 0, 0, 14, 195, 0,
                                   0, 14, 195, 1, 199, 111, 168, 100, 0, 0, 3, 63, 73, 68, 65, 84, 104, 67, 221, 152, 189, 149, 219, 48, 16,
                                   132, 21, 41, 185, 72, 129, 130, 11, 156, 95, 1, 87, 132, 138, 80, 172, 62, 212, 135, 66, 181, 224, 18, 212, 138,
                                   235, 240, 14, 23, 252, 128, 165, 8, 30, 101, 75, 207, 183, 158, 55, 15, 15, 67, 226, 103, 6, 132, 5, 248, 54,
                                   255, 3, 126, 254, 250, 145, 148, 53, 64, 169, 165, 194, 52, 128, 103, 202, 66, 108, 11, 232, 68, 196, 182, 128, 78,
                                   68, 108, 11, 232, 68, 196, 182, 128, 78, 68, 108, 11, 232, 68, 196, 182, 128, 78, 68, 108, 11, 232, 68, 196, 182,
                                   128, 78, 68, 108, 11, 232, 68, 196, 182, 128, 78, 68, 108, 11, 232, 68, 196, 182, 128, 78, 68, 108, 11, 232, 192,
                                   235, 155, 191, 53, 28, 174, 227, 195, 219, 238, 112, 126, 175, 109, 214, 147, 209, 62, 119, 151, 248, 234, 114, 222, 250,
                                   155, 143, 71, 70, 182, 246, 94, 10, 232, 192, 78, 128, 19, 245, 135, 200, 104, 199, 253, 228, 213, 191, 8, 208, 184,
                                   97, 122, 150, 182, 62, 113, 184, 227, 166, 203, 249, 232, 181, 237, 233, 22, 218, 151, 0, 183, 221, 135, 235, 177, 193,
                                   44, 237, 181, 151, 2, 58, 176, 14, 212, 15, 48, 204, 138, 3, 111, 118, 185, 149, 133, 12, 206, 226, 114, 180, 25,
                                   66, 179, 50, 169, 61, 127, 63, 125, 122, 101, 156, 58, 210, 222, 121, 41, 160, 3, 215, 4, 24, 86, 55, 6, 240,
                                   137, 3, 26, 103, 165, 203, 24, 32, 228, 111, 235, 64, 125, 177, 212, 208, 94, 121, 41, 160, 3, 103, 3, 92, 119,
                                   90, 146, 126, 128, 217, 250, 227, 1, 150, 54, 143, 211, 26, 121, 41, 160, 35, 247, 7, 127, 93, 3, 216, 147, 183,
                                   179, 85, 86, 5, 168, 159, 66, 1, 98, 151, 21, 91, 72, 51, 90, 179, 186, 118, 145, 214, 200, 75, 1, 61, 101,
                                   243, 17, 6, 140, 11, 211, 9, 32, 7, 117, 11, 109, 15, 199, 242, 92, 205, 232, 82, 81, 70, 139, 221, 59, 95,
                                   254, 142, 246, 214, 75, 1, 157, 136, 216, 22, 208, 137, 136, 109, 1, 157, 136, 216, 22, 208, 137, 136, 109, 1, 157,
                                   136, 216, 22, 208, 137, 136, 109, 1, 221, 146, 67, 32, 226, 171, 35, 166, 249, 185, 92, 248, 17, 124, 136, 156, 122,
                                   237, 128, 38, 189, 20, 208, 119, 108, 238, 5, 119, 215, 224, 121, 126, 179, 0, 181, 115, 8, 80, 207, 154, 187, 15,
                                   178, 16, 96, 174, 23, 167, 88, 193, 112, 50, 134, 198, 159, 187, 211, 147, 3, 48, 180, 38, 179, 79, 20, 51, 244,
                                   2, 116, 122, 205, 95, 93, 219, 198, 53, 246, 147, 2, 212, 53, 43, 171, 181, 63, 249, 21, 192, 217, 9, 208, 233,
                                   213, 108, 209, 17, 22, 96, 210, 248, 201, 91, 232, 137, 1, 120, 104, 45, 169, 191, 60, 64, 220, 12, 54, 241, 91,
                                   216, 66, 157, 47, 62, 219, 171, 9, 80, 63, 197, 115, 183, 80, 231, 87, 168, 25, 180, 92, 33, 231, 94, 53, 24,
                                   46, 225, 51, 189, 24, 63, 94, 93, 219, 198, 127, 249, 143, 248, 219, 18, 219, 2, 58, 17, 177, 45, 160, 19, 17,
                                   219, 2, 58, 17, 177, 45, 160, 19, 17, 219, 2, 58, 17, 177, 45, 160, 3, 95, 112, 45, 123, 34, 205, 149, 151,
                                   2, 58, 240, 197, 1, 46, 231, 157, 14, 135, 63, 165, 185, 242, 82, 64, 7, 78, 142, 64, 242, 216, 65, 67, 125,
                                   56, 221, 234, 201, 239, 7, 86, 120, 50, 192, 207, 166, 248, 188, 158, 128, 117, 162, 175, 254, 179, 209, 208, 90, 123,
                                   41, 160, 3, 123, 1, 12, 109, 134, 120, 123, 113, 91, 139, 127, 30, 181, 144, 229, 79, 102, 26, 182, 204, 98, 214,
                                   253, 84, 94, 155, 193, 154, 122, 41, 160, 3, 39, 1, 144, 190, 156, 237, 7, 153, 24, 237, 220, 49, 103, 3, 76,
                                   191, 213, 184, 4, 95, 210, 90, 122, 41, 160, 3, 215, 5, 40, 75, 222, 4, 160, 222, 250, 243, 102, 245, 106, 56,
                                   237, 248, 192, 230, 113, 90, 31, 47, 5, 116, 96, 179, 73, 20, 32, 46, 249, 186, 0, 241, 142, 217, 12, 40, 248,
                                   237, 176, 110, 33, 77, 106, 9, 53, 23, 30, 250, 180, 62, 94, 10, 232, 192, 197, 0, 184, 92, 220, 66, 241, 142,
                                   217, 124, 82, 225, 254, 126, 238, 19, 97, 96, 145, 214, 216, 75, 1, 157, 136, 216, 22, 208, 137, 136, 109, 1, 157,
                                   136, 216, 22, 208, 137, 136, 109, 1, 157, 136, 216, 22, 208, 137, 136, 109, 1, 157, 136, 216, 22, 208, 137, 136, 109,
                                   1, 157, 136, 216, 22, 106, 45, 21, 66, 128, 164, 44, 1, 18, 99, 179, 249, 13, 103, 64, 168, 59, 156, 67, 74,
                                   244, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130}
#End Region

        ''' <summary>
        ''' This property attempts to download the icon image for this guild wars object. If downloading fails, the specified or default 
        ''' 'image not available' image will be returned.
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public ReadOnly Property Image(Optional size As Size = Nothing) As Image
            Get
                If size = Nothing Then size = New Size(64, 64)
                Try
                    'https://render.guildwars2.com/file/{signature}/{file_id}.{format}
                    Dim api As String = String.Format("https://render.guildwars2.com/file/{0}/{1}.{2}", Me.icon_file_signature, Me.icon_file_id, "png")
                    Dim buffer As Byte()
                    Dim bm As Image
                    Using w As New WebClient
                        buffer = w.DownloadData(api)
                    End Using
                    Using s As New MemoryStream(buffer)
                        bm = Image.FromStream(s)
                    End Using
                    Dim resizedImage As New Bitmap(size.Width, size.Height)
                    Dim g As Graphics = Graphics.FromImage(resizedImage)
                    g.DrawImage(bm, 0, 0, resizedImage.Width + 1, resizedImage.Height + 1)
                    Return resizedImage
                Catch
                    Dim img As Image
                    Dim resizedImage As New Bitmap(size.Width, size.Height)
                    Dim g As Graphics = Graphics.FromImage(resizedImage)
                    Using ss As New MemoryStream(Item.defaultImageBytes)
                        If Me.OverrideErrorImage Is Nothing Then
                            img = Bitmap.FromStream(ss)
                        Else
                            img = Me.OverrideErrorImage
                        End If
                    End Using
                    g.DrawImage(img, 0, 0, resizedImage.Width + 1, resizedImage.Height + 1)
                    Return resizedImage
                End Try
            End Get
        End Property
#End Region
        ''' <summary>
        ''' Returns a string representation of this object. Unused properties are not included in this string representation.
        ''' </summary>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shadows Function ToString() As String
            Dim sb As New StringBuilder
            For Each s As String In UsedProperties
                Dim value As Object = GetPropValue(Me, s)
                Select Case value.GetType
                    Case GetType(String)
                        sb.Append(s & ": " & value.ToString & vbCrLf)
                    Case GetType(List(Of String))
                        Dim str As List(Of String) = DirectCast(value, List(Of String))
                        Dim arr As String = String.Empty
                        For Each ss As String In str
                            arr = arr & ss & ", "
                        Next
                        arr = arr.Substring(0, arr.Length - 2)
                        sb.Append(s & ": " & arr & vbCrLf)
                    Case Else

                End Select

            Next
            Return sb.ToString
        End Function
        ''' <summary>
        ''' Returns a listviewitem with values in the order specified by the order of the property names supplied in the propertyOrder string.
        ''' </summary>
        ''' <param name="propertyOrder">Provide a list of property names, from the "GW2API.Item" object, to return the 
        ''' values of those properties, in the order provided.</param>
        ''' <returns>Returns a ListViewItem containing the values of the specified properties, from this object, in the order provided.</returns>
        ''' <remarks></remarks>
        Public Function ToListViewItem(propertyOrder As List(Of String)) As ListViewItem
            Dim item As New ListViewItem("error")
            Dim values As List(Of Object) = Me.GetOrderedPropertyValues(propertyOrder)
            Dim currentPropName As String = String.Empty
            Dim index As Integer = -1
            Try
                For i As Integer = 0 To values.Count - 1
                    Dim s As Object = values(i)
                    index += 1
                    currentPropName = propertyOrder(index)
                    If s Is Nothing Then Continue For
                    Select Case s.GetType
                        Case GetType(String)
                            Dim str As String = DirectCast(s, String)
                            If index = 0 Then
                                item.Text = str
                                Continue For
                            End If
                            item.SubItems.Add(str)
                        Case GetType(List(Of String))
                            Dim str As List(Of String) = DirectCast(s, List(Of String))
                            Dim arr As String = String.Empty
                            For Each ss As String In str
                                arr = arr & ss & ", "
                            Next
                            arr = arr.Substring(0, arr.Length - 2)
                            If index = 0 Then
                                item.Text = arr
                                Continue For
                            End If
                            item.SubItems.Add(arr)
                        Case Else
                            item.SubItems.Add(s.ToString)
                    End Select
                Next
            Catch
            End Try
            Return item
        End Function
        Public Function GetOrderedPropertyValues(properties As List(Of String)) As List(Of Object)
            Dim result As New List(Of Object)
            For Each p As String In properties
                result.Add(GW2API.Item.GetPropValue(Me, p))
            Next
            Return result
        End Function
        Public Shared Function GetPropValue(src As Object, propName As String) As Object
            Try
                Return src.GetType.GetProperty(propName).GetValue(src, Nothing)
            Catch
                Return Nothing
            End Try
        End Function
        Public Class UnknownProperty
            Public PropertyName As String
            Public PropertyValues As New List(Of String)
            Public Property PropertyObject As Object
            Sub New(PropertyName As String, PropertyValues As Object)
                Me.PropertyName = PropertyName
                Select Case True
                    Case PropertyValues.GetType = GetType(List(Of String))
                        Me.PropertyValues = DirectCast(PropertyValues, List(Of String))
                    Case PropertyValues.GetType = GetType(String)
                        Me.PropertyValues.Add(DirectCast(PropertyValues, String))
                End Select
                Me.PropertyObject = PropertyValues
            End Sub
        End Class
        Private Shared Function GetAllJsonItems(filePath As String, delimiter As Char()) As List(Of String)
            Dim db As String = My.Computer.FileSystem.ReadAllText(filePath)
            Dim items As String() = db.Split(delimiter, StringSplitOptions.RemoveEmptyEntries)
            Return items.ToList
        End Function
        Public Shared Function FromID(ID As String) As Item
            Dim json As String = Client.ItemJSON(ID)
            Return Item.FromJson(json)
        End Function
        Public Shared Function FromJson(json As String) As Item
            Dim result As New Item
            Dim xml As String = Client.ItemXMLFromJSON(json)
            If xml = "" Then Return result
            Dim xmlReader As XmlReader = New XmlTextReader(New StringReader(xml))
            Dim doc As XmlDocument = Client.ItemJSONToXML(json)

            While xmlReader.Read
                Dim value As String = xmlReader.Value

                If xmlReader.NodeType = XmlNodeType.Element Then
                    Dim eleName As String = xmlReader.Name
                    If eleName = "GuildWars2Item" Then Continue While
                    If result.UsedProperties.IndexOf(eleName) > -1 Then Continue While
                    result.UsedProperties.Add(eleName)
                    Dim valueList As XmlNodeList = doc.GetElementsByTagName(xmlReader.Name)
                    Select Case eleName
                        Case "item_id" : result.item_id = valueList(0).InnerXml
                        Case "name" : result.name = valueList(0).InnerXml
                        Case "description" : result.description = valueList(0).InnerXml
                        Case "type" : result.type = valueList(0).InnerXml
                        Case "level" : result.level = valueList(0).InnerXml
                        Case "rarity" : result.rarity = valueList(0).InnerXml
                        Case "vendor_value" : result.vendor_value = valueList(0).InnerXml
                        Case "icon_file_id" : result.icon_file_id = valueList(0).InnerXml
                        Case "icon_file_signature" : result.icon_file_signature = valueList(0).InnerXml
                        Case "game_types"
                            For Each s As XmlNode In valueList
                                If result.game_types.IndexOf(s.InnerXml) > -1 Then Continue For
                                result.game_types.Add(s.InnerXml)
                            Next
                        Case "default_skin" : result.default_skin = valueList(0).InnerXml
                        Case "flags"
                            For Each s As XmlNode In valueList
                                If result.flags.IndexOf(s.InnerXml) > -1 Then Continue For
                                result.flags.Add(s.InnerXml)
                            Next
                        Case "weapon" : result.weapon = valueList(0).InnerXml
                        Case "damage_type" : result.damage_type = valueList(0).InnerXml
                        Case "min_power" : result.min_power = valueList(0).InnerXml
                        Case "max_power" : result.max_power = valueList(0).InnerXml
                        Case "defense" : result.defense = valueList(0).InnerXml
                        Case "suffix_item_id" : result.suffix_item_id = valueList(0).InnerXml
                        Case "secondary_suffix_item_id" : result.secondary_suffix_item_id = valueList(0).InnerXml
                        Case "infix_upgrade" : result.infix_upgrade = valueList(0).InnerXml
                        Case "attributes" : result.attributes = valueList(0).InnerXml
                        Case "attribute" : result.attribute = valueList(0).InnerXml
                        Case "modifier" : result.modifier = valueList(0).InnerXml
                        Case "armor" : result.armor = valueList(0).InnerXml
                        Case "weight_class" : result.weight_class = valueList(0).InnerXml
                        Case "consumable" : result.consumable = valueList(0).InnerXml
                        Case "unlock_type" : result.unlock_type = valueList(0).InnerXml
                        Case "recipe_id" : result.recipe_id = valueList(0).InnerXml
                        Case "container" : result.container = valueList(0).InnerXml
                        Case "bag" : result.bag = valueList(0).InnerXml
                        Case "no_sell_or_sort" : result.no_sell_or_sort = valueList(0).InnerXml
                        Case "size" : result.size = valueList(0).InnerXml
                        Case "infusion_slots" : result.infusion_slots = valueList(0).InnerXml
                        Case "color_id" : result.color_id = valueList(0).InnerXml
                        Case "trinket" : result.trinket = valueList(0).InnerXml
                        Case "gizmo" : result.gizmo = valueList(0).InnerXml
                        Case "back" : result.back = valueList(0).InnerXml
                        Case "upgrade_component" : result.upgrade_component = valueList(0).InnerXml
                        Case "bonuses" : result.bonuses = valueList(0).InnerXml
                        Case "suffix" : result.suffix = valueList(0).InnerXml
                        Case "buff" : result.buff = valueList(0).InnerXml
                        Case "skill_id" : result.skill_id = valueList(0).InnerXml
                        Case "duration_ms" : result.duration_ms = valueList(0).InnerXml
                        Case "restrictions"
                            For Each s As XmlNode In valueList
                                If result.restrictions.IndexOf(s.InnerXml) > -1 Then Continue For
                                result.restrictions.Add(s.InnerXml)
                            Next
                        Case "infusion_upgrade_flags" : result.infusion_upgrade_flags = valueList(0).InnerXml
                        Case "gathering" : result.gathering = valueList(0).InnerXml
                        Case "tool" : result.tool = valueList(0).InnerXml
                        Case "charges" : result.charges = valueList(0).InnerXml
                        Case Else
                            Dim unknowns As New List(Of String)
                            For Each s As XmlNode In valueList
                                If unknowns.IndexOf(s.InnerXml) > -1 Then Continue For
                                unknowns.Add(s.InnerXml)
                            Next
                            result.UnknownProperties.Add(New UnknownProperty(eleName, unknowns))
                    End Select
                End If
            End While
            Return result
        End Function
    End Class
End Namespace