Quiz using Visual Studio - arrays

I want to make a little quiz about me using visual studio. My goal is to have 10 questions and 4 choices each. I've tried to stack buttons and then change 10 labels at different times and it's getting a little complicated... using arrays or/and loops how could i make this more efficient? This is what I have
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.WindowState = FormWindowState.Maximized
Form1.Visible = False
Button2.Visible = False
Button3.Visible = False
Button4.Visible = False
Button5.Visible = False
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If RadioButton4.Checked = True Then
Label3.Text = "1/10"
Label4.Text = "Nice! That was Correct!
Great job!"
Label4.ForeColor = Color.LimeGreen
End If
If Label3.Text = "1/10" Then
Button2.Visible = True
End If
If RadioButton1.Checked = True Or RadioButton2.Checked = True Or RadioButton3.Checked = True Then
Label4.ForeColor = Color.DarkRed
Label4.Text = "Oh no! that was incorrect!
Try Again!"
End If
Button2.Text = "next"
End Sub
Private Sub Button2_click(sender As Object, e As EventArgs) Handles Button2.Click
Label1.Text = "What is Luke Lopez's favorite color?"
RadioButton4.Checked = False
RadioButton1.Text = "Purple"
RadioButton2.Text = "Burgundy"
RadioButton3.Text = "Turqoise"
RadioButton4.Text = "Brown"
If RadioButton1.Checked = True Then
Label3.Text = "2/10"
Label4.Text = "Nice! That was Correct!
Great job!"
Label4.ForeColor = Color.LimeGreen
End If
If Label3.Text = "2/10" Then
Button4.Visible = True
End If
If RadioButton3.Checked = True Or RadioButton2.Checked = True Or RadioButton4.Checked = True Then
Label4.ForeColor = Color.DarkRed
Label4.Text = "Oh no! that was incorrect!
Try Again!"
End If
Button2.Text = "check"
Button4.Text = "next"
If Label3.Text = "2/10" Then
Button3.Text = "next"
Button4.Text = "Check"
End If
End Sub
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
Button3.Visible = False
Label1.Text = "What is Luke Lopez's shoe size?"
RadioButton1.Checked = False
RadioButton1.Text = "7"
RadioButton2.Text = "8.5"
RadioButton3.Text = "7.5"
RadioButton4.Text = "8"
Button3.Visible = False
If RadioButton2.Checked = True Then
Label3.Text = "3/10"
Label4.Text = "Nice! That was Correct!
Great job!"
Label4.ForeColor = Color.LimeGreen
End If
If Label3.Text = "3/10" Then
Button5.Visible = True
Button4.Visible = False
Button3.Visible = False
Button2.Visible = False
Button1.Visible = False
End If
If RadioButton1.Checked = True Or RadioButton4.Checked = True Or RadioButton3.Checked = True Then
Label4.ForeColor = Color.DarkRed
Label4.Text = "Oh no! that was incorrect!
Try Again!"
End If
End Sub
Private Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click
End Sub
It's my first three questions and there are all the buttons and labels and radiobuttons checking and changing every click but I need this to be more efficient because I don't want to waste a lot of time and computer memory on this mini project.

