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.
Related
Although I'm reasonable experienced VBA developer, I have not had the need to use class modules or collections but thought this may be my opportunity to extend my knowledge.
In an application I have a number of forms which all have the same functionality and I now need to increase that functionality. Towards that, I am trying to reorder a collection in a class module, but get an error 91 - object variable or with block not set. The collection is created when I assign events to controls. The original code I obtained from here (Many thanks mwolfe) VBA - getting name of the label in mousemove event
and has been adapted to Access. The assignments of events works well and all the events work providing I am only doing something with that control such as change a background color, change size or location on the form.
The problem comes when I want to reorder it in the collection - with a view to having an impact on location in the form. However I am unable to access the collection itself in the first place.
The below is my latest attempt and the error occurs in the collcount Get indicated by asterisks (right at the bottom of the code block). I am using Count as a test. Once I understand what I am doing wrong I should be able to manipulate it as required.
mLabelColl returns a correct count before leaving the LabelsToTrack function, but is then not found in any other function.
As you will see from the commented out debug statements, I have tried making mLabelColl Private and Dim in the top declaration, using 'Debug.Print mLabelColl.Count' in the mousedown event and trying to create a different class to store the list of labels.
I feel I am missing something pretty simple but I'm at a loss as to what - can someone please put me out of my misery
Option Compare Database
Option Explicit
'weMouseMove class module:
Private WithEvents mLbl As Access.Label
Public mLabelColl As Collection
'Dim LblList as clLabels
Function LabelsToTrack(ParamArray labels() As Variant)
Set mLabelColl = New Collection 'assign a pointer
Dim i As Integer
For i = LBound(labels) To UBound(labels)
'Set mLabelColl = New Collection events not assigned if set here
Dim LblToTrack As weMouseMove 'needs to be declared here - why?
Set LblToTrack = New weMouseMove 'assign a pointer
Dim lbl As Access.Label
Set lbl = labels(i)
LblToTrack.TrackLabel lbl
mLabelColl.Add LblToTrack 'add to mlabelcoll collection
'Set LblList as New clLabels
'LblList.addLabel lbl
Next i
Debug.Print mLabelColl.Count 'returns correct number
Debug.Print dsform.countcoll '1 - incorrect
End Function
Sub TrackLabel(lbl As Access.Label)
Set mLbl = lbl
End Sub
Private Sub mLbl_MouseDown(Button As Integer, Shift As Integer, x As Single, Y As Single)
Dim tLbl As Access.Label
'Debug.Print LblList.Count 'Compile error - Expected function or variable (Despite Count being an option
'Debug.Print mLabelColl.Count 'error 91
'Debug.Print LblList.CountLbls 'error 91
Debug.Print collCount
End Sub
Property Get collCount() As Integer
*collCount = mLabelColl.Count* 'error 91
End Property
In order to have all the weMouseMove objects reference the same collection in their mLabelColl pointer, a single line can achieve it:
LblToTrack.TrackLabel lbl
mLabelColl.Add LblToTrack
Set LblToTrack.mLabelColl = mLabelColl ' <-- Add this line.
But please be aware that this leads to a circular reference between the collection and its contained objects, a problem that is known to be a source of memory leaks, but this should not be an important issue in this case.
Not sure if my title makes much sense, so I will try to explain my question here. So basically I am expanding my program by allowing things to be customized within it.
Say for example I do this: I click on File -> Options, and a new form is opened with tabs. I have different settings that you can toggle via dropdown box and checkboxes. Now once a user sets the settings they want, or don't want, they click on a button that says either "OK" or "Cancel".
What is the method to saving these settings, or reverting back to the original settings? Do you save via txt file, or is this a default function within a certain line of code?
UPDATE:
So I fixed my previous issue. Now I am having another with the saves. The saves are working good, but I want to use them in selecting my CheckListBox Collection range and also have that range load on start as well. so these are the 2 things that I have been using to do so, that results in adding to the previous, set, collection.
Working for RNG:
Dim rand As New Random()
Dim winners = Enumerable.Range(1, My.Settings.numberSetting).OrderBy(Function(r) rand.Next()).Take(5).ToArray()
Not working for Onload CheckListBox:
Me.LotteryNumbers.Items.Add(1, My.Settings.numberSetting)
If I remove the 1 from Me.LotteryNumbers.Items.Add, the result is this:
This ought not compile:
LotteryNumbers.Items.Add(1, My.Settings.numberSetting)
The overload which takes a second argument expect a Boolean to set the item added to Checked or not. One way is to add items in a loop:
Dim maxNums = My.Settings.numberSetting
' make sure it is empty
clb.Items.Clear()
For n As Int32 = 1 To maxNums
clb.Items.Add(n.ToString)
Next
I don't like using items in Settings as variables, so it grabs the current value to use. Another way uses AddRange:
clb.Items.AddRange(Enumerable.Range(1, maxNums).Select(Function(s) s.ToString()).ToArray())
Items is an collection of Object, so the Select converts to string to add them.
NEVER ORDER BY RANDOM.NEXT()
Mostly you get lucky, but it's not guaranteed. It's only a matter of time before that code blows up on you at run time. The longer the sequence to be sorted, the more likely you are to get an exception.
What you should do instead is implement a Fisher-Yates sort method:
Private rand As New Random()
Public Function Shuffle(Of T)(ByVal items As IList(Of T)) As IList(Of T)
For i As Integer = items.Count - 1 To 1 Step -1
Dim j As Integer = rand.Next(i + 1)
Dim temp As T= items(i)
items(i) = items(j)
items(j) = temp
Next
Return items
End Function
Solution for the working code to update and save checklistbox box count.
Private Sub OptionOkButton_Click(sender As Object, e As EventArgs) Handles OptionOkButton.Click
Main.LotteryNumbers.Items.Clear()
My.Settings.numberSetting = CInt(NumberCombo.Text)
Dim maxNum = My.Settings.numberSetting
Main.LotteryNumbers.Items.AddRange(Enumerable.Range(1, maxNum).Select(Function(s) s.ToString()).ToArray())
My.Settings.Save()
Me.Close()
End Sub
After reading this question, I wrote some code to create a label for each attribute of an xml element.
The problem is that when I run the project, my form only displays the first label. I've checked in the immediate window as well as debug window and all of the labels are loaded to the form, but none of them are displayed. Help?
Here's the code that runs when the form loads.
Dim doc As New XmlDocument()
doc.Load("xmlfile")
Dim ability As XmlNode = doc.GetElementsByTagName("ability").Item(0)
Dim numberofLabels = ability.Attributes.Count
ReDim labels(numberofLabels)
For counter As Integer = 0 To numberofLabels - 1
labels(counter) = New Label
labels(counter).Visible = True
labels(counter).Text = ability.Attributes.Item(counter).Name
labels(counter).Location = New System.Drawing.Point(10, 30 + counter * 10)
Me.Controls.Add(labels(counter))
Next
You should be using some layout manager, to help you with control positioning. Doing it manually is not worth the pain. Try using TableLayoutPanel or FlowLayoutPanel. Both can be docked or anchored to a parent control, so everything behaves very smoothly. Otherwise you are looking to write a lot of positioning/resizing code, and then maintaining it later.
Change the value of 10 in the original code line for a new point to a bigger value such as 40, so that new labels could appear separated visually:
labels(counter).Location = New System.Drawing.Point(10 + counter, 30 + counter * 40)
This is probably easy as well. But I have this listview which contains exe files I've listed up. Now, I want to execute these exe files in turn from which items are checked or not.
So, I've tried this:
For each item in listView1.CheckedItems
Msgbox item.ToString
Next
Cause I noticed that the item in checkedItems doesn't contain much. And if I convert it to a string, it ends up in the msgbox looking like this: ListViewItem: {Filename.exe}
Now, I want the filename obviously. But is there any other way of extracting the name only? Or do I have to strip the string to remove the ListViewItem: { part away?
Your first step should have been to consult the documentation of ListViewItem to find out how to retrieve the required information from the object.
The Text property is what you’re after.
For Each item in listView1.CheckedItems
MsgBox(item.Text)
Next
For each item in listView1.CheckedItems
Msgbox item.Text
Next
This should work for winforms.
Have you tried Msgbox item.Text?
Your probably lookin for more of something like this. This will have the item and the subitems. You will need a loop with in a loop to accomplish this. Hopes this helps
Dim x As Integer = 0
Dim y As Integer = 0
For Each item In listView1.CheckedItems
For Each subitem In listView1.CheckedItems(y).SubItems
MsgBox(subitem.Text)
x = x + 1
Next
y = y + 1
Next
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,