Is it possible to display the contents of a two dimensional array vertically on a form in vb.net using listview, and if so how would I do it?
So, if my array is declared as
dim myarray (2,10) how would I display the contents vertically in listview. All and any help much apprciated, thank you.
This method should do the trick for you (I have assumed we are talking about a winforms app, but I realize that it could just as well be an ASP.NET app, in which case my answer might no longer be applicable):
Private Sub ShowArrayInListView(ByVal listView As ListView, ByVal dataArray As String(,))
listView.Items.Clear()
For y As Integer = dataArray.GetLowerBound(1) To dataArray.GetUpperBound(1)
Dim lvi As New ListViewItem
For x As Integer = dataArray.GetLowerBound(0) To dataArray.GetUpperBound(0)
If x = 0 Then
lvi.Text = dataArray(x, y)
Else
lvi.SubItems.Add(dataArray(x, y))
End If
Next
listView.Items.Add(lvi)
Next
End Sub
Every control like ListView in .NET has a marvelous template mechanism what you can use to put HTML inside of it. Moreover you can handle ItemDataBound event and fill a Label located inside the ItemTemplate section of your control with HTML code. Then, use a nested loop to generate your <tr> and <td>, place them on a string and assign it to the Label.Text property.
Hope that helps,
Related
Sorry this is weird and silly question but I need a solution of this...
I have 30 textboxes named as Txt1,Txt2,Txt3,...,Txt30
I have to fill textbox as Txt1.text = 0 on button click..
Is there any way like On Button Click
Dim i as Integer
For i = 1 to 30 '----- Possible in string but don't know if possible in textboxes
Txt(i).text = 0
Next
Or I have to write all 30 lines like
Txt1.text = 0
...
Txt30.text = 0
I don't know how this question asked, maybe Question improper.
Thanx in Advance...
If the textboxes are all contained in Controls collection of the Form, then it is really easy to loop over them
For Each(t in Me.Controls.OfType(Of TextBox)())
t.Text = "0"
Of course the advantage of this approach is that you don't have to worry if you add other textboxes to your form. They will be found using the foreach loop without having a fixed top limit.
And, if not all of your textboxes should be included in the loop, then you can simply use the Tag property of the textboxes that you want to use. For example, if you set the Tag property to the string "Y", then you can change the foreach loop to find only the controls with the matching Tag property
For Each t in Me.Controls.OfType(Of TextBox)() _
.Where(Function(x) x.Tag = "Y")
t.Text = "0"
The two solutions above works well if all your textboxes are contained in the same container (Form, GroupBox or Panel), instead, if these textboxes are dispersed in different containers (some in a groupbox, others in a panel etc) then you can build a List(Of TextBox) variable filling it with the textboxes instances and use it when the need arise
Dim myTexts = New List(Of TextBox)() From { Txt1, Txt2, Txt3, ....}
And loop over this variable
You can do as Steve said, but if you have other textboxes that you don't want to edit then there is another way:
For i = 1 to 30
dim found = Me.Controls.Find("Txt" & i, True) '<- the True argument is for recursive search
If Not IsNothing(found) AndAlso found.Length > 0 Then
found(0).Text = "0"
End If
Next
If your textboxes are all in the same control, for example GroupBox, you can do GroupBox.Controls.Find saving CPU resources
I made a custom DataGridViewColumn control together with its DataGridViewCell controls.
The idea is to dynamically create the contents of the cell, which consists of a series of clickable function buttons, upon databinding. The number and kinds of buttons depend on the data value passed.
For this, I override the Paint method of the DataGridViewCell and check the formattedValue on its contents and draw buttons accordingly. However, these buttons are "dead" and not clickable, so the question is how to make them clickable, i.e. how do I add a handler for the click event?
Do I have to override the cell's OnClick method and then try to pinpoint which button exactly is clicked? Is this even possible? Are there better ways?
This is what I've got so far:
Protected Overrides Sub Paint(graphics As Graphics, clipBounds As Rectangle, cellBounds As Rectangle, rowIndex As Integer, cellState As DataGridViewElementStates, value As Object, formattedValue As Object, errorText As String, cellStyle As DataGridViewCellStyle, advancedBorderStyle As DataGridViewAdvancedBorderStyle, paintParts As DataGridViewPaintParts)
MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts)
Dim cellBackground As New SolidBrush(cellStyle.BackColor)
graphics.FillRectangle(cellBackground, cellBounds)
cellBackground.Dispose()
PaintBorder(graphics, clipBounds, cellBounds, cellStyle, advancedBorderStyle)
Dim sValue As String = formattedValue.ToString()
If (sValue.Contains("ViewAsPDF")) Then
Dim buttonArea As Rectangle = cellBounds
Dim buttonAdjustment As Rectangle = Me.BorderWidths(advancedBorderStyle)
buttonArea.X += buttonAdjustment.X
buttonArea.Y += buttonAdjustment.Y
buttonArea.Height -= buttonAdjustment.Height
buttonArea.Width -= buttonAdjustment.Width
buttonArea.Width = buttonArea.Width / 4
ButtonRenderer.DrawButton(graphics, buttonArea, PushButtonState.Default)
TextRenderer.DrawText(graphics, "PDF", Me.DataGridView.Font, buttonArea, SystemColors.ControlText)
End If
'etcetera
End Sub
I think you may have wandered down the wrong road. Based on the code provided, you are simply drawing the cells to look like they contain buttons. Since they are not actually objects, they are incapable of raising events.
I don't understand ButtonRenderer, if you can't create actual Buttons with it
The ButtonRender does not create a new button object, it is meant to be used by Button objects for drawing. Often a subclassed a button, will not use it because it employs the existing theme and style which is may be what a you wants to do differently (even the DataGridViewButtonCell does not use it -- at least not directly).
From the code provided, it seems to work out each button on the fly each time rather than drawing from some collection or definition. What if the "action" list needs to vary based on the row (e.g. different actions for a DOC, XLS or Image row)? Doing so, would seem to take a great deal of code.
Your current course may not be impossible, but it is not trivial either. You might be able to create a collection of virtual buttons (basically the Rect from when it was drawn) and render them as you have done. Then in the cell-click event, translate/adjust the X position to see which rectangle contains thisPt.X to determine which related action to take.
There are "issues" still such as what happens when the user resizes the column? What about when the button list varies by some other cell value (DOC vs XLS vs IMG vs PDF)? This would require a collection of button sets...and a fair amount of code.
This is not to say it cant be done, but it seems like a great deal of code would be required to make it even a little flexible.
Are there better ways?
I think so.
A simpler, existing solution might be to use the existing DataGridViewComboBoxColumn to store "Actions" or "Activities". It seems a bit less cluttered and more user friendly:
It takes only a small amount of code to provide a different list for each animal:
' dogs like to go for walks
Private ActsCan() As String = {"Feed", "Pet", "Bathe", "Brush", "Take for Walk"}
' no walks or baths for cats
Private ActsFel() As String = {"Feed", "Pet", "Baby-Talk To", "Brush"}
' never bathe a Mugwai, comb rather than brush
Private ActsMug() As String = {"Feed", "Pet", "Baby-Talk To", "Comb"}
Private ActsGrem() As String = {"Hide From", "Strangle"}
...
Private Sub dgv_RowEnter(sender As Object,
e As DataGridViewCellEventArgs) Handles dgv.RowEnter
Dim dgvCBO As DataGridViewComboBoxCell
dgvCBO = CType(dgv.Rows(e.RowIndex).Cells("ColActs"), DataGridViewComboBoxCell)
dgvCBO.Items.Clear()
Select Case dgv.Rows(e.RowIndex).Cells("colSpecies").Value.ToString
Case "Canine"
dgvCBO.Items.AddRange(ActsCan)
Case "Feline"
dgvCBO.Items.AddRange(ActsFel)
Case "Mugwai"
dgvCBO.Items.AddRange(ActsMug)
Case "Gremlin"
dgvCBO.Items.AddRange(ActsGrem)
End Select
End Sub
A class to encapsulate most of that might be nice for unbound DGVs. It could be optimized not to rebuild the list when the trigger value for thisRow is the same as the last.
What about this approach. Only implementing the ui.
I am trying to make the reversi game in VB.Net. I have some difficulties translating the game`s logic into vb.net
If a button is black and the button next to it is white,than the button next to the white one will be black wen pressed.
newButton.tag = colum of button + (row of button * amount of columns)
-> I made 64 buttons via a function loop and added a tag
Dim knop As Button = sender
Dim value As String = knop.Tag
If value = "...(?)" Then
knop.BackColor = Color.Black
If ....(?)
End If
End If
I already made a scheme with the label of the buttons, but I find it hard to implement the logic. Can someone help me out with thid one?
EDIT: http://i.stack.imgur.com/3gdrJ.png
If you use Dim ButtonList As List(Of List(Of Button)) and add the buttons to the form in runtime you can add each the button for each row to a list then add that list to ButtonList. Now you can access each button by the indexes in the 2 dimensional list.
Since you're changing the backcolor just use that instead of using the tag.
How do I get the SuspendLayout and ResumeLayout to work correctly in regards to a listview. I have added these lines of code before and after I have added the items, yet each item is still being displayed as I add each item.
thanks
My code:
Dim x As Integer
Dim startTick As Integer = Environment.TickCount
lstFiles.SuspendLayout()
For x = 0 To UBound(cacheListArray)
If cacheListArray(x) Like "*.txt" Then
lstFiles.Items.Add(cacheListArray(x))
End If
Next
lstFiles.ResumeLayout()
MsgBox(Environment.TickCount - startTick)
I am adding 2000 items. This takes 7 seconds. I was told that it should be a lot shorter than that. Is that correct?
New code:
Dim ListViewItemArray(-1) As ListViewItem
ReDim Preserve ListViewItemArray(UBound(ListViewItemArray) + 1)
ListViewItemArray(UBound(ListViewItemArray)).Text = file.Name
ListViewItemArray(UBound(ListViewItemArray)).SubItems.Add(file.FullName)
ListViewItemArray(UBound(ListViewItemArray)).SubItems.Add(file.Length)
ListViewItemArray(UBound(ListViewItemArray)).SubItems.Add(file.CreationTime)
ListViewItemArray(UBound(ListViewItemArray)).SubItems.Add(file.LastWriteTime)
ListViewItemArray(UBound(ListViewItemArray)).SubItems.Add(file.LastAccessTime)
lstFiles.Items.AddRange(ListViewItemArray)
Nothing is being added. What have I done incorrectly?
You are using the wrong method. The Suspend/ResumeLayout() methods are only appropriate for container controls whose child controls you want to move around without them getting repainted while you are doing so. You never give ListView any child controls.
Use the Begin/EndUpdate() methods instead.
I have a combobox with a given width.
It may occur that one row of the data is partially hidden (the combobox might be too narrow). I'd like to show the whole line by using a tooltip or right-click context menu.
Currently I can't find how to 'catch' the row that I'm currently holding on or passing over by mouse. Please tell me.
Thanks in advance!
Have you tried to increase the DropDownWidth property so that everything is visible?
Edit: To find the ideal width based on the items in the list:
var maxLength = 0;
// using the ComboBox to get a Graphics object:
using (var g = Graphics.FromHwnd(comboBox2.Handle)) {
foreach (var item in comboBox2.Items.Cast<string>()) {
var itemLength = g.MeasureString(item, comboBox2.Font);
maxLength = Math.Max((int) itemLength.Width, maxLength);
}
}
if (comboBox2.Items.Count > comboBox2.MaxDropDownItems) {
// correction when ScrollBar is displayed
maxLength += 15;
}
comboBox2.DropDownWidth = maxLength;
I put this code in the DropDown event of the ComboBox for testing. Maybe you can find a better place for it, like after populating the ComboBox...
Going in the same direction that Julien went, here is a generic extension method that will resize the drop down area regardless of how the combobox is filled (manually with strings or via data binding).
<Extension()> _
Public Sub AutosizeDropDownWidth(ByVal combobox As ComboBox)
Dim longestItem As Integer = 0
Using g = Graphics.FromHwnd(combobox.Handle)
Dim itemsAsText = (From item In combobox.Items _
Select combobox.GetItemText(item))
longestItem = CInt(itemsAsText.Max(Function(text) g.MeasureString(text, combobox.Font).Width))
End Using
' Account for scrollbar
If (combobox.Items.Count > combobox.MaxDropDownItems) Then longestItem += 15
' Resize as needed (but never smaller than the default width)
combobox.DropDownWidth = Math.Max(longestItem, combobox.Width)
End Sub
To use it then you can simply do the following...
Private Sub MyCombobox_DropDown(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyCombobox.DropDown
MyCombobox.AutosizeDropDownWidth()
End Sub
Note, I didn't test corner cases like an empty combobox in this code example.
Your're right, there really isn't a "Item.OnMouseOver", but I suppose you could (off the top of my head, so I've likely forgotten something)...
inherit from ComboBox,
override OnDrawItem (you may need to turn change .DrawMode to "Owner Drawn").
you will know which item is hovered in the OnDrawItem event/override from the EventArgs.
Set the tooltip on the control at that point.
optionally set a timer to manually show the tooltip if the above doesn't work automatically.