In comments I talked about storing your data in a text file. This is what my text file looks like. Each record is on a single line and each field is separated by a pipe character |. I chose a pipe because you won't have any of that character in the text of your questions and answers.
1|Largest planet?|Jupiter|Venus|Saturn|Mars|1
2|Smallest planet?|Earth|Uranus|Mercury|Neptune|3
3|Comes closest to Earth?|Mars|Venus|Mercury|Jupiter|2
4|What planet is called the red planet?|Venus|Mars|Saturn|Neptune|2
5|What planet is furthest from Earth?|Saturn|Jupiter|Uranus|Neptune|4
6|How many planets in our solar system?|7|8|9|10|2
7|How many planets between Earth and Sun?|1|2|3|4|2
8|Which planet is said to have rings?|Jupiter|Uranus|Saturn|Neptune|3
You have been working with classes all along because a Form is a class. Classes can have Properties, methods and Events among other things. Now to the class, QuestionAnswer. The properties are pretty straight forward. The Sub New creates a new instance of the class and uses parameters to set all the properties of the class.
In the Form.Load FillQuestionList is called. This method uses the File class in System.IO (need to add an Imports for this). ReadAllLines returns an array of the all the lines in the file. We can loop through these lines and then split each line into fields. The little c after the "|" tells compiler that you intend a Char not a String. Now we can call the Sub New of QuestionAnswer providing all the properties from the parts of the line. This new instance is then added to the QuestionList so we can use it in the program.
Next, the Load event calls DisplayQuestion. This method will also be called from the btnNext click event. We get the index we want to display from the form level variable CurrentQuestionIndex. See how handy the class is to set the values we need. Loop through all the radio buttons clearing the Tag from the last question and clearing the check. The file provided the number of the correct answer. This is stored in the radio button's Tag property.
When the user clicks btnAnswer we get which radio button was selected and check the Tag property to see if the answer was correct. If yes, increment Score and display the score.
The btnNext.Click simply checks if we have reached the end of the list before incrementing the index and displaying the next question.
Public Class QuestionGame
Private QuestionList As New List(Of QuestionAnswer)
Private CurrentQuestionIndex As Integer
Private Score As Integer
Private Sub QuestionGame_Load(sender As Object, e As System.EventArgs) Handles MyBase.Load
FillQuestionList()
DisplayQuestion()
End Sub
Private Sub DisplayQuestion()
Dim QA = QuestionList(CurrentQuestionIndex)
lblQuestion.Text = QA.Question
RadioButton1.Text = QA.Answer1
RadioButton2.Text = QA.Answer2
RadioButton3.Text = QA.Answer3
RadioButton4.Text = QA.Answer4
For Each rb In Controls.OfType(Of RadioButton)
rb.Tag = ""
rb.Checked = False
Next
Select Case QA.Correct
Case 1
RadioButton1.Tag = "Correct"
Case 2
RadioButton2.Tag = "Correct"
Case 3
RadioButton3.Tag = "Correct"
Case 4
RadioButton4.Tag = "Correct"
End Select
End Sub
Private Sub FillQuestionList()
Dim lines = File.ReadAllLines("C:\Users\xxxxxxxx\Questions.txt")
For Each line In lines
Dim parts = line.Split("|"c)
QuestionList.Add(New QuestionAnswer(CInt(parts(0)), parts(1), parts(2), parts(3), parts(4), parts(5), CInt(parts(6))))
Next
End Sub
Private Sub btnAnswer_Click(sender As Object, e As EventArgs) Handles btnAnswer.Click
Dim rb = Controls.OfType(Of RadioButton)().FirstOrDefault(Function(r) r.Checked = True)
If rb IsNot Nothing AndAlso rb.Tag.ToString = "Correct" Then
Score += 1
lblScore.Text = Score.ToString
MessageBox.Show("Correct!")
btnAnswer.Enabled = False 'The user can't increase his score by clicking answer several times
Else
MessageBox.Show("Sorry, wrong answer")
End If
btnNext.Enabled = True
End Sub
Private Sub btnNext_Click(sender As Object, e As EventArgs) Handles btnNext.Click
btnNext.Enabled = False 'user can't move to next question until he answers current question
If CurrentQuestionIndex = QuestionList.Count - 1 Then
MessageBox.Show("This is the last question")
Else
CurrentQuestionIndex += 1
DisplayQuestion()
End If
End Sub
End Class
Public Class QuestionAnswer
Public Property QuestionNumber As Integer
Public Property Question As String
Public Property Answer1 As String
Public Property Answer2 As String
Public Property Answer3 As String
Public Property Answer4 As String
Public Property Correct As Integer
Public Sub New(Num As Integer, Ques As String, Ans1 As String, Ans2 As String, Ans3 As String, Ans4 As String, Cor As Integer)
QuestionNumber = Num
Question = Ques
Answer1 = Ans1
Answer2 = Ans2
Answer3 = Ans3
Answer4 = Ans4
Correct = Cor
End Sub
End Class

