FindAll does not get all Child Objects in WPFListView using SilkTest 17.5 - vb.net

I need to scroll to an element present in table for a WPF application, the value is dynamically provided during run time.
I have below code which runs fine for small listview as scrollbar moves correctly but does not scroll to elements near the end of a long list.
My list is as below and I scroll using names (A1, A2, ...)
A1 1 3
A2 1 5
S1 1 3
Q2 1 5
.....
.....
Z7 1 3
Z82 1 5
Z9 1 3
Imports SilkTest.Ntf.Wpf
Public Module Main
Dim _desktop As Desktop = Agent.Desktop
Public Sub Main()
Dim iPosition As Double = 0.5
Dim iSumPosition As Double = 0.0
Dim sObjlocator As String = "//WPFListView[#automationId='MyListView']"
Dim sData As String = "Z118"
Dim sObjSublocator As String = "//WPFToggleButton[#caption='*']"
Dim rows As IList = _desktop.WPFListView(sObjlocator).FindAll(sObjSublocator)
Dim sObjExist As Boolean = False
For Each row As WPFToggleButton In rows
Dim sString As String = row.Text
Console.WriteLine(sString) ' <--names
If Trim(sString) = sData Then
sObjExist = True
Exit For
Else
iSumPosition += iPosition
Console.WriteLine(iSumPosition) ' <--Position
_desktop.WPFListView(sObjlocator).ScrollToPosition(iSumPosition, Orientation.Vertical)
End If
Next
End Sub
End Module
Issue:
As shown in the output below, the printed lines A1, A10, ... from Console.WriteLine(sString) and the numbers from Console.WriteLine(iSumPosition), works only for a few objects off-screen, the scrollbar moves vertically down, but if my list is large and I need scroll many times then scrolling doesn't work any more.
The scroll bar does not scroll to the end for names near the end of the list, only if my list is very small then it scrolls down to very last element as well.
In Debug mode I see that the rows list (Dim rows As IList = _desktop.WPFListView(sObjlocator).FindAll(sObjSublocator)) does not have the values (names) for elements near the end of the list.
In the output below, we can see names and positions are printed initially but near the end of the long list only positions are printed.
Output:
A1
0.5
A10
1
A11
1.5
A12
2
...
...
...
9.5
10
10.5
Additional info:
Locator type is WPFScrollBar.
WPF pre-fill forms settings in SilkTest is : yes
Using automation testing tool : Microfocus SilkTest 17.5

You could try using a while loop to continually increase the scroll bar value (to scroll down) until the maximum scroll bar value is met. Below I have put together some sample code that demonstrates this when executed against the WPF sample application that ships with Silk Test.
Imports SilkTest.Ntf.Wpf
Public Module Main
Dim _desktop As Desktop = Agent.Desktop
Public Sub Main()
With _desktop.WPFWindow("#caption='WPF Sample Application'")
.SetActive()
.WPFMenu().Select("/Controls/Basic Controls")
End With
With _desktop.WPFWindow("#caption='Basic Controls'")
.WPFTabControl("#automationId='tabControl'").Select("ScrollBar")
Dim sScrollBar As WPFScrollBar
sScrollBar = .WPFScrollBar("//WPFTabControl[#automationId='tabControl']/WPFScrollBar[2]")
'Set the scroll bar to the top
sScrollBar.SetValue(0.0)
System.Threading.Thread.Sleep(1000)
Dim iPosition As Double
iPosition = 0.0
While sScrollBar.Value < sScrollBar.Maximum
Console.WriteLine("scroll Bar Maximum " + sScrollBar.Maximum.ToString)
Console.WriteLine("scroll Bar Value " + sScrollBar.Value.ToString)
'Set Scroll bar position
sScrollBar.SetValue(iPosition)
'Return text within scroll
Console.WriteLine(.WPFTextBox("#automationId='txtScrollBarEvents'").Text)
'Increment scroll bar position for each iteration
iPosition = iPosition + 0.1
System.Threading.Thread.Sleep(1000)
End While
.Close()
End With
End Sub
End Module

Related

How to display Userform Scrollable Listbox value?

