I am trying to add rows to a datagridview and when loading the from it only displays one letter on the variable I am trying to retrieve.
Dim col As New DataGridViewTextBoxColumn 'adding the colunm player to the data grid view
col.HeaderText = "Player"
DataGridView_displayfigures.Columns.Add(col)
DataGridView_displayfigures.Rows.Add(New String({AssignRuns.batsman1A}))
This is the structure
Structure AssignRuns
Shared batsman1A As String = PlayerSelection.player1_cmbox.Text
Shared batsman1Aruns As Integer
I don't understand this. any help would be appreciated
This is a perfect example of why you should have Option Strict On. You are use a String constructor here:
DataGridView_displayfigures.Rows.Add(New String({AssignRuns.batsman1A}))
But that is definitely not doing what you intend. You are passing a String array as an argument but there is no String constructor that has a parameter of type String array. With Option Strict On, that would generate a syntax error and your code would fail to compile until you fixed it.
With Option Strict Off, the compiler looks for a constructor that is similar enough that it can massage your code to work. In this case, it uses the one that has a parameter of type Char array. That constructor creates a String containing all the Char values from the array.
In your case, each String in your array is converted to a Char by simply taking the first character in each String. Your array only contains one String so only one Char is passed to the constructor, so the String that gets created only contains one character.
As well as that, there's no overload of that Add method that takes a single String either. There is one that takes an Object array though, so that's what you should be passing:
DataGridView_displayfigures.Rows.Add(New Object() {AssignRuns.batsman1A})
This would also work:
DataGridView_displayfigures.Rows.Add({AssignRuns.batsman1A})
That is technically passing a String array to the Add method but that is allowed because it's a widening conversion, i.e. no data can be lost. Converting a String to a Char is a narrowing conversion because data can be lost, as it was in your original code. Option Strict On allows implicit widening conversions but not implicit narrowing conversions.
EDIT:
Actually, thinking about that last code snippet and the fact that you can pass a String array directly to Add makes me think that maybe your mistake was just to misplace a single closing parenthesis because, rather than this:
DataGridView_displayfigures.Rows.Add(New String({AssignRuns.batsman1A}))
you could have had this:
DataGridView_displayfigures.Rows.Add(New String() {AssignRuns.batsman1A})
Moving that closing parenthesis means that you are denoting a String array and then initialising it, rather than passing a literal String array as an argument to a constructor.
You can try me this way to add rows and columns in the DataGridView control.
Public Class Form1
Structure AssignRuns
Shared batsman1A As String = "player1"
Shared batsman1Aruns As Integer = 3
End Structure
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'definite columncount and then add columns of datagridview1
DataGridView1.ColumnCount = AssignRuns.batsman1Aruns
DataGridView1.Columns(0).HeaderText = "Player"
'add rows of datagridview1
Dim row As String() = {AssignRuns.batsman1A} 'You can try {AssignRuns.batsman1A,AssignRuns.batsman1A,AssignRuns.batsman1A}
DataGridView1.Rows.Add(row)
End Sub
End Class
Related
How do I change a string / remove the quotations to make it a existing object value instead of string? I've got a constant object that is used to input what the "currentcreature" is which's value is inputted into byVal tables but whenever I try inputting it as the result of a SQL table search is a string I do not know how to put the string result turning into an object.
Dim Placeholder As New List(Of Object)
Sub with stuff
another sub that ends with this
Placeholder.Add(SearchResults.GetString(0))
CurrentCreature = Placeholder(0)
LoadCreature(CurrentCreature, Player)
End sub
Object of the Constant CurrentCreature immediately gets an error with the preceding code
Value of Creature should be Object rather than String
Creature "Frog" Object {String}
What should happen:
CurrentCreature sure be able to apply with the object as its input than string (this works normally if I put it equal to any object so I mainly want to figure out how to change the values of strings into datatype object/gain the values of it initially stored as objects)
I was wondering if there is any way to access the expected data type within a function similar to an event arg. I am doubtful that this is possible, though it would be an excellent feature.
I frequently work with (old and disorganized)Mysql databases creating interfaces through VB.Net. Often I will have an optional field which contains a NULL value in the database. I am frequently dealing with errors due to NULL and dbnull values in passing data to and from the database.
To complicate things, I often am dealing with unexpected datatypes. I might have an integer zero, a double zero, an empty string, or a string zero.
So I spend a fair amount of code checking that each entry is of the expected type and or converting NULLs to zeros or empty strings depending on the case. I have written a function ncc(null catch convert) to speed up this process.
Public Function ncc(obj As Object, tp As Type) As Object 'Null Catch Convert Function...
My function works great, but I have to manually set the type every time I call the function. It would be so much easier if it were possible to access the expected type of the expression. Here is an example of what I mean.
Dim table as datatable
adapter.fill(table)
dim strinfo as string
dim intinfo as long
strinfo = ncc(table.Rows(0).Item(0),gettype(String)) 'here a string is expected
intinfo = ncc(table.Rows(0).Item(0),gettype(Long)) 'here a long is expected
It would be so much more efficient if it were possible to access the expected type directly from the function.
Something like this would be great:
Public Function ncc(obj As Object, optional tp As Type = nothing) As Object
If tp Is Nothing Then tp = gettype(ncc.expectedtype)
That way I do not have to hard code the type on each line.
strinfo = ncc(table.Rows(0).Item(0))
You can make the ncc function generic to simplify calling it:
Public Function ncc(Of T)(obj As T) As T
If DbNull.Value.Equals(obj) Then Return Nothing
Return Obj
End Function
This kind of function will be able to in some cases infer the type, but if there's any possibility of null you'll still want to include a type name (because DBNull will be the inferred type for those values). The advantage is not needing to call gettype() and so gaining a small degree of type safety:
strinfo = ncc(Of String)(table.Rows(0).Item(0))
But I think this has a small chance to blow up at run time if your argument is not implicitly convertible to the desired type. What you should be doing is adding functions to accept a full row and return a composed type. These functions can exist as static/shared members of the target type:
Shared Function FromDataRow(IDataRow row) As MyObject
And you call it for each row like this:
Dim record As MyObject = MyObject.FromDataRow(table.Rows(i))
But, you problem still exists.
What happens if the column in the database row is null?
then you DO NOT get a data type!
Worse yet? Assume the data column is null, do you want to return null into that variable anyway?
Why not specify a value FOR WHEN its null.
You can use "gettype" on the passed value, but if the data base column is null, then you can't determine the type, and you right back to having to type out the type you want as the 2nd parameter.
You could however, adopt a nz() function (like in VBA/Access).
So, this might be better:
Public Function ncc(obj As Object, Optional nullv As Object = Nothing) As Object
If obj Is Nothing OrElse IsDBNull(obj) Then
Return nullv
End If
Return obj
End Function
So, I don't care if the database column is null, or a number, for such numbers, I want 0.
So
dim MyInt as integer
Dim MyDouble As Double
MyInt = ncc(rstData.Rows(0).Item("ContactID"), 0)
MyDouble = ncc(rstData.Rows(0).Item("ContactID"), 0)
dim strAddress as string = ""
strAddress = ncc(rstData.Rows(0).Item("Address"), "")
Since in NEAR ALL cases, you need to deal with the null from the DB, then above not only works for all data types, but also gets you on the fly conversion.
I mean, you CAN declare variables such as integer to allow null values.
eg:
dim myIntValue as integer?
But, I not sure above would create more problems than it solves.
So,
You can't get exactly what you want, because a function never has knowledge of how it's going to be used. It's not guaranteed that it will be on the right-hand side of an assignment statement.
If you want to have knowledge of both sides, you either need to be assigning to a custom type (so that you can overload the assignment operator) or you need to use a Sub instead of an assignment.
You could do something like this (untested):
Public Sub Assign(Of T)(ByVal field As Object, ByRef destination As T,
Optional ByVal nullDefault As T = Nothing)
If TypeOf field Is DBNull Then
destination = nullDefault
Else
destination = CType(field, T)
End If
End Sub
I haven't tested this, so I'm not completely certain that the compiler would allow the conversion, but I think it would because field is type Object. Note that this would yield a runtime error if field is not convertible to T.
You could even consider putting on a constraint requiring T to be a value type, though I don't think that would be likely to work because you probably need to handling String which is a reference type (even though it basically acts like a value type).
Because the destination is an argument, you wouldn't ever need to specify the generic type argument, it would be inferred.
I'm made a new list of string and when I try to add something there it gives me an error: Argument 'Prompt' cannot be converted to type 'string
My code:
Dim variables As New List(Of String)
Try
variables.Append(CStr(TextBox1.Text))
variables.Append(CStr(TextBox2.Text))
MsgBox(variables)
Catch ex As Exception
MsgBox(ex.Message)
End Try
How can I fix that?
The error is coming from your use of MsgBox(). You're passing it the variables variable, and it doesn't know how to convert a List(Of String) to a String.
As stated by jmcilhinney, you should be using Add() instead of Append().
Additionally, you should use MessageBox.Show() instead of MsgBox().
As for the error, we can only assume you want to see all the current values in your List? If so, one solution is to use String.Join() and display that instead:
Dim variables As New List(Of String)
variables.Add(TextBox1.Text)
variables.Add(TextBox2.Text)
MessageBox.Show(String.Join(",", variables))
But your variables list should be declared at Form level so that you aren't creating a new one each time. It isn't clear from your post if this is the case or not.
You should be calling the Add instance method of your List(Of String). Append is an extension method and is not appropriate in that scenario. Append would be used for an enumerable list that you wanted to enumerate on the spot, e.g.
Dim names = {"Peter", "Paul", "Mary"}
Dim pNames = names.Where(Function(name) name.StartsWith("P"))
For Each pName In pNames.Append("Philip")
Console.WriteLine(pName)
Next
In that case the Append only affects the list being enumerated by the loop where it's used. The original list is unaffected.
You should be using the Add method:
Dim variables As List(Of String) = New List(Of String)
variables.Add(TextBox1.Text)
(No need for the redundant CStr as TextBox1.Text is already of type String.)
As #Mary will no doubt suggest - rightly! - always have Option Explicit and Option Strict set to On (and in my opinion Option Infer Off); it'll help you with any syntax issues.
And always pay attention to the syntax/compiler suggestions in the left margin which will give you clues/tips to fix or improve your code.
Lastly, refer to the Microsoft documentation if in doubt. It should be your first port-of-call if you're unsure of anything.
As several people have mentioned, use the .Add method not .Append.
The .Text property of a TextBox is already a String. No need to convert with CStr().
A message box displays a String. variables is not a String; it is a List(Of String). To see what is in your list use a For Each loop.
Private Sub OpCode()
Dim variables As New List(Of String)
variables.Add(TextBox1.Text)
variables.Add(TextBox2.Text)
For Each s In variables
MsgBox(s)
Next
End Sub
#SteveCinq is correct :-); turn on Option Strict.
**I hav problem when i use DataGridView1 with thread
i get empty rows like image **
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim thread As New Thread(AddressOf grid)
thread.Start()
End Sub
Public Function grid()
For i As Int16 = 1 To 50
Invoke(Sub()
DataGridView1.Rows.Add(i)
DataGridView1.Refresh()
End Sub)
Next
End Function
https://i.stack.imgur.com/KOXRR.jpg
This is a perfect example of why you MUST read the relevant documentation, especially if something doesn't work the way you expect. If you had bothered to read the documentation for the Add method you're calling here then you'd have seen that that particular overload adds the specific number of rows to the grid and that's all. At no point does it populate those rows with any data. The code you have is going to add 1+2+3+4+...+48+49+50 empty rows to your grid. If what you actually want is to add a single row each time where i is the data displayed in that row then you need to call one of the overloads of Add that does that, or else call the overload with no arguments to add a single row, then get that row and set the Value of a cell explicitly.
EDIT: The simplest way to add a row with i as data is to call the overload of Add that takes an array of cell values. If you only have one cell, you use an array with one element:
DataGridView1.Rows.Add({i})
The braces indicate that the contents is an array. It's shorthand for this:
DataGridView1.Rows.Add(New Integer() {i})
Note that, if you pass a single Integer, the overload with a single Integer parameter will be called as it's the closest match. If you were to pass multiple discrete Integers, e.g.
DataGridView1.Rows.Add(i, i)
then you would not have the same problem because there is no overload with multiple Integer parameters. In that case, the overload that takes an array of Objects would be called. That overload's parameter is declared ParamArray, which means that you can pass either multiple individual objects or a single array. Another option would be to cast your Integer as type Object, which would also cause the overload that takes an array of Objects to be called:
DataGridView1.Rows.Add(CObj(i))
When you call an overloaded method, the closest valid match will be called, so be sure that your arguments match the parameters of the overload you want to call and make sure you understand what each overload does. ALWAYS read the documentation if you aren't 100% sure. The F1 key and the Help menu are there for a reason.
In declaration of variables and objects, when exactly should I use "New" word, and when shouldn't I use it?
I know that I should declare a string without "New" word:
Dim mystring As String
I also know I should use it declaring a datatable:
Dim mytable As New Datatable()
New creates an object that is an instance of the specified class. If you just write the following then you have a reference, but the reference is Nothing as you didn't actually create a Datatable for it to refer to:
Dim mytable As Datatable
You don't typically use New for value types (Numbers, Dates, Booleans, Structures, Enums - a full list is here), as they always have a value (cannot be Nothing). For example this outputs 0:
Dim num as Int32
Console.WriteLine(num)
I wouldn't worry too much about this, but some value types (structures) can be initialised with New, which is somewhat inconsistent, for example:
Dim dec = New Decimal(2, 3, 4, True, 5)