You can save questions, options and answers to a database and then read them to a DataTable, every time you want to show the question, just use a DataRow from the DataTable. That means you don't need to edit questions like:
Use 'Label.TextChanged' event to handle 'Label3.Text':
Private Sub Label3_TextChanged(sender As Object, e As EventArgs) Handles Label3.TextChanged
Select Case Label3.Text
Case "1/10"
Button2.Visible = True
Case "2/10"
Button4.Visible = True
Button3.Text = "next"
Button4.Text = "Check"
Case "3/10"
...
...
End Select
End Sub
Use 'If ... Else ...' statement. For Example:
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
'...
If RadioButton1.Checked = True Then
Label3.Text = "2/10"
Label4.Text = "Nice! That was Correct! Great job!"
Label4.ForeColor = Color.LimeGreen
Else
Label4.ForeColor = Color.DarkRed
Label4.Text = "Oh no! that was incorrect! Try Again!"
End If
'If RadioButton3.Checked = True Or RadioButton2.Checked = True Or RadioButton4.Checked = True Then
' Label4.ForeColor = Color.DarkRed
' Label4.Text = "Oh no! that was incorrect! Try Again!"
'End If
'...
End Sub

Related

NotifyCollectionChangedAction.Reset Empties ComboBox Text

I have a ComboBox, which its ItemsSource is set to an object which inherits ObservableCollection.
The object gets refreshed with new data on a timer.
Since sometimes there is a large set of new data, I don't use the Add method on the ObservableCollection, but rather I use the following code:
For Each itm In MyNewItems
Items.Add(itm)
Next
MyBase.OnPropertyChanged(New PropertyChangedEventArgs("Count"))
OnPropertyChanged(New PropertyChangedEventArgs("Items[]"))
'NEXT LINE CAUSES ISSUE
OnCollectionChanged(New NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset))
The problem is that when the last line runs, the Text of the ComboBox gets reset to an empty string.
If I remove that line, then the issue is resolved, but the Items show old data, since the ComboBox doesn't know that new data came in
Please advise
With appreciation
UPDATE
Hi, as requested, I'm posting the relevant code here
1: The Xaml, Pretty Simple:
<Window x:Class="dlgTest"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mch="clr-namespace:Machshevet.Windows;assembly=Machshevet" >
<StackPanel>
<TextBlock Text="{Binding CaseID}"/>
<mch:TestPick Name="cmbTest" SelectedValuePath="ID" DisplayMemberPath="Name" SelectedValue="{Binding CaseID}" IsEditable="True" IsTextSearchEnabled="False" />
</StackPanel>
</Window>
2: The TestPick class, not too complex either:
Public Class TestPick
Inherits ComboBox
Dim usertyped As Boolean
Function Query() As IQueryable
Dim txt = ""
Dispatcher.Invoke(Sub() txt = Text)
Dim ret = GetSlimContext.Query("viwCase").Select("new (ID,Name,ClientName,SubjectName)")
If txt <> "" AndAlso usertyped Then ret = ret.TextFiltered(txt)
Return ret
End Function
Private Sub EntityPick_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
Dim qs = New QuerySource(Function() Query())
Me.ItemsSource = qs
qs.Control = Me
qs.ShouldRefresh = Function() True
End Sub
Private Sub EntityPick_PreviewTextInput(sender As Object, e As TextCompositionEventArgs) Handles Me.PreviewTextInput
usertyped = True
End Sub
Private Sub TestPick_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles Me.SelectionChanged
If e.AddedItems.None Then
Dim a = 1
End If
End Sub
End Class
3: The QuerySource class which does all the heavy lifting
Public Class QuerySource
Inherits ObjectModel.ObservableCollection(Of Object)
Event Refreshed(sender As QuerySource, e As EventArgs)
Property RefreshSpan As TimeSpan = TimeSpan.FromSeconds(3)
Property CheckProperties As Boolean = True
Property Control As ItemsControl
Dim Timer As Threading.Timer = New Threading.Timer(Sub() TimerTick(), Nothing, 0, 600)
Dim _lastRefresh As Date?
Dim Query As Func(Of IQueryable)
Dim workingon As Date?
Sub New(Query As Func(Of IQueryable), Control As ItemsControl)
Me.Control = Control
Me.Query = Query
End Sub
Async Sub TimerTick()
Try
If Now - _lastRefresh.GetValueOrDefault < RefreshSpan Then Exit Sub
If GetLastInputTime() > 60 * 15 Then Exit Sub
Dim isvis = False
Await Control.Dispatcher.BeginInvoke(Sub() isvis = Control.IsUserVisible())
If Not isvis Then Exit Sub
If workingon.HasValue AndAlso workingon.Value > Now.AddSeconds(-15) Then Exit Sub 'if wasnt working for 15 seconds, probaly err or something
workingon = Now
Dim fq = Query.Invoke
Dim itmtype = fq.ElementType
Dim props = itmtype.CachedProperties.Where(Function(x) x.CanWrite AndAlso x.IsScalar(True)).ToList
Dim keyprops = itmtype.CachedKeyProperties.ToList
Dim newData = fq.ToObjectList
If newData Is Nothing Then Exit Sub
Dim keySelector As Func(Of Object, Object)
Dim diff As CollectionDiff(Of Object)
If itmtype.IsScalar Then 'list of strings..
keySelector = Function(x) x
Else
If keyprops.Count <> 1 Then DevError("?")
Dim kp = keyprops.FirstOrDefault
keySelector = Function(x) kp.GetValue(x)
End If
diff = CollectionDiff(Me, newData, keySelector, props, CheckProperties)
Dim toPreserve As Object
ExecIfType(Of Primitives.Selector)(Control, Sub(x) toPreserve = x.Dispatcher.Invoke(Function() x.SelectedItem))
If toPreserve IsNot Nothing Then diff.ToPreserve = {toPreserve}.ToDictionary(Function(x) x, Function(x) Nothing)
diff.PreserveOnDelete = True
If diff.ModificationCount > 400 Or diff.ClearOld Then
CheckReentrancy()
If diff.ClearOld Then
Items.Clear()
Else
For Each pair In diff.ToReplaceByIndex
Control.Dispatcher.Invoke(Sub() Items(pair.Key) = pair.Value)
Next
For Each idx In diff.GetIndexesToDelete
Items.RemoveAt(idx)
Next
End If
For Each itm In diff.ToAdd 'for mem optimization im not using addrange
Items.Add(itm)
Next
MyBase.OnPropertyChanged(New PropertyChangedEventArgs("Count"))
OnPropertyChanged(New PropertyChangedEventArgs("Items[]"))
Control.Dispatcher.Invoke(Sub() OnCollectionChanged(New NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)))
Else
Dim preservIdx = diff.ToPreserve?.Select(Function(x) Items.IndexOf(x.Key))?.ToHashSet
For Each pair In diff.ToReplaceByIndex
Control.Dispatcher.Invoke(Sub() Me(pair.Key) = pair.Value)
Next
For Each idx In diff.GetIndexesToDelete
If diff.PreserveOnDelete AndAlso preservIdx IsNot Nothing AndAlso preservIdx.Contains(idx) Then Continue For
Control.Dispatcher.Invoke(Sub() RemoveAt(idx))
Next
'don't use addrange - will cause a reset
Await Control.Dispatcher.BeginInvoke(Sub() diff.ToAdd.ForEach(Sub(x) Add(x)))
End If
_lastRefresh = Now
workingon = Nothing
Control.Dispatcher.Invoke(Sub()
Dim cvs = System.Windows.Data.CollectionViewSource.GetDefaultView(Me)
If cvs.SortDescriptions.None Then
Dim defsorts = {KVP("Name", False), KVP(NameOf(RecordBase.LastEditedOn), True), KVP(NameOf(LiteRecordBase.ID), True)}
For Each defsort In defsorts
If itmtype.HasProperty(defsort.Key) Then
cvs.SortDescriptions.Add(New SortDescription(defsort.Key, If(defsort.Value, ListSortDirection.Descending, ListSortDirection.Ascending)))
Exit For
End If
Next
End If
End Sub)
RaiseEvent Refreshed(Me, Nothing)
Catch ex As Exception
Control.Dispatcher.BeginInvoke(Sub() ex.Rethrow)
End Try
End Sub
End Class
Okay
Thanks all for chipping in, in the end it seems like my answer is actually here
ObservableCollection : calling OnCollectionChanged with multiple new items
Works like a charm, and thank you all again for your time and patience

