Foreword: This is code for a game.
On one of the forms on my VB program I have a large number of text boxes, the issue is regarding the following code:
Total_Gold.Text = (WoodPrice * TxtBoxWoodUnits.Text) + (MagicWoodPrice * TxtBoxMagicWoodUnits.Text) + (Pheonix_EggsPrice * TxtBoxPheonixEggsUnits.Text) + (MetalPrice * TxtBoxMetalUnits.Text) + (Dwarven_GemsPrice * TxtBoxDwarvenGemsUnits.Text) + (LeatherPrice * TxtBoxLeatherUnits.Text) + (Dragon_ScalesPrice * TxtBoxDragonScalesUnits.Text) + (Raw_SilverPrice * TxtBoxRawSilverUnits.Text) + (Raw_GoldPrice * TxtBoxRawGoldUnits.Text) + (DownPrice * TxtBoxDownUnits.Text) + (CottonPrice * TxtBoxCottonUnits.Text) + (QuicksilverPrice * TxtBoxQuicksilverUnits.Text) + (StonePrice * TxtBoxStoneUnits.Text) + (CoalPrice * TxtBoxCoalUnits.Text) + (ThreadPrice * TxtBoxThreadUnits.Text) + (FurPrice * TxtBoxFurUnits.Text)
This is contained in a timer event that shows how much it would cost the player to purchase all of the items. This works as intended, until the text box is blank. Each "section" draws information from one of 16 text boxes.
My question is this: Is it possible to have each text box to have a "default" number that gets put into a text box when it is empty.
This is needed to be done for all of the text boxes, so either a loop or a non specific code slice would be preferred.
The short answer is no.
The long answer is yes, you can.
Create your own textbox that inherits from the TextBox class, adding a property called "DefaultValue" Override the appropriate property/method adding logic for the default value.
Then simply replace the standard textbox with your textbox.
I hope you are validating the input as well because if TxtBoxWoodUnits.Text = "Foo" and you multiply it by 4.5, it's not gonna be pretty. You should turn on Error notifications for Implicit conversions as well, so you get compiler warnings when you try to multiply strings by numbers.
Public Class MyTextBox
Inherits TextBox
Public Property DefaultValue As String
Public Overrides Property Text As String
Get
If String.IsNullOrWhiteSpace(MyBase.Text) Then
Return DefaultValue
Else
Return MyBase.Text
End If
End Get
Set(ByVal value As String)
MyBase.Text = value
End Set
End Property
End Class
Well in the designer you could put the text value as "0", then in the textchanged event handler do this:
If TxtBoxWoodUnits.Text = "" Then
TxtBoxWoodUnits.Text = "0"
EndIf
Basically everytime the text of your textbox is changed, it checks if it is null, if it is, then make the value of textbox "0".
Hope this helps.
Private Sub btn_generate_text_array_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click ' will generate a group of 10 text boxes
Dim j As Integer
For j = 0 To 10
ReDim Preserve c(j)
c(j) = New TextBox
c(j).Name = "txt" & j
c(j).Parent = Me
c(j).Top = j * c(j).PreferredHeight + 2
c(j).Tag = j
c(j).Visible = True
Next
End Sub
Private Sub c_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
For j = 0 To 10 'loop will load 0 to all the text boxes having ""(null) values
If c(j).Text = "" Then
c(j).Text = "0"
End If
Next
End Sub
Related
Full disclosure, I'm working on an assignment for COP2170, but the additional feature isn't apart of the assignment just trying to stretch a little further...
I'm trying to add 5 test scores and output the average of the 5 scores, that part works just fine. In addition I'm trying to add an additional feature that will allow the user to enter less than 5 scores and the program will still output the average of whatever scores were entered.
So this works:
And this works:
The problem I'm running into is if the first score is omitted and the rest are filled in, it doesn't work:
Here's the code I've got so far:
Public Class frmTestScoreAverage
Private Sub btnCalculate_Click(sender As Object, e As EventArgs) Handles btnCalculate.Click
Dim decScore1, decScore2, decScore3, decScore4, decScore5 As Double ' decScore1-5 to hold test scores1-5
Dim decScoreAverage As Double ' to hold test score average
Dim intDivideBy As Double = 5 ' declare intDivideBy variable with starting value of 5
lblStatusLabel.Text = String.Empty 'set error message to empty string
Try
' Read user input convert to double and assign value to variable
decScore1 = Convert.ToDouble(txtScore1.Text)
decScore2 = Convert.ToDouble(txtScore2.Text)
decScore3 = Convert.ToDouble(txtScore3.Text)
decScore4 = Convert.ToDouble(txtScore4.Text)
decScore5 = Convert.ToDouble(txtScore5.Text)
' Calculate average
decScoreAverage = (decScore1 + decScore2 + decScore3 + decScore4 + decScore5) / intDivideBy
'display result
lblResult.Text = CStr(decScoreAverage)
Catch
' Display error message, asks for all scores
lblStatusLabel.Text = "Please enter all test scores"
'Calculate average even without all scores
For Each c As TextBox In Me.Controls.OfType(Of TextBox)() 'loop through each textbox in form see: http://stackoverflow.com/a/13504361/1947286
If c.Text = String.Empty Then intDivideBy -= 1 'If text equals empty string, Then decrement intDivideBy
Next
'catch divide by zero error
Try
'calculate average
decScoreAverage = (decScore1 + decScore2 + decScore3 + decScore4 + decScore5) / intDivideBy 'add test scores and divide to find average
'display result
lblResult.Text = CStr(decScoreAverage)
Catch
lblStatusLabel.Text = "Please enter at least one test score"
End Try
End Try
End Sub
End Class
I'm pretty sure the problem has to do with the way I'm finding the average:
decScoreAverage = (decScore1 + decScore2 + decScore3 + decScore4 + decScore5) / intDivideBy
Is there a way to find the average that will allow for empty variables in any arrangement?
The problem you are having is that Convert.ToDouble(txtBox.text) (with empty string, will make Convert throw an Exception.
Add a validation that the string isn't empty or use TryParse to see if the Textbox value is parseable to a number.
Either
If not String.IsNullOrEmpty(txtBox.Text) then
Convert.ToDouble(txtBox.text)
Or
dim value as Double
if Double.TryParse(txtBox.Text, value) then
avg += value
When the first one is empty, it goes to the Catch part of the code, then you try to calculate the avg, but the values of the Txtbox are not assigned to the declarations you made, so when it tries to do the average
decScore1 = Convert.ToDouble(txtScore1.Text) // Exception here to Catch
decScore2 = Convert.ToDouble(txtScore2.Text) // Not evaluated
decScore3 = Convert.ToDouble(txtScore3.Text) // Not evaluated
decScore4 = Convert.ToDouble(txtScore4.Text) // Not evaluated
decScore5 = Convert.ToDouble(txtScore5.Text) // Not evaluated
Theses do not have any value, in return this doesn't do what you want
decScoreAverage = (decScore1 + decScore2 + decScore3 + decScore4 + decScore5) / intDivideBy
UPDATE
(Vb code not tested)
Function GetTextValue(dim score as string) as Double
dim value as Double = 0
if (Double.TryParse(score, value))
return value
else
return value
End Function
This
decScore1 = Convert.ToDouble(txtScore1.Text)
Becomes
decScore1 = GetTextValue(txtScore1.Text)
I suggest you store reference to each textbox in an array. You'll see why at the end of this example.
Public Class frmTestScoreAverage
Public Sub New()
Me.InitializeComponent()
Me.boxes = {Me.txtScore1, Me.txtScore2, Me.txtScore3, Me.txtScore4, Me.txtScore5}
End Sub
Private boxes As TextBox()
The common way to validate user input in winforms is to handle the Validating event, usually combined with the error provider class as mentioned by Hans Passant.
Private Sub HandleScoreValidating(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles txtScore1.Validating, txtScore2.Validating, txtScore3.Validating, txtScore4.Validating, txtScore5.Validating
With DirectCast(sender, TextBox)
If ((Not String.IsNullOrEmpty(.Text)) AndAlso (Not Double.TryParse(.Text, 0.0R))) Then
e.Cancel = True
'Alert or set error provider:
'Me.ErrorProvider1.SetError(DirectCast(sender, Control), "Not double")
Else
e.Cancel = False
'Clear error provider:
'Me.ErrorProvider1.Clear()
End If
End With
End Sub
Now, back to the textbox array. Create a new list of double and iterate the textbox array. If the text isn't empty, parse and add the value to the list. At the end, use the Average extension method to get the average value.
Private Sub HandleCalculate(sender As Object, e As EventArgs) Handles btnCalculate.Click
Dim values As New List(Of Double)
For Each box As TextBox In Me.boxes
If (Not String.IsNullOrEmpty(box.Text)) Then
values.Add(Double.Parse(box.Text))
'Else
' values.Add(0.0R)
End If
Next
Dim average As Double = values.Average()
'....
End Sub
End Class
Recently when creating a program for my client as part of my computing project in visual basic .net I've came across a problem, which looks like following; In order to receive additional marks for my program I must take an advantage of either Binary Search or Insertion Sort subroutine declared recursively, so far the only place I can use it on is my View form which displays all reports generated by program but the problem with this is since I'm using MS Access to store my data all of the data is downloaded and placed in listview in load part of form. So the only way I can use it is by running it on listview which is a major problem for me due to the fact that I'm not very experienced in vb.
For binary search I have tried downloading all of the items in specified by user column into an array but that's the bit I was struggling on the most because I'm unable to download all items from only one column into an array. Also instead of searching every single column user specifies in my form in which column item is located (For example "19/02/2013" In Column "Date"), In my opinion if I manage to download every single entry in specified column into an array it should allow me to run binary search later on therefore completing the algorithm. Here's what I've got so far.
Sub BinarySearch(ByVal Key As String, ByVal lowindex As String, ByVal highindex As String, ByVal temp() As String)
Dim midpoint As Integer
If lowindex > highindex Then
MsgBox("Search Failed")
Else
midpoint = (highindex + lowindex) / 2
If temp(midpoint) = Key Then
MsgBox("found at location " & midpoint)
ElseIf Key < temp(midpoint) Then
Call BinarySearch(Key, lowindex, midpoint, temp)
ElseIf Key > temp(midpoint) Then
Call BinarySearch(Key, midpoint, highindex, temp)
End If
End If
End Sub
Private Sub btnSearch_Click(sender As System.Object, e As System.EventArgs) Handles btnSearch.Click
Dim Key As String = txtSearch.Text
Dim TargetColumn As String = Me.lstOutput.Columns(cmbColumns.Text).Index
Dim lowindex As Integer = 0
Dim highindex As Integer = lstOutput.Items.Count - 1
'Somehow all of the items in Target column must be placed in temp array
Dim temp(Me.lstOutput.Items.Count - 1) As String
' BinarySearch(Key, lowindex, highindex, temp)
End Sub
For Insertion sort i don't even have a clue how to start, and the thing is that I have to use my own subroutine instead of calling system libraries which will do it for me.
Code which I have to use looks like following:
Private Sub InsertionSort()
Dim First As Integer = 1
Dim Last As Integer = Me.lstOutput.
Dim CurrentPtr, CurrentValue, Ptr As Integer
For CurrentPtr = First + 1 To Last
CurrentValue = A(CurrentPtr)
Ptr = CurrentPtr - 1
While A(Ptr) > CurrentValue And Ptr > 0
A(Ptr + 1) = A(Ptr)
Ptr -= 1
End While
A(Ptr + 1) = CurrentValue
Next
Timer1.Enabled = False
lblTime.Text = tick.ToString
End Sub
Any ideas on how to implement this code will be very appreciated, and please keep in my mind that I'm not very experienced in this language
Perhaps this might give you a place to begin. If you already have a ListView with "stuff" in it you could add a button to the form with the following code to copy the Text property for each item into an array:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim myArray(Me.ListView1.Items.Count - 1) As String
Dim i As Integer
' load array
For i = 0 To Me.ListView1.Items.Count - 1
myArray(i) = Me.ListView1.Items(i).Text
Next
' show the results
Dim s As String = ""
For i = 0 To UBound(myArray)
s &= String.Format("myArray({0}): {1}", i, myArray(i)) & vbCrLf
Next
MsgBox(s, MsgBoxStyle.Information, "myArray Contents")
' now go ahead and manipulate the array as needed
' ...
End Sub
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I have a movie theater seating project that dynamically creates checkboxes as seats. I dynamically create labels across the top and down the right side of the checkboxes that represents the seats (alpha) and rows (numbers). Currently I have numbers across the top and I want letters i.e. A, B, C, D.
Here is my code
Public Class frmSeating
' Declare two dynamic arrays to store the created CheckBox and Label
' control instances. The array named chkSeats is a 2-dimensional array
' and the array lblRow is a one dimensional array.
Private chkSeats(,) As System.Windows.Forms.CheckBox
Private lblRow() As System.Windows.Forms.Label
Private lblSeat() As System.Windows.Forms.Label
' The following constants improve readibility by defining the
' standard size of each check box, and the number of seats and rows
' for each airplane type.
Private Const cintCheckBoxHeight As Integer = 23
Private Const cintCheckBoxWidth As Integer = 23
Private Const cintABCSeats As Integer = 20
Private Const cintABCRows As Integer = 20
Private Const cintCBSSeats As Integer = 26
Private Const cintCBSRows As Integer = 30
Private Const cintNBCSeats As Integer = 10
Private Const cintNBCRows As Integer = 25
' The variables mintFull and mintEmpty store the number of
' occupied and empty seats in the theater.
Private mintFull As Integer
Private mintEmpty As Integer
' pntCurrent is used to create a Point structure.
Private pntCurrent As System.Drawing.Point
' All of the work takes place in the ConfigureSeating procedure. This
' procedure is called by the constructor. See the New procedure in the
' Windows Form Designer generated code.
Private Sub ConfigureSeating(ByVal TheaterType As String)
' Variables to store the current seat and the current row.
Dim pintSeatCurrent, pintRowCurrent As Integer
' The Select Case statement configures the airplane based on the
' type of airplane. This value is passed to the procedure, and is
' obtained from the argument passed through the constructor.
Select Case TheaterType
Case "ABC Theater"
' Redimension the arrays containing the check boxes and
' labels based on the current Theater configuration.
ReDim chkSeats(cintABCSeats, cintABCRows)
ReDim lblRow(cintABCRows)
ReDim lblSeat(cintABCSeats)
' Define the number of empty seats.
mintEmpty = cintABCSeats * cintABCRows
' Create each check box representing a seat.
For pintSeatCurrent = 0 To cintABCSeats - 1
For pintRowCurrent = 0 To cintABCRows - 1
pntCurrent = New Point((pintSeatCurrent + 1) * cintCheckBoxWidth, _
(pintRowCurrent + 1) * cintCheckBoxHeight)
Call CreateCheckBox(pintSeatCurrent, pintRowCurrent, pntCurrent)
Next
Next
'Create the labels to identify the rows.
For pintRowCurrent = 0 To cintABCRows - 1
Call CreateRowLabel(pintRowCurrent)
lblRow(pintRowCurrent).Left = 490
lblRow(pintRowCurrent).Top = (pintRowCurrent + 1) * cintCheckBoxHeight
lblRow(pintRowCurrent).Height = 15
lblRow(pintRowCurrent).Width = 25
Next
'Create the labels to identify the columns
For pintSeatCurrent = 0 To cintABCSeats - 1
Call CreateSeatLabel(pintSeatCurrent)
lblSeat(pintSeatCurrent).Left = (pintSeatCurrent + 1) * cintCheckBoxHeight
lblSeat(pintSeatCurrent).Top = 1
lblSeat(pintSeatCurrent).Height = 15
lblSeat(pintSeatCurrent).Width = 25
Next
Case "CBS Theater"
ReDim chkSeats(cintCBSSeats, cintCBSRows)
ReDim lblRow(cintCBSRows)
ReDim lblSeat(cintCBSSeats)
mintEmpty = cintCBSSeats * cintCBSRows
For pintSeatCurrent = 0 To cintCBSSeats - 1
For pintRowCurrent = 0 To cintCBSRows - 1
pntCurrent = New Point((pintSeatCurrent + 1) * cintCheckBoxWidth, _
(pintRowCurrent + 1) * cintCheckBoxHeight)
Call CreateCheckBox(pintSeatCurrent, pintRowCurrent, pntCurrent)
Next
Next
For pintRowCurrent = 0 To cintCBSRows - 1
Call CreateRowLabel(pintRowCurrent)
lblRow(pintRowCurrent).Left = 625
lblRow(pintRowCurrent).Top = (pintRowCurrent + 1) * cintCheckBoxHeight
lblRow(pintRowCurrent).Height = 15
lblRow(pintRowCurrent).Width = 25
Next
For pintSeatCurrent = 0 To cintCBSSeats - 1
Call CreateSeatLabel(pintSeatCurrent)
lblSeat(pintSeatCurrent).Left = (pintSeatCurrent + 1) * cintCheckBoxHeight
lblSeat(pintSeatCurrent).Top = 1
lblSeat(pintSeatCurrent).Height = 15
lblSeat(pintSeatCurrent).Width = 25
Next
Case "NBC Theater"
ReDim chkSeats(cintNBCSeats, cintNBCRows)
ReDim lblRow(cintNBCRows)
ReDim lblSeat(cintNBCSeats)
mintEmpty = cintNBCSeats * cintNBCRows
For pintSeatCurrent = 0 To cintNBCSeats - 1
For pintRowCurrent = 0 To cintNBCRows - 1
pntCurrent = New Point((pintSeatCurrent + 1) * cintCheckBoxWidth, _
(pintRowCurrent + 1) * cintCheckBoxHeight)
Call CreateCheckBox(pintSeatCurrent, pintRowCurrent, pntCurrent)
Next
Next
For pintRowCurrent = 0 To cintNBCRows - 1
Call CreateRowLabel(pintRowCurrent)
lblRow(pintRowCurrent).Left = 255
lblRow(pintRowCurrent).Top = (pintRowCurrent + 1) * cintCheckBoxHeight
lblRow(pintRowCurrent).Height = 15
lblRow(pintRowCurrent).Width = 25
Next
For pintSeatCurrent = 0 To cintNBCSeats - 1
Call CreateSeatLabel(pintSeatCurrent)
lblSeat(pintSeatCurrent).Left = (pintSeatCurrent + 1) * cintCheckBoxHeight
lblSeat(pintSeatCurrent).Top = 1
lblSeat(pintSeatCurrent).Height = 15
lblSeat(pintSeatCurrent).Width = 25
Next
End Select
End Sub
' The CreateCheckBox procedure is responsible for actually creating
' each CheckBox control instance and adding a reference to the array.
' The current seat and row are passed as arguments, along with the
' position of the check box.
Private Sub CreateCheckBox(ByVal pintSeatCurrent As Integer, ByVal pintRowcurrent As Integer, ByVal pnt As Point)
' Create an instance of the CheckBox control and make it visible.
chkSeats(pintSeatCurrent, pintRowcurrent) = New CheckBox()
chkSeats(pintSeatCurrent, pintRowcurrent).Visible = True
' Define the size of the CheckBox control instance by creating an
' instance of the Size structure and assigning a value to the Size
' property.
chkSeats(pintSeatCurrent, pintRowcurrent).Size = _
New System.Drawing.Size(cintCheckBoxWidth, cintCheckBoxHeight)
' Define the position of the CheckBox control instance.
chkSeats(pintSeatCurrent, pintRowcurrent).Location = pnt
' Add the event handler for the newly created CheckBox control instance.
' The procedure named chkSeats_CheckChanged will handle the CheckedChanged event for
' all of the created check boxes.
AddHandler chkSeats(pintSeatCurrent, pintRowcurrent).CheckedChanged, _
AddressOf chkseats_CheckedChanged
' Finally, add the newly creted CheckBox control instance to the Controls
' collection for the Panel. Note that by adding the control instance to the
' Controls collection of the Panel rather than the form, the control instances
' will be contained by the Panel. The reason is simple. The CheckBox control
' instances will scroll with the Panel instead of the form.
Me.pnlSeats.Controls.Add(chkSeats(pintSeatCurrent, pintRowcurrent))
End Sub
' The CreateLabel procedure is responsible for actually creating each
' Label control instance and adding a reference to the array.
Private Sub CreateRowLabel(ByVal pintRowCurrent As Integer)
lblRow(pintRowCurrent) = New Label()
lblRow(pintRowCurrent).Visible = True
lblRow(pintRowCurrent).Text = (pintRowCurrent + 1).ToString()
Me.pnlSeats.Controls.Add(lblRow(pintRowCurrent))
End Sub
Private Sub CreateSeatLabel(ByVal pintSeatCurrent As Integer)
lblSeat(pintSeatCurrent) = New Label()
lblSeat(pintSeatCurrent).Visible = True
lblSeat(pintSeatCurrent).Text = (pintSeatCurrent + 1).ToString()
Me.pnlSeats.Controls.Add(lblSeat(pintSeatCurrent))
End Sub
' The CheckedChanged event handler is a multicast event handler and
' handles the CheckedChanged event for all of the CheckBox control instances.
' The statements in the event handler update the number of full or empty
' seats in the theater.
Private Sub chkseats_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)
' Declare a varible to store the CheckBox.
Dim chkCurrent As System.Windows.Forms.CheckBox
' Again, because sender is of type System.Object, explicitly convert
' the argument to a check box using the CType function
chkCurrent = CType(sender, System.Windows.Forms.CheckBox)
' If the check box is checked, increment the number of occupied seats
' and decrement the number of empty seats. If the check box is not checked,
' then do the reverse.
Select Case chkCurrent.Checked
Case True
mintFull += 1
mintEmpty -= 1
Case False
mintFull -= 1
mintEmpty += 1
End Select
' Display the results in the labels.
lblFull.Text = mintFull.ToString()
lblEmpty.Text = mintEmpty.ToString()
End Sub
' Uncheck all of the check boxes by enumerating the Controls collection of the Panel.
Private Sub mmuSeatsClear_Click(sender As System.Object, e As System.EventArgs) Handles mmuSeatsClear.Click
Dim ctlCurrent As Control
Dim chkCurrent As CheckBox
' The For Each loop enumerates the Controls collection for the
' Panel rather than the form.
For Each ctlCurrent In pnlSeats.Controls
' Check that the type of the control instance is a CheckBox.
' Labels are also contained by the Panel. If the control instance
' is a CheckBox, then remove the check mark by setting the Checked property
' to False.
If TypeOf (ctlCurrent) Is System.Windows.Forms.CheckBox Then
chkCurrent = CType(ctlCurrent, System.Windows.Forms.CheckBox)
chkCurrent.Checked = False
End If
Next
lblFull.Text = ""
lblEmpty.Text = ""
End Sub
Private Sub mmuFileExit_Click(sender As System.Object, e As System.EventArgs) Handles mmuFileExit.Click
Me.Close()
End Sub
End Class
Get the Char representation of the ascii value :
Private Sub CreateSeatLabel(ByVal pintSeatCurrent As Integer)
lblSeat(pintSeatCurrent) = New Label()
lblSeat(pintSeatCurrent).Visible = True
lblSeat(pintSeatCurrent).Text = Chr(pintSeatCurrent + 65)
Me.pnlSeats.Controls.Add(lblSeat(pintSeatCurrent))
End Sub
65 is the value representing A character in ASCII Chart. Everytime the index increases by 1 you will get the next alphabetic character.
I'm designing a windows form. I have output to be displayed on the form it self.
Tried using print, but it is not working.
How do I do that?
I'M NOT PRINTING THE FORM.
ADDED:
I need to display 3 numbers with text string next to each number.
I want to do this in a way that it shows in the form or label in the form without overwriting the previous results.
example:
3 (wrong) 1 (right) 8 (wrong)
2 (wrong) 1 (right) 5 (right)
9 (right) 1 (right) 5 (right)
ADDED:
Thanks for the help everyone. one more question and i think i'm good.
I was thinking of doing something like this inside a loop, problem is I can't add a string and an int together to make a new var:
Xnum1 = Xnum1 + 50
Xnum2 = Xnum1 + ".0F"
Ynum1 = Ynum1 + 50
Ynum2 = Ynum1 + ".0F"
In VB6 you could use the Print statement to draw to the surface of the form. In VB.NET, however, you should be using the Form.CreateGraphics method to create a new Graphics object that can be used to draw to the form's surface. For instance:
Private Sub PrintText(text As String, x As Single, y As Single)
Dim g As Graphics = Me.CreateGraphics()
g.DrawString(text, New Font("Arial", 16), New SolidBrush(Color.Black), New PointF(x, y))
End Sub
That would be the closest equivalent to using the VB6 Print statement like that.
However, I would strongly recommend using a control to display the data. It looks like for the data you need to display, a simple multi-line text box or label would be sufficient. For instance:
Private Sub AppendResult(index As Integer, right As Boolean)
If right Then
TextBox1.Text = TextBox1.Text & " " & index.ToString() & " (right)"
Else
TextBox1.Text = TextBox1.Text & " " & index.ToString() & " (wrong)"
End If
End Sub
If you want to get more fancy, you could look into using a data grid, a list box, a list view, or even a table layout control instead.
I believe that the most efficient way is to use a tableLayoutPanel with 6 columns. Add in each cell a label showing in the first cell the number, in the second the indicator for that number (right/wrong). Do the same for second and third number.(second number = third and fourth cell, third number =fifth and sixth cell)
For the next set of numbers you can add a new row with with labels in each cell.
I'll add some code to make my answer more professional.
First you add the tableLayoutPanel in your form. You size it as you like (make its width, long enough to handle the data)
You delete the lastRow and then you add columns (you want to have 6 columns). You edit the size of the columns to be Percentage =16.67%
Public Class Form1
Private rowIndex
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
For i = 0 To 4 Step 2
Dim val As Integer = 3
AddLabels(val, i, 0)
Next
For i = 1 To 5 Step 2
Dim val As String = "right"
AddLabels(val, i, 0)
Next
End Sub
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
rowIndex = rowIndex + 1
Me.TableLayoutPanel1.RowStyles.Add(New RowStyle(SizeType.Absolute, 30))
Me.TableLayoutPanel1.Height = Me.TableLayoutPanel1.Height + 30
For i = 0 To 4 Step 2
Dim val As Integer = 3 'here you have to put your number
AddLabels(val, i, rowIndex)
Next
For i = 1 To 5 Step 2
Dim val As String = "right" 'here you have to put your indicator
AddLabels(val, i, rowIndex)
Next
End Sub
Private Sub AddLabels(ByVal lblValue As String, ByVal column As Integer, ByVal row As Integer)
Dim lblHeader As New Label
lblHeader.AutoSize = True
lblHeader.Margin = New Padding(0)
lblHeader.BackColor = Color.Transparent
lblHeader.TextAlign = ContentAlignment.MiddleLeft
lblHeader.Dock = DockStyle.None
lblHeader.Text = lblValue
'Put the lblHeader in the right cell
Dim lblHeaderPos As New TableLayoutPanelCellPosition(column, row)
TableLayoutPanel1.SetCellPosition(lblHeader, lblHeaderPos)
TableLayoutPanel1.Controls.Add(lblHeader)
End Sub
Let me know if you facing any problems.
Also if you don't know how many rows you will add, put the tableLyoutPanel inside a panel. Make the panel's property AutoScroll=True and then you can add infinite number of new rows.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
DataGridView - Validating for Cell
hi...i have a requirement. i dont know how to get the data from the datagrid after the user entered data in textboxcolumn. i also want to validate the entered text in datagrid cell.
This may answer your question:
Suppose there are:
2 textboxes named "txt_X_Values" (gets the values for column "x") and "txt_Y_Values" (that gets the user input for column Y);
a button named "btnAdd_2_Table" (click to add data from textboxes to table);
a datagridview control named "dgv_RawData"; and
(of course) a form that will contain the controls/components mentioned above..
With the following codes, when the button is clicked, the button will store the data input from the textboxes to their respective arrays. In here, i have declared an array named "Column_X" that stores values from txt_X_Values.text and Column_Y for txt_Y_Values.text.
After the values are stored, i may now put/display them in the datagridview cells (codes are shown below..with the comment " ' add columns/rows to datagridview"). With such process, you can add filters/validators or whatever you would call it. You may declare a new sub or function for that.
Here are the codes:
Private Sub btnAdd_2_Table_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAdd_2_Table.Click
If Blank_Input(txt_X_Values.Text, txt_Y_Values.Text) Then
MessageBox.Show("You cannot have a blank data. Please provide numeric values to both columns.", _
"ERROR ON INPUT", MessageBoxButtons.OK, MessageBoxIcon.Error)
If txt_X_Values.Text = "" Or txt_X_Values.Text = " " Then
txt_X_Values.Focus()
Else
txt_Y_Values.Focus()
End If
Else
Data_InputProc()
Display_Table_Proc()
' add columns to datagridview
If rowCounter - 1 = 0 Then
dgv_RawData.Columns.Add("Column_X", x_Title)
dgv_RawData.Columns.Add("Column_Y", y_Title)
End If
' add rows to datagridview
dgv_RawData.Rows.Add(x_Column(rowCounter - 1), y_Column(rowCounter - 1))
' enable reset
btnReset.Enabled = True
' reset dot counters
dotCountX = 0
dotCountY = 0
End If
btnSave_Data.Enabled = True
End Sub
Here are the codes for the functions that I have made:
*Note that I am only filtering/validating numeric values with these codes.
(function to store data from textbox to arrays)
Public Sub Data_InputProc()
' resize array
ReDim Preserve x_Column(total_Rows), y_Column(total_Rows)
' engine
x_Column(rowCounter) = CDbl(txt_X_Values.Text)
y_Column(rowCounter) = CDbl(txt_Y_Values.Text)
'' next row
rowCounter += 1
total_Rows = rowCounter
' ready value textbox for another input from user
txt_X_Values.Clear()
txt_Y_Values.Clear()
txt_X_Values.Focus()
End Sub
(function/sub to validate numeric values...actually this code only allows the use of 1 dot per numeric entry)
' keypress handler
Public Sub NumericOnly(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles _
txt_X_Values.KeyPress, txt_Y_Values.KeyPress
' do not allow non-numeric characters but allow backspace and dot
If Not e.KeyChar Like "[0-9.]" And Asc(e.KeyChar) <> 8 Then
e.KeyChar = Nothing
ToolTip_Universal.Show("Only NUMERIC values are valid.", grpDataEntry, 300, 100, 1500)
' do not allow multiple dots
ElseIf sender Is txt_X_Values And e.KeyChar Like "." Then
dotCountX += 1
If dotCountX > 1 And e.KeyChar Like "." Then _
e.KeyChar = Nothing
ToolTip_Universal.Show("Only ONE DOT is allowed.", txt_X_Values, 130, 20, 1500)
ElseIf sender Is txt_Y_Values And e.KeyChar Like "." Then
dotCountY += 1
If dotCountY > 1 And e.KeyChar Like "." Then _
e.KeyChar = Nothing
ToolTip_Universal.Show("Only ONE DOT is allowed.", txt_X_Values, 130, 20, 1500)
End If
End Sub
I hope this one helps you out with your problem:
I built a simple program that lets the user put values to the datagridview control. After that, a button is pressed to get the values from that table and store it to a 2D array. The array may then be used to manipulate data as you wish.
Code:
' declare array for storage of all values
Dim array_of_all_values(,) As Object
' number of columns and rows from the datagridview control
Dim Num_of_Columns, Num_of_Rows As Integer
' this block of code asks the user to how many columns does he want to add to the DGV
Private Sub btnNo_of_Columns_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNo_of_Columns.Click
Num_of_Columns = txtCol_Num.Text
For columnCount = 1 To Num_of_Columns
dgv_Test.Columns.Add("Column_" & columnCount, InputBox("What is the header of Column " & columnCount & "?" & vbCrLf, "Column Header", "no header"))
Next
btnNo_of_Columns.Enabled = False
txtCol_Num.Clear()
dgv_Test.Focus()
End Sub
Private Sub btnGetSpecific_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGetSpecific.Click
' this code gets the specific value of the cell that is selected by the user (selection by mouse <left> click)
rtb_TestResult.Text = dgv_Test.Item(dgv_Test.CurrentCellAddress.X, dgv_Test.CurrentCellAddress.Y).Value
' you may now insert the value of the cell into a variable
' you may code for the specific validation that you require/desire
End Sub
Private Sub btnGetAll_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGetAll.Click
Dim rowValue As String
' this code will get values of all cells and record it to an array
Num_of_Rows = dgv_Test.RowCount - 1
ReDim Preserve array_of_all_values(Num_of_Rows, Num_of_Columns)
For dgvColumnIndex = 0 To Num_of_Columns - 1
For dgvRowIndex = 0 To Num_of_Rows - 1
array_of_all_values(dgvRowIndex, dgvColumnIndex) = dgv_Test.Item(dgvColumnIndex, dgvRowIndex).Value
Next
Next
' you may now manipulate the inputs using the 2d array
' you may now construct validation codes
' this code displays the array values in table form
' this is useful in checking arrays
For arr_X_index = 0 To UBound(array_of_all_values, 1)
For arr_Y_index = 0 To UBound(array_of_all_values, 2)
rowValue &= array_of_all_values(arr_X_index, arr_Y_index) & vbTab
Next
rtb_TestResult.Text &= rowValue & vbCrLf
rowValue = ""
Next
End Sub
Sample of how the program worked:
Hope that answers your problem.. please be specific next time. :D