In a userform that I create, I add a scrollable listbox (2 columns, 7 rows) and a button.
When I click the button, the value in the third column should change, and the listbox should display the new value accordingly.
Currently particular rows fail to display the new value even I change it already. I also notice that the rows that fail to display the new value are those not showing in the scrollable list box when I click the button.
When I click the button once, the second column of each row is - as expected - increased by 1:
However, when I click the button a second time, the rows that are not displayed in the scrollable listbox at the moment, fail to increase by 1 again:
This is the code I have so far:
Private Sub CommandButton1_Click()
For i = 0 To lstProducts.ListCount - 1
lstProducts.List(i, 1) = lstProducts.List(i, 1) + 1
Next i
End Sub
Private Sub UserForm_Initialize()
Dim iCell As Long
VBA.Randomize
With lstProducts
.ColumnCount = 2
.ColumnWidths = "120;60;50"
.List = Worksheets("Product").Range("a1").CurrentRegion.Value
End With
End Sub
Replace your loop with this code
x = lstProducts.TopIndex
For i = 0 To lstProducts.ListCount - 1
lstProducts.ListIndex = i
lstProducts.List(i, 1) = lstProducts.List(i, 1) + 1
Next i
lstProducts.ListIndex = x

VB 2-Dimensional Array Item comparison to image