Search Functions through Array

I'm super stuck on this one guys and need some help.
I have a multiple arrays Name, age, height, weight which is created on another form where all their data is entered into the arrays but then I need to go to another form where there is text box that I enter one of the name into and click search and then in a text box or list box it will show age, height, weight corresponding to the index of that name search.
My main problem is trying to get the arrays data over to another form and the other problem is trying to get the computer to search through the array know what index it is and show the corresponding data to that index for the other arrays. Been stuck on this for very long now could some please give me suggestions on how to do this it would be heavily appreciated, Thank you.
This is the code/ arrays I have so far
Imports System.IO
Public Class DataEntry
Dim Surname(200)
Dim Firstname(200)
Dim Age(200) As String
Dim HeightA(200) As String
Dim Weight(200)
Dim index As Integer
Public filepath As String = "c:\Patients\All Patients File"
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles btnCreate.Click
Dim di As DirectoryInfo = New DirectoryInfo("c:\Patients")
If di.Exists Then
MsgBox("File is Already There")
txtSur.Enabled = True
txtWeight.Enabled = True
txtHeight.Enabled = True
txtFirst.Enabled = True
txtAge.Enabled = True
btnAddPatient.Enabled = True
btnClear.Enabled = True
btnFileShow.Enabled = True
btnEdit.Enabled = True
btnSave.Enabled = True
txtReader.Enabled = True
Else
di.Create()
MsgBox("File is Already There")
txtSur.Enabled = True
txtWeight.Enabled = True
txtHeight.Enabled = True
txtFirst.Enabled = True
txtAge.Enabled = True
btnAddPatient.Enabled = True
btnClear.Enabled = True
btnFileShow.Enabled = True
btnEdit.Enabled = True
btnSave.Enabled = True
txtReader.Enabled = True
End If
End Sub
Private Sub btnAddPatient_Click(sender As Object, e As EventArgs) Handles btnAddPatient.Click
index = index + 1
lblNum.Text = index
Surname(index) = txtSur.Text
Firstname(index) = txtFirst.Text
Age(index) = txtAge.Text
Weight(index) = txtWeight.Text
HeightA(index) = txtHeight.Text
Dim textAppend As String
textAppend = txtSur.Text & ", " + txtFirst.Text & ", " + txtAge.Text & ", " + txtHeight.Text & "mm" & ", " + txtWeight.Text & "kg" & "."
Try
File.AppendAllText(filepath, textAppend)
MsgBox("Patient Added Successfully")
Catch ex As Exception
MsgBox("Error Adding Patient")
End Try
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles btnFileShow.Click
Dim objreader As New System.IO.StreamReader("c:\Patients\All Patients File")
txtReader.Text = objreader.ReadToEnd
objreader.Close()
End Sub
Private Sub btnClear_Click(sender As Object, e As EventArgs) Handles btnClear.Click
Dim result As Integer = MessageBox.Show("Are You Sure You Want To Clear", "ALERT", MessageBoxButtons.YesNoCancel)
If result = DialogResult.Cancel Then
MessageBox.Show("Cancel pressed")
ElseIf result = DialogResult.No Then
MessageBox.Show("Not Clearing")
ElseIf result = DialogResult.Yes Then
MessageBox.Show("Clearing")
End If
Dim objwriter As New System.IO.StreamWriter("c:\Patients\All Patients File")
'adding text from textbox to text fil
objwriter.Write("")
objwriter.Close()
Array.Clear(Surname, 0, Surname.Length)
Array.Clear(Firstname, 0, Firstname.Length)
Array.Clear(Age, 0, Age.Length)
Array.Clear(Weight, 0, Weight.Length)
Array.Clear(HeightA, 0, HeightA.Length)
index = 0
txtAge.Text = ""
txtFirst.Text = ""
txtHeight.Text = ""
txtSur.Text = ""
txtWeight.Text = ""
txtReader.Text = ""
End Sub
Private Sub DataEntry_Load(sender As Object, e As EventArgs) Handles MyBase.Load
txtSur.Enabled = False
txtWeight.Enabled = False
txtHeight.Enabled = False
txtFirst.Enabled = False
txtAge.Enabled = False
btnAddPatient.Enabled = False
btnClear.Enabled = False
btnFileShow.Enabled = False
btnEdit.Enabled = False
btnSave.Enabled = False
txtReader.Enabled = False
End Sub
Private Sub btnEdit_Click(sender As Object, e As EventArgs) Handles btnEdit.Click
If txtReader.Text = "" Then
MsgBox("No Infomation To Edit")
Else
txtReader.Focus()
End If
End Sub
Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click
If txtReader.Text = "" Then
MsgBox("Nothing To Save")
Else
Dim objwriter As New System.IO.StreamWriter("c:\Patients\All Patients File")
'adding text from textbox to text file
objwriter.Write(txtReader.Text)
objwriter.Close()
MsgBox("Saved Edit")
End If
End Sub
Private Sub Button1_Click_1(sender As Object, e As EventArgs) Handles Button1.Click
Form1.Show()
Me.Hide()
End Sub
End Class
And this is the form I have to get the arrays over to for the search
Public Class SearchPatient
Private Sub btnSearch_Click(sender As Object, e As EventArgs) Handles btnSearch.Click
End Sub

