Reputation: 19
I posted a question about how to read the content of external xml files in VB.Net (find it here) and so far everything is going great, but I have no idea how to cycle through the data (they are all elements called savedPassword
with a specific id number). Now, I know I am supposed to give a minimum of code, but I am just starting off in XML and VB.Net and I have no idea how much code I need to give for someone to help me out with a script, so here I am, giving a paragraph of code blocks...
I have the following code so far and it works amazingly well (so if no one could modify it, that would be amazing).
My module (Overview.vb
):
' Dim values for directories and paths '
Public ReadOnly DirectoryHome As String = "C:\VelocityDK Codes"
Public ReadOnly DirectoryApp As String = "C:\VelocityDK Codes\Password Manager"
Public ReadOnly DataFile As String = "C:\VelocityDK Codes\Password Manager\appData.xml"
' Dim values for .xml file '
Public ReadOnly xmlRoot As String = "savedData"
My [general] form reading the data from my xml file (frmManager.vb
):
Option Strict On
Imports System.IO
Imports System.Xml.Serialization
' Some unrelated code '
' This current line is not in the code, but I am disabling the error message with an "unused member" - which is refering to the xmlRoot value right below. '
#Disable Warning IDE0051 ' Remove unused private members
Private ReadOnly xmlRoot As String = "savedData"
#Enable Warning IDE0051 ' Remove unused private members
' Class to represent the xml file '
Public Class SavedData
<XmlElement("savedPassword")>
Public Property SavedPasswords As List(Of SavedPassword)
End Class
' Class to represent data from external xml file '
Public Class SavedPassword
<XmlAttribute("id")>
Public Property ID As Byte
<XmlElement("name")>
Public Property Name As String
<XmlElement("email")>
Public Property Email As String
<XmlElement("password")>
Public Property Password As String
End Class
' Read xml content at first load '
Private Sub FrmManager_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim filename = DataFile
Dim data As SavedData
Dim serializer As New XmlSerializer(GetType(SavedData))
Using sr = New StreamReader(filename)
data = CType(serializer.Deserialize(sr), SavedData)
End Using
For Each sp In data.SavedPasswords
txtID.Text = {sp.ID}.ToString
txtName.Text = {sp.Name}.ToString
txtEmail.Text = {sp.Email}.ToString
txtPassword.Text = {sp.Password}.ToString
Next
End Sub
Finally, my .xml
file (appData.xml
located in the directory C:\VelocityDK Codes\Password Manager
) looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<savedData>
<savedPassword id="01">
<name>Name 01</name>
<email>[email protected]<email>
<password>password01</password>
</savedPassword>
<savedPassword id="02">
<name>Name 02</name>
<email>[email protected]<email>
<password>password02</password>
</savedPassword>
<!-- Other sections like the aboves going from id's 03 to 06 -->
<savedPassword id="07">
<name>Name 07</name>
<email>[email protected]<email>
<password>password07</password>
</savedPassword>
</savedData>
In brief, I have two buttons (btnPrevious
& btnNext
) and I want to make it so that when I click on the btnPrevious
button, it goes to the previous savedPassword
(located in my xml file) and vice versa for the btnNext
button. How can I do so?
Upvotes: 0
Views: 102
Reputation: 3007
First of all, make your form's load event look like this.
'Make this global
Dim data As SavedData
Private Sub FrmManager_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim filename = DataFile
Dim serializer As New XmlSerializer(GetType(SavedData))
Using sr = New StreamReader(filename)
data = CType(serializer.Deserialize(sr), SavedData)
End Using
'Remove for loop to display just the first record. .
txtID.Text = {data.SavedPasswords(0).ID}.ToString
txtName.Text = {data.SavedPasswords(0).Name}.ToString
txtEmail.Text = {data.SavedPasswords(0).Email}.ToString
txtPassword.Text = {data.SavedPasswords(0).Password}.ToString
End Sub
Next, keep an index somewhere in your program for cycling back and forth the list.
Dim data As SavedData
Dim currentIndex As Integer = 0
Next, Under the button click events, add the following code
'Next button
Public Sub BtnNext_Click(sender As Object, e As EventArgs)
If currentIndex < data.SavedPasswords.Count() Then
currentIndex += 1
Else
MessageBox.Show("End of data reached")
End If
txtID.Text = {data.SavedPasswords(currentIndex).ID}.ToString
txtName.Text = {data.SavedPasswords(currentIndex).Name}.ToString
txtEmail.Text = {data.SavedPasswords(currentIndex).Email}.ToString
txtPassword.Text = {data.SavedPasswords(currentIndex) .Password}
End Sub
'Previous button
Public Sub BtnPrevious_Click(sender As Object, e As EventArgs)
If currentIndex > 0 Then
currentIndex -= 1
Else
MessageBox.Show("This is the first record!")
End If
txtID.Text = {data.SavedPasswords(currentIndex).ID}.ToString
txtName.Text = {data.SavedPasswords(currentIndex).Name}.ToString
txtEmail.Text = {data.SavedPasswords(currentIndex).Email}.ToString
txtPassword.Text = {data.SavedPasswords(currentIndex).Password}
End Sub
Upvotes: 1
Reputation: 7142
I would do the following. First, create some global variable which would keep the current saved password ID. Then the following procedure will search for the next ID. Note that the actual getting XML must be realized by you.
Private curr_id$ = "01" '//Global variable
'// The direction we're searching
Enum Direction
Forward
Backward
End Enum
'// Get the <savedPassword> element. The function returns Nothing,
'// if it doesn't find ID.
Function GetSavedPassword(direction As Direction) As XElement
Dim obj_xml =
<?xml version="1.0" encoding="UTF-8"?>
<savedData>
<savedPassword id="01">
<name>Name 01</name>
<email>[email protected]</email>
<password>password01</password>
</savedPassword>
<savedPassword id="02">
<name>Name 02</name>
<email>[email protected]</email>
<password>password02</password>
</savedPassword>
<!-- Other sections like the aboves going from id's 03 to 06 -->
<savedPassword id="07">
<name>Name 07</name>
<email>[email protected]</email>
<password>password07</password>
</savedPassword>
</savedData>
Dim next_id = -1 '//ID we're searching (initial state)
Dim curr_id_num = CInt(curr_id) '//Convert string to int
'// Get all IDs from XML
Dim ids = obj_xml.<savedData>.<savedPassword>.Select(Function(x) CInt(x.@id))
'// Next we compare the current ID with available IDs
If direction = Direction.Forward Then
'// If we need to go FORWARD,
'// we must get all IDs which are greater than current id
Dim next_ids = ids.Where(Function(id) id > curr_id_num)
'// Make sure we have found something -
'// in this case it's safe to call Min()
If next_ids.Any() Then next_id = next_ids.Min()
ElseIf direction = Direction.Backward
'// If we need to go BACKWARD,
'// we must get all IDs which are less than current id
Dim next_ids = ids.Where(Function(id) id < curr_id_num)
'// Make sure we have found something -
'//in this case it's safe to call Max()
If next_ids.Any() Then next_id = next_ids.Max()
End If
'// If we found id, it will be greater than 0
If next_id > 0 Then
Dim id_string = If(next_id <= 9, "0" & next_id, next_id)
Return obj_xml.<savedData>.<savedPassword>.
Where(Function(p) p.@id = id_string).
FirstOrDefault()
End If
End Function
'// Usage
Sub Main()
Dim saved_password As XElement = GetSavedPassword(Direction.Forward)
If saved_password IsNot Nothing Then
'// Update current id
curr_id = saved_password.@id
Dim name = saved_password.<name>(0)
Dim email = saved_password.<email>(0)
Dim password = saved_password.<password>(0)
'// Update state of the program
'// ....
End If
End Sub
Upvotes: 1