Why does the messagebox show "False"?
Dim images(4, 4) As Image
For rows = 0 To 4
For columns = 0 To 4
images(rows, columns) = My.Resources.kaboom
Next
Next
MessageBox.Show(images(3, 3).Equals(My.Resources.kaboom))
If you look at the code behind the kaboom property, you will see it creates a new object every time.
'''<summary>
''' Looks up a localized resource of type System.Drawing.Bitmap.
'''</summary>
Friend ReadOnly Property kaboom() As System.Drawing.Bitmap
Get
Dim obj As Object = ResourceManager.GetObject("kaboom", resourceCulture)
Return CType(obj,System.Drawing.Bitmap)
End Get
End Property
If you keep a reference to one object, it will be equal to true. It might also be faster since it doesn't need to create a new object.
Dim kaboom As Image = My.Resources.kaboom
Dim images(4, 4) As Image
For rows = 0 To 4
For columns = 0 To 4
images(rows, columns) = kaboom
Next
Next
MessageBox.Show(images(3, 3).Equals(kaboom))
Maybe you are already planning on doing this but here is a suggestion. If you are creating some sort of game, separate the display from the game logic. This mean, save the type of tile instead of the image and compare that. Later, you can add a bunch of different properties to a tile.
Const TYPE_KABOOM As Integer = 1
Dim tileType(4, 4) As Integer
For rows = 0 To 4
For columns = 0 To 4
tileType(rows, columns) = TYPE_KABOOM
Next
Next
MessageBox.Show(tileType(3, 3).Equals(TYPE_KABOOM))

iTextsharp - draw a line at the end and start of a page with tables

Selecting records from a table I create iTextsharp's Tables one for every first letter of the records
On the picture a table for the "G" letter:
"G" is a row of 6 cells
Then a row of 6 cells with the "headers"
and then rows with records
The cells of the rows only need left and right border.
But I need to draw or "close" the line for the last row of the page and also draw or "open" the line of the first row of the next page.
I read a lot of post but I can't figure it out the solution
I know how to draw a graphic line and how to find the coords or how to set bottom or top border, but I don´t know how to detect the page break or if I can manage this situation with forced footers or headers only on cases like the one of the picture.
The code of the class adapated to VB
Thanks to COeDev for the support
Now I only need to resolve the Rectangle (or draw a line) because is not the same on VB.NET (Lines marked as comment)
Imports iTextSharp.text.pdf
Public Class LineaBottom
Implements IPdfPTableEvent
Public Sub TableLayout(table As PdfPTable, widths As Single()(), heights() As Single, headerRows As Integer, rowStart As Integer, canvases() As PdfContentByte) Implements IPdfPTableEvent.TableLayout
'Throw New NotImplementedException()
Dim columns As Integer
Dim rect As Rectangle
Dim footer As Integer = widths.Length - table.FooterRows
Dim header As Integer = table.HeaderRows - table.FooterRows + 1
Dim ultima As Integer = footer - 1
If ultima <> -1 Then
columns = widths(ultima).Length - 1
rect = New Rectangle(widths(ultima)(0), heights(ultima), widths(footer - 1)(columns), heights(ultima + 1))
'rect.BorderColor = BaseColor.BLACK
'rect.BorderWidth = 1
'rect.Border = Rectangle.TOP_BORDER
'canvases(PdfPTable.BASECANVAS).Rectangle(rect)
End If
End Sub
I hope this code will serve other people because there is not much information on the Internet
This should be helpful for you: itextsharp: how to show the bottom line of a table with property HeaderRows=1 if border bottom of the row is not set?
You will need to add some code to draw an additional header line, too
e.g.:
columns = widths[0].Length - 1;
rect = new Rectangle(widths[0][0], heights[0], widths[0][columns], heights[0]);
rect.BorderColor = Color.BLACK;
rect.BorderWidth = 1;
rect.Border = Rectangle.TOP_BORDER;
canvases[PdfPTable.BASECANVAS].Rectangle(rect);
4.1.6.0
I found the solution, no new class required
Dim heightActualLetter, verticalSpaceAvailable As Integer
heightActualLetter = table.TotalHeight
verticalSpaceAvailable = pdfWrite.GetVerticalPosition(False) - pdfDoc.BottomMargin
If heightActualLetter > verticalSpaceAvailable Then
Dim finalLine As PdfContentByte
finalLine = pdfWrite.DirectContent
Dim curY As Int32
curY = pdfWrite.GetVerticalPosition(False)
finalLine.SetLineWidth(0.5)
finalLine.MoveTo(xStart, curY)
finalLine.LineTo(xEnd + 1, curY)
finalLine.Stroke()
End If
I don´t know why I need the +1 on xEnd + 1 but maybe is because of the other lines being 0.5 I need to rounded up

Changing the Color of the Rows of a Form Based on Values Stored in a Table

Working with an Access based application. Need to change the color of some specific rows of a form (the color of "one" field per row needs to be changed) based on values stored in these fields. For instance, when we open the form, we need to see color green in the field of a certain row where we have the value 1. If the value of this field is 2, we need to see color orange and if it is 3 it is red.
Example of the output of the form
ID Criteria
201 1 --> the cell containing 1 should be colored in green
203 3 --> the cell containing 3 should be colored in red
204 3
205 --> the cell that contains nothing should be kept uncolored
206 1
207 2
Note: the values (1, 2 and 3) are already available when the form opens and they are also stored in a table.
To solve the issue I used conditional formatting
(I am using Microsoft Office Access 2007).
Below is the corresponding code.
Option Compare Database
Option Explicit
Const GreenG As Byte = 1
Const OrangeO As Byte = 2
Const RedR As Byte = 3
Private Sub StartCondFormatting()
Dim objFrc As FormatCondition
Const orange As Long = 42495
Const green As Long = 25600
Const red As Long = 255
Dim ctl As Control
For Each ctl In Me.Controls
If ctl.Tag = "Conditional" Then
With ctl
'Remove format conditions
.FormatConditions.Delete
'Create three format objects and add them to the FormatConditions
Set objFrc = .FormatConditions.Add(acExpression, acEqual, "[fieldName] = " & GreenG)
Set objFrc = .FormatConditions.Add(acExpression, acEqual, "[fieldName] = " & OrangeO)
Set objFrc = .FormatConditions.Add(acExpression, acEqual, "[fieldName] = " & RedR)
'Specify the formating conditions
.FormatConditions(0).BackColor = green
.FormatConditions(0).Enabled = True
.FormatConditions(1).BackColor = orange
.FormatConditions(1).Enabled = True
.FormatConditions(2).BackColor = red
.FormatConditions(2).Enabled = True
End With
End If
Next ctl
Set objFrc = Nothing
End Sub
Private Sub Form_Load()
StartCondFormatting
End Sub
For more information on conditional formatting.

Multi Select List Box

I have a list box on a form and it works fine for what I want to do.
I am wanting to edit items on the form, this means populating the listbox and then selecting the relevant items.
My listbox contains a list of item sizes, i want to select the sizes which belong to the item being edited.
PLease can someone give me some pointers.
I tried me.lstItemSizes.SetSelected(i,true) but this only works for a single item.
Any help wil be much appreciated.
My Code:
Private Sub SelectItemSizes(ByVal itemID As Integer)
Dim itemSizes As IList(Of ItemSize) = _sizeLogic.GetItemSizes(itemID)
Me.lstItemSizes.SelectionMode = SelectionMode.MultiExtended
If (itemSizes.Count > 0) Then
For i As Integer = 0 To Me.lstItemSizes.Items.Count - 1
For x As Integer = 0 To itemSizes.Count - 1
If (CType(Me.lstItemSizes.Items(i), PosSize).SizeID = itemSizes(x).SizeID) Then
Me.lstItemSizes.SetSelected(i, True)
Else
Me.lstItemSizes.SetSelected(i, False)
End If
Next
Next
End If
End Sub
Did you set the selectionmode to multi?
You need to specify that in order to allow multiple selections.
Then you can do:
Dim i as Integer=0
For i=0 To Me.listBox.SelectedItems.Count -1
'display the listbox value
next i
Here is a screen shot:
After you set the property on the listbox then call setselected based on the values you want selected.
me.lstItemSizes.SetSelected(3,true)
me.lstItemSizes.SetSelected(4,true)
me.lstItemSizes.SetSelected(9,true)
Here you can add 20 numbers and only select the even.
Dim i As Integer
'load the list with 20 numbers
For i = 0 To 20
Me.ListBox1.Items.Add(i)
Next
'now use setselected
'assume only even are selected
For i = 0 To 20
If i Mod 2 = 0 Then
Me.ListBox1.SetSelected(i, True)
End If
Next
3rd edit
Look at the way you are looping, lets assume I create a list of integers, my vb.net is rusty I mainly develop in C#. But assume you did this:
Dim l As New List(Of Integer)
l.Add(2)
l.Add(6)
l.Add(20)
You only have three items in your list, so first loop based on the items on your list, then within the items in your listbox, you have it vice versa. Look at this:
Dim i As Integer
Dim l As New List(Of Integer)
l.Add(2)
l.Add(6)
l.Add(20)
'load the list with 20 numbers
For i = 0 To 20
Me.ListBox1.Items.Add(i)
Next
Dim lCount As Integer = 0
For lCount = 0 To l.Count - 1
For i = 0 To 20
If i = l.Item(lCount) Then
Me.ListBox1.SetSelected(i, True)
Exit For
End If
Next
Next
In the code my l is a list of just 3 items: 2, 6, and 20.
I add these items to l which is just a list object.
So now I have to loop using these 3 numbers and compare with my listbox. You have it the opposite you are looping on your listbox and then taking into account the list object.
Notice in my for loop that once the item in my list is found I no longer need to loop so I exit for. This ensures I dont overdue the amount of looping required. Once the item is found get out and go back to the count of your list object count.
After running my code here is the result
You have to change the ListBox.SelectionMode property in order to enable multiple-selection.
The possible values are given by the SelectionMode enum, as follows:
None: No items can be selected
One: Only one item can be selected
MultiSimple: Multiple items can be selected
MultiExtended: Multiple items can be selected, and the user can use the Shift, Ctrl, and arrow keys to make selections
So, you simply need to add the following line to the code you already have:
' Change the selection mode (you could also use MultiExtended here)
lstItemSizes.SelectionMode = SelectionMode.MultiSimple;
' Select any items of your choice
lstItemSizes.SetSelected(1, True)
lstItemSizes.SetSelected(3, True)
lstItemSizes.SetSelected(8, True)
Alternatively, you can set the SelectionMode property at design time, instead of doing it with code.
According to MSDN, SetSelected() can be used to select multiple items. Simply repeat the call for each item that needs to be selected. This is the example they use:
' Select three items from the ListBox.
listBox1.SetSelected(1, True)
listBox1.SetSelected(3, True)
listBox1.SetSelected(5, True)
For reference, this is the MSDN article.
Because my code had the following loops:
For i As Integer = 0 To Me.lstItemSizes.Items.Count - 1
For x As Integer = 0 To itemSizes.Count - 1
If (CType(Me.lstItemSizes.Items(i), PosSize).SizeID = itemSizes(x).SizeID) Then
Me.lstItemSizes.SetSelected(i, True)
Else
Me.lstItemSizes.SetSelected(i, False)
End If
Next
Next
The first loop loops through the available sizes and the second loop is used to compare the item sizes.
Having the following code:
Else
Me.lstItemSizes.SetSelected(i, False)
End If
Meant that even if item i became selected, it could also be deselected.
SOLUTION:
Remove Me.lstItemSizes.SetSelected(i, False) OR Include Exit For