WPF - destroy page after unloaded has run

In a WPF app we have the need to sometimes create a new tab that contains a Page inside a Frame..
Once the page has been opened (initialised once) it still seems to stay in navigation history and attempts to load data that may not be relevant at the time.
I have tried a myriad of methods including NavigationService.RemoveBackEntry, but it still persists :-(
This is an example of how the tab/page are opened
Private Sub CashFlow_Edit(sender As Object, e As RoutedEventArgs)
Try
Dim DGV As DGVx = ReportsCashFlow_Grid.FindName("CashFlow_DGV")
e.Handled = True
IsNewRecord = False
If DGV.SelectedItems.Count = 1 Then
Dim row As System.Data.DataRowView = DGV.SelectedItems(0)
Form_ID = row("ID")
Dim vName As String = row("Name")
Dim vTab As STC_Tabx = Application.Current.MainWindow.FindName(TabName)
Dim TabControl As STCx = Application.Current.MainWindow.FindName("AccountingReports_TabControl")
If Not vTab Is Nothing Then
vTab.Close()
End If
Dim MCFrame As New Frame
Dim MCTab As New STC_Tabx
With MCTab
.Name = TabName
.Header = " " & vName & " "
.ImageSource = ReturnImageAsString("Edit.png", 16)
.CloseButtonVisibility = DevComponents.WpfEditors.eTabCloseButtonVisibility.Visible
.TabToolTip = "View or edit the " & vName & " template"
.Content = MCFrame
End With
RemoveHandler MCTab.Closing, AddressOf TabControl_TabClosing
AddHandler MCTab.Closing, AddressOf TabControl_TabClosing
Dim vGrid As Grid = Application.Current.MainWindow.FindName("MainGrid_Accounting")
RegisterControl(vGrid, MCTab)
TabControl.Items.Add(MCTab)
Dim MCPage As New ReportCashFlow_Page
MCFrame.NavigationService.Navigate(MCPage)
LoadedTabs(TabName)
MCTab.IsSelected = True
End If
Catch ex As Exception
EmailError(ex)
End Try
End Sub
To remove all the back entries do something like:
while(NavigationService.CanGoBack)
{
NavigationService.RemoveBackEntry();
}
It's not the clean bit of code I would like, but it works - create a global Boolean - when the sub that opens the tab/page is called it's set to true and the loading event will only run the loading code if this is true - it's set to false at the end.
Private Sub ReportCashFlow_Page_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
Try
If IsNewTab = False Then
Exit Sub
End If
'Run all the loading code here
Catch ex As Exception
EmailError(ex)
Finally
IsNewTab = False
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, CType(Sub() CashFlow_LoadBudget(), SendOrPostCallback), Nothing)
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, CType(Sub() ToggleReserve(), SendOrPostCallback), Nothing)
End Try
End Sub

