Conviene que no interactues con el control para construir las columnas y filas, en su lugar puedes definir un DataTable y construir la tabla allí, y entonces usar la propiedad DataSource del DataGridView. Recuerda, cuanta menos interacción directa exista por parte de tu código con los controles, mejor.
He extendido mucho (realmente mucho) el siguiente ejemplo, pero bueno, así es como lo haría yo:
Primeramente, definimos un type para almacenar y/o generar secuencias numéricas aleatorias. Aparte de servirnos para la representación epxlícita de este tipo de secuencias numéricas, otra diferencia (o ventaja) entre una colección List(Of Integer()) y esto, es que podremos reutilizarlo para muchos otros propósitos en el futuro:
Ejemplo de uso:
Seguidamente, definimos un segunto Type donde implementaremos las interfaces IFormatProvider y ICustomFormatter, y así desarrollaremos el algoritmo de formateo para representar en texto horizontal o vertical una secuencia numérica. La gran ventaja de desarrollar nuestro propio proveedor de formato es que se puede adaptar para utilizarlo de mil formas distintas, en cientos de situaciones diferentes.
Ejemplo de uso:
Nota:
En el el type RandomSequence no necesitaremos utilizarlo pasando tantos argumentos, lo acortaremos a RandomSequence.Value("H") y RandomSequence.Value("V").
Por último, solo nos queda hacer uso de todo esto para construir la tabla y representarla en el control DataGridView:
Nótese que el contenido de las celdas se formatean controlando el evento DataGridView1.CellFormatting, esto es algo ilustrativo y opcional, se puede contruir la data-table con las celdas ya formateadas para no tener que hacerlo después controlando ese evento, pero veo de mayor utilidad tener un data-table de RandomSequence, que de Strings multilinea...
Resultado de ejecución:
Saludos!
He extendido mucho (realmente mucho) el siguiente ejemplo, pero bueno, así es como lo haría yo:
Primeramente, definimos un type para almacenar y/o generar secuencias numéricas aleatorias. Aparte de servirnos para la representación epxlícita de este tipo de secuencias numéricas, otra diferencia (o ventaja) entre una colección List(Of Integer()) y esto, es que podremos reutilizarlo para muchos otros propósitos en el futuro:
Código (vbnet) [Seleccionar]
Public Class RandomSequence
Protected Shared ReadOnly rand As New Random()
Public ReadOnly Property Value As Integer()
Get
Return Me.valueB
End Get
End Property
Protected valueB As Integer()
Public ReadOnly Property Value(ByVal format As String) As String
Get
Return Me.ToString(New IntegerSequenceFormatter(), format)
End Get
End Property
Public ReadOnly Property Length As Integer
Get
Return Me.lengthB
End Get
End Property
Protected lengthB As Integer
Private Sub New()
End Sub
Protected Friend Sub New(ByVal value As Integer())
Me.valueB = value
Me.lengthB = value.Length
End Sub
Protected Friend Sub New(ByVal length As Integer)
Me.valueB = Me.GenerateSequence(length).ToArray()
Me.lengthB = length
End Sub
Protected Friend Sub New(ByVal length As Integer, ByVal minValue As Integer, ByVal maxValue As Integer)
Me.valueB = Me.GenerateSequenceInternal(length, minValue, maxValue).ToArray()
Me.lengthB = length
End Sub
Public Overridable Function GenerateSequence(ByVal length As Integer) As Integer()
Me.valueB = Me.GenerateSequenceInternal(length, minValue:=0, maxValue:=Integer.MaxValue).ToArray()
Return Me.valueB
End Function
Public Overridable Function GenerateSequence(ByVal length As Integer, ByVal minValue As Integer, ByVal maxValue As Integer) As Integer()
Me.valueB = Me.GenerateSequenceInternal(length, minValue, maxValue).ToArray()
Return Me.valueB
End Function
Protected Iterator Function GenerateSequenceInternal(ByVal length As Integer, ByVal minValue As Integer, ByVal maxValue As Integer) As IEnumerable(Of Integer)
For i As Integer = 0 To (length - 1)
Yield rand.Next(minValue, maxValue)
Next i
End Function
Public Overrides Function Equals(ByVal obj As Object) As Boolean
If (TypeOf obj IsNot RandomSequence) Then
Return False
Else
Return String.Join(" ", Me.valueB).Equals(String.Join(" ", DirectCast(obj, RandomSequence).valueB))
End If
End Function
Public Overridable Shadows Function ToString(ByVal formatProvider As IFormatProvider, ByVal format As String) As String
If (TypeOf formatProvider Is ICustomFormatter) Then
Return DirectCast(formatProvider, ICustomFormatter).Format(format, Me.valueB, formatProvider)
ElseIf (formatProvider IsNot Nothing) Then
Return formatProvider.ToString()
Else
Return Me.valueB.ToString()
End If
End Function
<EditorBrowsable(EditorBrowsableState.Never)>
Public Overridable Shadows Function GetHashCode() As Integer
Return MyBase.GetHashCode()
End Function
<EditorBrowsable(EditorBrowsableState.Never)>
Public Overridable Shadows Function [GetType]() As Type
Return MyBase.GetType()
End Function
<EditorBrowsable(EditorBrowsableState.Never)>
Public Shared Shadows Function ReferenceEquals(ByVal objA As Object, ByVal objB As Object) As Boolean
Return Object.ReferenceEquals(objA, objB)
End Function
End Class
Ejemplo de uso:
Código (vbnet) [Seleccionar]
Dim seq1 As New RandomSequence(length:=3) ' minValue:=0, maxValue:=Integer.MaxValue
Dim seq2 As New RandomSequence(length:=3, minValue:=0, maxValue:=100)
Dim seq3 As New RandomSequence({1, 2, 3})
Console.WriteLine(seq1.Length)
Console.WriteLine(seq1.Equals(seq2))
Console.WriteLine(seq1.Value.ToString())
Console.WriteLine(seq1.Value("Horizontal")) ' o "H"
Console.WriteLine(seq1.Value("Vertical")) ' o "V"
Seguidamente, definimos un segunto Type donde implementaremos las interfaces IFormatProvider y ICustomFormatter, y así desarrollaremos el algoritmo de formateo para representar en texto horizontal o vertical una secuencia numérica. La gran ventaja de desarrollar nuestro propio proveedor de formato es que se puede adaptar para utilizarlo de mil formas distintas, en cientos de situaciones diferentes.
Código (vbnet) [Seleccionar]
Public Class IntegerSequenceFormatter : Implements IFormatProvider, ICustomFormatter
Public Function GetFormat(formatType As Type) As Object Implements IFormatProvider.GetFormat
If formatType Is GetType(ICustomFormatter) Then
Return Me
Else
Return Nothing
End If
End Function
Public Function Format(fmt As String, arg As Object, formatProvider As IFormatProvider) As String Implements ICustomFormatter.Format
If Not Me.Equals(formatProvider) Then
Return Nothing
End If
If String.IsNullOrEmpty(fmt) Then
Dim result As Integer() = TryCast(arg, Integer())
If (result Is Nothing) Then
Throw New ArgumentException("Value is not of type Integer()", paramName:="arg")
Exit Function
End If
End If
If String.IsNullOrEmpty(fmt) Then
Throw New ArgumentNullException(paramName:="fmt")
Exit Function
End If
Select Case fmt.ToLower()
Case "h", "horizontal"
Dim seq As Integer() = DirectCast(arg, Integer())
Dim maxLength As Integer = CStr(seq.Max()).Length
Dim sb As New StringBuilder(capacity:=seq.Length * maxLength)
For Each item As Integer In seq
sb.Append(item.ToString().PadLeft(maxLength, "0"c))
sb.Append(" "c)
Next
Return sb.ToString.TrimEnd(" "c)
Case "v", "vertical"
Dim seq As Integer() = DirectCast(arg, Integer())
Dim maxLength As Integer = CStr(seq.Max()).Length
Dim sb As New StringBuilder(capacity:=seq.Length * maxLength)
For Each item As Integer In seq
sb.AppendLine(item.ToString().PadLeft(maxLength, "0"c))
Next
Return sb.ToString()
Case Else
Throw New FormatException(String.Format("'{0}' cannot be used to format {1}.", fmt, arg.ToString()))
End Select
End Function
End Class
Ejemplo de uso:
Código (vbnet) [Seleccionar]
Dim arr As Integer() = {1, 2, 3, 4, 5}
Dim strHorz As String = String.Format(New IntegerSequenceFormatter, "{0:H}", arr)
Dim strVert As String = String.Format(New IntegerSequenceFormatter, "{0:V}", arr)
Console.WriteLine(strHorz)
Console.WriteLine(strVert)
Nota:
En el el type RandomSequence no necesitaremos utilizarlo pasando tantos argumentos, lo acortaremos a RandomSequence.Value("H") y RandomSequence.Value("V").
Por último, solo nos queda hacer uso de todo esto para construir la tabla y representarla en el control DataGridView:
Código (vbnet) [Seleccionar]
Public Class Form1 : Inherits Form
Dim seqList As New List(Of RandomSequence)
Dim seqTable As New DataTable("RandomSequenceTable")
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim seqCount As Integer = 20 ' Amount of random sequences to generate.
' Build random sequences list. This is optional, just to have a short reference to a generic collection in source-code.
For i As Integer = 0 To (seqCount - 1)
seqList.Add(New RandomSequence(length:=16, minValue:=0, maxValue:=16))
Next
' Build table from list.
For x As Integer = 0 To (seqList.Count - 1)
seqTable.Columns.Add(New DataColumn)
seqTable.Columns(x).DataType = GetType(RandomSequence)
Next
seqTable.Rows.Add.ItemArray = seqList.ToArray()
' To build a data-table of vertical strings representation:
' seqTable.Rows.Add.ItemArray = (From seq As RandomSequence In seqList Select seq.Value("V")).ToArray()
seqTable.AcceptChanges()
' Build grid.
DataGridView1.SuspendLayout()
With DataGridView1
.AllowUserToAddRows = False
.AllowUserToResizeColumns = False
.AutoGenerateColumns = True
.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.DisplayedCells
.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.DisplayedCells
.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableWithoutHeaderText
.ColumnHeadersVisible = False
.DefaultCellStyle.Padding = New Padding(5, 2, 5, 2)
.DefaultCellStyle.WrapMode = DataGridViewTriState.True
.MultiSelect = True
.ReadOnly = True
.RowHeadersVisible = False
.RowsDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
.Size = New Size(New Point(400, 240))
End With
DataGridView1.DataSource = seqTable
DataGridView1.ResumeLayout()
End Sub
Private Sub DataGridView1_CellFormatting(ByVal sender As Object, ByVal e As DataGridViewCellFormattingEventArgs) _
Handles DataGridView1.CellFormatting
If (e.Value IsNot Nothing) Then
Dim item As RandomSequence = TryCast(e.Value, RandomSequence)
If (item IsNot Nothing) Then
e.Value = item.Value("Vertical")
End If
End If
End Sub
End Class
Nótese que el contenido de las celdas se formatean controlando el evento DataGridView1.CellFormatting, esto es algo ilustrativo y opcional, se puede contruir la data-table con las celdas ya formateadas para no tener que hacerlo después controlando ese evento, pero veo de mayor utilidad tener un data-table de RandomSequence, que de Strings multilinea...
Resultado de ejecución:
Saludos!