Visual Basic & SQL Picturebox Controls

Using picture boxes overlaid onto an image as seen below.
Click for Form Layout
When the form loads if the student attends the class then the picturebox becomes a green tick. If the student does not attend the class the picturebox becomes blank.
Using SQL I can query the database to return all the classes that a specific student attends.
These classes are stored in an array StudentClass(n)
There are 50 classes on the timetable stored in an array AttendsClass(n). All with a default value of False.
If the student attends a class then the specific attendsclass in the array becomes True.
Once the form is loaded the user can click on a picturebox to select that class and the corresponding attendsclass in the array becomes true.
Finally the user saves the form, inserting the classes back into the database.
The problem I have is in the Sub Form4_Load at the end, I currently have to repeat the same block of code 50 times. That simply checks if the student attends the class then sets the picture box = to an image of a tick on the GUI (_new.jpg).
enter code here
If AttendsClass(1) = True Then
PictureBox1.Image = My.Resources._new
End If
If AttendsClass(2) = True Then
PictureBox2.Image = My.Resources._new
End If
If AttendsClass(3) = True Then
PictureBox3.Image = My.Resources._new
End If
If AttendsClass(4) = True Then
PictureBox4.Image = My.Resources._new
End If
Is it possible to put this into a loop to shorten my code. The code does work but its slow and lengthy so any improvements would be helpful.
Many Thanks Alex Currie
A Level Computing Student
Full Code:
enter code here
Imports System.Data.OleDb
Public Class Form4
Public con As New OleDbConnection
Public ds As New DataSet
Public da As OleDbDataAdapter
Public cb As OleDbCommandBuilder
Public constring As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source =" & Application.StartupPath & "\wma.accdb"
Public AttendsClass(50) As Boolean
Public StdID As Integer = Form2.DataGridView1.SelectedRows(0).Cells("StudentID").Value
Private Sub Form4_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim Forename As String = Form2.DataGridView1.SelectedRows(0).Cells("Forename").Value
Dim Surname As String = Form2.DataGridView1.SelectedRows(0).Cells("Surname").Value
Student.Text = "Student: " & Forename & " " & Surname
If Not con.State = ConnectionState.Open Then
con.ConnectionString = constring
con.Open()
End If
da = New OleDbDataAdapter("SELECT * FROM StudentClass WHERE StudentId = " & StdID, con)
da.Fill(ds, "Class")
Dim Maxrow As Integer = ds.Tables("Class").Rows.Count
Dim StudentClass(Maxrow) As Integer
For n = 1 To 50
AttendsClass(n) = False
Next
For n = 1 To Maxrow
StudentClass(n) = ds.Tables("Class").Rows(n - 1).Item(1)
For a = 0 To 50
If StudentClass(n) = a Then
AttendsClass(a) = True
End If
Next
Next
If AttendsClass(1) = True Then
PictureBox1.Image = My.Resources._new
End If
If AttendsClass(2) = True Then
PictureBox2.Image = My.Resources._new
End If
If AttendsClass(3) = True Then
PictureBox3.Image = My.Resources._new
End If
If AttendsClass(4) = True Then
PictureBox4.Image = My.Resources._new
End If
End Sub
Private Sub PictureBox1_Click(sender As System.Object, e As System.EventArgs) Handles PictureBox1.Click
If PictureBox1.Image Is Nothing Then
PictureBox1.Image = My.Resources._new
AttendsClass(1) = True
Else
PictureBox1.Image = Nothing
AttendsClass(1) = False
End If
End Sub
Private Sub PictureBox2_Click(sender As System.Object, e As System.EventArgs) Handles PictureBox2.Click
If PictureBox2.Image Is Nothing Then
PictureBox2.Image = My.Resources._new
AttendsClass(2) = True
Else
PictureBox2.Image = Nothing
AttendsClass(2) = False
End If
End Sub
Private Sub PictureBox4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PictureBox4.Click
If PictureBox4.Image Is Nothing Then
PictureBox4.Image = My.Resources._new
AttendsClass(4) = True
Else
PictureBox4.Image = Nothing
AttendsClass(4) = False
End If
End Sub
Private Sub PictureBox3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PictureBox3.Click
If PictureBox3.Image Is Nothing Then
PictureBox3.Image = My.Resources._new
AttendsClass(3) = True
Else
PictureBox3.Image = Nothing
AttendsClass(3) = False
End If
End Sub
Private Sub btnSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSave.Click
If Not con.State = ConnectionState.Open Then
con.ConnectionString = constring
con.Open()
End If
Dim cmd As New OleDb.OleDbCommand
cmd.Connection = con
'Deletes Existing Records To Be rewritten'
cmd.CommandText = "DELETE * FROM StudentClass WHERE StudentID=" & StdID
cmd.ExecuteNonQuery()
For n = 1 To 50
If AttendsClass(n) = True Then
cmd.CommandText = "INSERT INTO StudentClass (StudentID, ClassID) VALUES (" & StdID & "," & n & ")"
cmd.ExecuteNonQuery()
End If
Next
Me.Dispose()
MsgBox("Updated Successfully", MsgBoxStyle.Information, "WMA")
con.Close()
End Sub
End Class
Working example:
Private Sub PictureBox1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles PictureBox1.Click, ...., PictureBox50.Click
Dim pic As PictureBox = CType(Controls(CType(sender, PictureBox).Name), PictureBox)
'now you have clicked picturebox
'you can change image by pic.Image = ...
'if you want picturebox index, use line below:
Dim picidx As Integer = CInt(CType(sender, PictureBox).Name.Replace("PictureBox", ""))
End Sub
VB2010Ex.

Add Array ID's to Label Text and List Box VB.NET

Its been nearly a year since I messed with VB, but I am having an issue on my first assignment of the semester which is supposed to be a refresher. What I am supposed to do is make an application that I input a students name, address, GPA, age by textbox, and which year(freshman, sophomore, other) by radio, and classes by checkbox.
Once filled out I need to take that information and have it previewed in a label.text. If it looks right, I need the textbox.text info concatenated into a listbox. No matter what I try or do it either shows String.Array() in the preview or the program crashes at line 57 any help or insight would be appreciated.
Public Class Form1
'CIS259 Spring 2014 Matthew McQuarrie
'Declare Student Data as a String of 9 arrays
Dim StudentData(8) As String
Private Sub btnExit_Click(sender As Object, e As EventArgs) Handles btnExit.Click
'Close application
Me.Close()
End Sub
Private Sub btnReset_Click(sender As Object, e As EventArgs) Handles btnReset.Click
'Clear entire form
txtName.Clear()
txtAddress.Clear()
txtGPA.Clear()
txtAge.Clear()
radFreshman.Checked = False
radSophomore.Checked = False
radOther.Checked = False
chkCIS.Checked = False
chkMath.Checked = False
chkScience.Checked = False
chkHistory.Checked = False
lblPreview.Text = ""
End Sub
Public Sub btnPreview_Click(sender As Object, e As EventArgs) Handles btnPreview.Click
StudentData(0) = txtName.Text
StudentData(1) = txtAddress.Text
StudentData(2) = txtGPA.Text
StudentData(3) = txtAge.Text
'Find which radio button is checked to add to StudentData
If radFreshman.Checked = True Then
StudentData(4) = "Freshman"
ElseIf radSophomore.Checked = True Then
StudentData(4) = "Sophomore"
ElseIf radOther.Checked = True Then
StudentData(4) = "Other"
End If
'Find which check boxes are checked to add to StudentData
If chkCIS.Checked = True Then
StudentData(5) = "CIS"
If chkMath.Checked = True Then
StudentData(6) = "Math"
If chkScience.Checked = True Then
StudentData(7) = "Science"
If chkHistory.Checked = True Then
StudentData(8) = "History"
End If
End If
End If
End If
'Show StudentData ino the text of lblPreview
lblPreview.Text = StudentData(0 & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8)
End Sub
Private Sub btnStudent_Click(sender As Object, e As EventArgs) Handles btnStudent.Click
'Add StudentData elements to Student list
lstStudents.Items.Add(StudentData(0 & 1 & 2 & 3))
End Sub
End Class
maybe this approach I used here can help, but there a few differences..
my source is database.. I concatenate the fields in the database (the source)
and I display only the text, not the id on the listbox displaymember. you could concatenate the id to the textfield from the source and displya the fullstring contactenated.
'create the adapter
Dim adapterU As New OleDb.OleDbDataAdapter("Select id,nombre+' '+apellido as fullname from users", con)
'create a datatable
Dim datatableU As New DataTable
'bring the info from the adapter (database) into the datatable.
adapterU.Fill(datatableU)
'relate the datasource (datable) to the listbox lsUsers
lsUsers.DataSource = datatableU
lsUsers.ValueMember = "id"
lsUsers.DisplayMember = "fullname"

Resources